1// Copyright 2013-2014 The Rust Project Developers.
2// Copyright 2018 The Uuid Project Developers.
3//
4// See the COPYRIGHT file at the top-level directory of this distribution.
5//
6// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
7// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
9// option. This file may not be copied, modified, or distributed
10// except according to those terms.
11
12//! Generate and parse universally unique identifiers (UUIDs).
13//!
14//! Here's an example of a UUID:
15//!
16//! ```text
17//! 67e55044-10b1-426f-9247-bb680e5fe0c8
18//! ```
19//!
20//! A UUID is a unique 128-bit value, stored as 16 octets, and regularly
21//! formatted as a hex string in five groups. UUIDs are used to assign unique
22//! identifiers to entities without requiring a central allocating authority.
23//!
24//! They are particularly useful in distributed systems, though can be used in
25//! disparate areas, such as databases and network protocols. Typically a UUID
26//! is displayed in a readable string form as a sequence of hexadecimal digits,
27//! separated into groups by hyphens.
28//!
29//! The uniqueness property is not strictly guaranteed, however for all
30//! practical purposes, it can be assumed that an unintentional collision would
31//! be extremely unlikely.
32//!
33//! UUIDs have a number of standardized encodings that are specified in [RFC4122](http://tools.ietf.org/html/rfc4122),
34//! with recent additions [in draft](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04).
35//!
36//! # Getting started
37//!
38//! Add the following to your `Cargo.toml`:
39//!
40//! ```toml
41//! [dependencies.uuid]
42//! version = "1.4.0"
43//! features = [
44//! "v4", # Lets you generate random UUIDs
45//! "fast-rng", # Use a faster (but still sufficiently random) RNG
46//! "macro-diagnostics", # Enable better diagnostics for compile-time UUIDs
47//! ]
48//! ```
49//!
50//! When you want a UUID, you can generate one:
51//!
52//! ```
53//! # fn main() {
54//! # #[cfg(feature = "v4")]
55//! # {
56//! use uuid::Uuid;
57//!
58//! let id = Uuid::new_v4();
59//! # }
60//! # }
61//! ```
62//!
63//! If you have a UUID value, you can use its string literal form inline:
64//!
65//! ```
66//! use uuid::{uuid, Uuid};
67//!
68//! const ID: Uuid = uuid!("67e55044-10b1-426f-9247-bb680e5fe0c8");
69//! ```
70//!
71//! # Working with different UUID versions
72//!
73//! This library supports all standardized methods for generating UUIDs through individual Cargo features.
74//!
75//! By default, this crate depends on nothing but the Rust standard library and can parse and format
76//! UUIDs, but cannot generate them. Depending on the kind of UUID you'd like to work with, there
77//! are Cargo features that enable generating them:
78//!
79//! * `v1` - Version 1 UUIDs using a timestamp and monotonic counter.
80//! * `v3` - Version 3 UUIDs based on the MD5 hash of some data.
81//! * `v4` - Version 4 UUIDs with random data.
82//! * `v5` - Version 5 UUIDs based on the SHA1 hash of some data.
83//!
84//! Versions that are in draft are also supported. See the _unstable features_ section for details.
85//!
86//! This library also includes a [`Builder`] type that can be used to help construct UUIDs of any
87//! version without any additional dependencies or features. It's a lower-level API than [`Uuid`]
88//! that can be used when you need control over implicit requirements on things like a source
89//! of randomness.
90//!
91//! ## Which UUID version should I use?
92//!
93//! If you just want to generate unique identifiers then consider version 4 (`v4`) UUIDs. If you want
94//! to use UUIDs as database keys or need to sort them then consider version 7 (`v7`) UUIDs.
95//! Other versions should generally be avoided unless there's an existing need for them.
96//!
97//! Some UUID versions supersede others. Prefer version 6 over version 1 and version 5 over version 3.
98//!
99//! # Other features
100//!
101//! Other crate features can also be useful beyond the version support:
102//!
103//! * `macro-diagnostics` - enhances the diagnostics of `uuid!` macro.
104//! * `serde` - adds the ability to serialize and deserialize a UUID using
105//! `serde`.
106//! * `arbitrary` - adds an `Arbitrary` trait implementation to `Uuid` for
107//! fuzzing.
108//! * `fast-rng` - uses a faster algorithm for generating random UUIDs.
109//! This feature requires more dependencies to compile, but is just as suitable for
110//! UUIDs as the default algorithm.
111//!
112//! # Unstable features
113//!
114//! Some features are unstable. They may be incomplete or depend on other
115//! unstable libraries. These include:
116//!
117//! * `v6` - Version 6 UUIDs using a timestamp and monotonic counter.
118//! * `v7` - Version 7 UUIDs using a Unix timestamp.
119//! * `v8` - Version 8 UUIDs using user-defined data.
120//! * `zerocopy` - adds support for zero-copy deserialization using the
121//! `zerocopy` library.
122//! * `borsh` - adds the ability to serialize and deserialize a UUID using
123//! `borsh`.
124//!
125//! Unstable features may break between minor releases.
126//!
127//! To allow unstable features, you'll need to enable the Cargo feature as
128//! normal, but also pass an additional flag through your environment to opt-in
129//! to unstable `uuid` features:
130//!
131//! ```text
132//! RUSTFLAGS="--cfg uuid_unstable"
133//! ```
134//!
135//! # Building for other targets
136//!
137//! ## WebAssembly
138//!
139//! For WebAssembly, enable the `js` feature:
140//!
141//! ```toml
142//! [dependencies.uuid]
143//! version = "1.4.0"
144//! features = [
145//! "v4",
146//! "v7",
147//! "js",
148//! ]
149//! ```
150//!
151//! ## Embedded
152//!
153//! For embedded targets without the standard library, you'll need to
154//! disable default features when building `uuid`:
155//!
156//! ```toml
157//! [dependencies.uuid]
158//! version = "1.4.0"
159//! default-features = false
160//! ```
161//!
162//! Some additional features are supported in no-std environments:
163//!
164//! * `v1`, `v3`, `v5`, `v6`, and `v8`.
165//! * `serde`.
166//!
167//! If you need to use `v4` or `v7` in a no-std environment, you'll need to
168//! follow [`getrandom`'s docs] on configuring a source of randomness
169//! on currently unsupported targets. Alternatively, you can produce
170//! random bytes yourself and then pass them to [`Builder::from_random_bytes`]
171//! without enabling the `v4` feature.
172//!
173//! # Examples
174//!
175//! Parse a UUID given in the simple format and print it as a URN:
176//!
177//! ```
178//! # use uuid::Uuid;
179//! # fn main() -> Result<(), uuid::Error> {
180//! let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
181//!
182//! println!("{}", my_uuid.urn());
183//! # Ok(())
184//! # }
185//! ```
186//!
187//! Generate a random UUID and print it out in hexadecimal form:
188//!
189//! ```
190//! // Note that this requires the `v4` feature to be enabled.
191//! # use uuid::Uuid;
192//! # fn main() {
193//! # #[cfg(feature = "v4")] {
194//! let my_uuid = Uuid::new_v4();
195//!
196//! println!("{}", my_uuid);
197//! # }
198//! # }
199//! ```
200//!
201//! # References
202//!
203//! * [Wikipedia: Universally Unique Identifier](http://en.wikipedia.org/wiki/Universally_unique_identifier)
204//! * [RFC4122: A Universally Unique Identifier (UUID) URN Namespace](http://tools.ietf.org/html/rfc4122)
205//! * [Draft RFC: New UUID Formats, Version 4](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04)
206//!
207//! [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
208//! [`cargo-web`]: https://crates.io/crates/cargo-web
209//! [`getrandom`'s docs]: https://docs.rs/getrandom
210
211#![no_std]
212#![deny(missing_debug_implementations, missing_docs)]
213#![doc(
214 html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
215 html_favicon_url = "https://www.rust-lang.org/favicon.ico",
216 html_root_url = "https://docs.rs/uuid/1.4.0"
217)]
218
219#[cfg(any(feature = "std", test))]
220#[macro_use]
221extern crate std;
222
223#[cfg(all(not(feature = "std"), not(test)))]
224#[macro_use]
225extern crate core as std;
226
227#[cfg(all(uuid_unstable, feature = "zerocopy"))]
228use zerocopy::{AsBytes, FromBytes, Unaligned};
229
230mod builder;
231mod error;
232mod parser;
233
234pub mod fmt;
235pub mod timestamp;
236
237pub use timestamp::{context::NoContext, ClockSequence, Timestamp};
238
239#[cfg(any(feature = "v1", feature = "v6"))]
240pub use timestamp::context::Context;
241
242#[cfg(feature = "v1")]
243#[doc(hidden)]
244// Soft-deprecated (Rust doesn't support deprecating re-exports)
245// Use `Context` from the crate root instead
246pub mod v1;
247#[cfg(feature = "v3")]
248mod v3;
249#[cfg(feature = "v4")]
250mod v4;
251#[cfg(feature = "v5")]
252mod v5;
253#[cfg(all(uuid_unstable, feature = "v6"))]
254mod v6;
255#[cfg(all(uuid_unstable, feature = "v7"))]
256mod v7;
257#[cfg(all(uuid_unstable, feature = "v8"))]
258mod v8;
259
260#[cfg(feature = "md5")]
261mod md5;
262#[cfg(feature = "rng")]
263mod rng;
264#[cfg(feature = "sha1")]
265mod sha1;
266
267mod external;
268
269#[macro_use]
270mod macros;
271
272#[doc(hidden)]
273#[cfg(feature = "macro-diagnostics")]
274pub extern crate uuid_macro_internal;
275
276use crate::std::convert;
277
278pub use crate::{builder::Builder, error::Error};
279
280/// A 128-bit (16 byte) buffer containing the UUID.
281///
282/// # ABI
283///
284/// The `Bytes` type is always guaranteed to be have the same ABI as [`Uuid`].
285pub type Bytes = [u8; 16];
286
287/// The version of the UUID, denoting the generating algorithm.
288///
289/// # References
290///
291/// * [Version in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.3)
292#[derive(Clone, Copy, Debug, PartialEq)]
293#[non_exhaustive]
294#[repr(u8)]
295pub enum Version {
296 /// The "nil" (all zeros) UUID.
297 Nil = 0u8,
298 /// Version 1: Timestamp and node ID.
299 Mac = 1,
300 /// Version 2: DCE Security.
301 Dce = 2,
302 /// Version 3: MD5 hash.
303 Md5 = 3,
304 /// Version 4: Random.
305 Random = 4,
306 /// Version 5: SHA-1 hash.
307 Sha1 = 5,
308 /// Version 6: Sortable Timestamp and node ID.
309 #[cfg(uuid_unstable)]
310 SortMac = 6,
311 /// Version 7: Timestamp and random.
312 #[cfg(uuid_unstable)]
313 SortRand = 7,
314 /// Version 8: Custom.
315 #[cfg(uuid_unstable)]
316 Custom = 8,
317 /// The "max" (all ones) UUID.
318 #[cfg(uuid_unstable)]
319 Max = 0xff,
320}
321
322/// The reserved variants of UUIDs.
323///
324/// # References
325///
326/// * [Variant in RFC4122](http://tools.ietf.org/html/rfc4122#section-4.1.1)
327#[derive(Clone, Copy, Debug, PartialEq)]
328#[non_exhaustive]
329#[repr(u8)]
330pub enum Variant {
331 /// Reserved by the NCS for backward compatibility.
332 NCS = 0u8,
333 /// As described in the RFC4122 Specification (default).
334 RFC4122,
335 /// Reserved by Microsoft for backward compatibility.
336 Microsoft,
337 /// Reserved for future expansion.
338 Future,
339}
340
341/// A Universally Unique Identifier (UUID).
342///
343/// # Examples
344///
345/// Parse a UUID given in the simple format and print it as a urn:
346///
347/// ```
348/// # use uuid::Uuid;
349/// # fn main() -> Result<(), uuid::Error> {
350/// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
351///
352/// println!("{}", my_uuid.urn());
353/// # Ok(())
354/// # }
355/// ```
356///
357/// Create a new random (V4) UUID and print it out in hexadecimal form:
358///
359/// ```
360/// // Note that this requires the `v4` feature enabled in the uuid crate.
361/// # use uuid::Uuid;
362/// # fn main() {
363/// # #[cfg(feature = "v4")] {
364/// let my_uuid = Uuid::new_v4();
365///
366/// println!("{}", my_uuid);
367/// # }
368/// # }
369/// ```
370///
371/// # Formatting
372///
373/// A UUID can be formatted in one of a few ways:
374///
375/// * [`simple`](#method.simple): `a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8`.
376/// * [`hyphenated`](#method.hyphenated):
377/// `a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8`.
378/// * [`urn`](#method.urn): `urn:uuid:A1A2A3A4-B1B2-C1C2-D1D2-D3D4D5D6D7D8`.
379/// * [`braced`](#method.braced): `{a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8}`.
380///
381/// The default representation when formatting a UUID with `Display` is
382/// hyphenated:
383///
384/// ```
385/// # use uuid::Uuid;
386/// # fn main() -> Result<(), uuid::Error> {
387/// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
388///
389/// assert_eq!(
390/// "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
391/// my_uuid.to_string(),
392/// );
393/// # Ok(())
394/// # }
395/// ```
396///
397/// Other formats can be specified using adapter methods on the UUID:
398///
399/// ```
400/// # use uuid::Uuid;
401/// # fn main() -> Result<(), uuid::Error> {
402/// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
403///
404/// assert_eq!(
405/// "urn:uuid:a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
406/// my_uuid.urn().to_string(),
407/// );
408/// # Ok(())
409/// # }
410/// ```
411///
412/// # Endianness
413///
414/// The specification for UUIDs encodes the integer fields that make up the
415/// value in big-endian order. This crate assumes integer inputs are already in
416/// the correct order by default, regardless of the endianness of the
417/// environment. Most methods that accept integers have a `_le` variant (such as
418/// `from_fields_le`) that assumes any integer values will need to have their
419/// bytes flipped, regardless of the endianness of the environment.
420///
421/// Most users won't need to worry about endianness unless they need to operate
422/// on individual fields (such as when converting between Microsoft GUIDs). The
423/// important things to remember are:
424///
425/// - The endianness is in terms of the fields of the UUID, not the environment.
426/// - The endianness is assumed to be big-endian when there's no `_le` suffix
427/// somewhere.
428/// - Byte-flipping in `_le` methods applies to each integer.
429/// - Endianness roundtrips, so if you create a UUID with `from_fields_le`
430/// you'll get the same values back out with `to_fields_le`.
431///
432/// # ABI
433///
434/// The `Uuid` type is always guaranteed to be have the same ABI as [`Bytes`].
435#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
436#[cfg_attr(
437 all(uuid_unstable, feature = "zerocopy"),
438 derive(AsBytes, FromBytes, Unaligned)
439)]
440#[cfg_attr(
441 all(uuid_unstable, feature = "borsh"),
442 derive(borsh::BorshDeserialize, borsh::BorshSerialize)
443)]
444#[repr(transparent)]
445pub struct Uuid(Bytes);
446
447impl Uuid {
448 /// UUID namespace for Domain Name System (DNS).
449 pub const NAMESPACE_DNS: Self = Uuid([
450 0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
451 0xc8,
452 ]);
453
454 /// UUID namespace for ISO Object Identifiers (OIDs).
455 pub const NAMESPACE_OID: Self = Uuid([
456 0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
457 0xc8,
458 ]);
459
460 /// UUID namespace for Uniform Resource Locators (URLs).
461 pub const NAMESPACE_URL: Self = Uuid([
462 0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
463 0xc8,
464 ]);
465
466 /// UUID namespace for X.500 Distinguished Names (DNs).
467 pub const NAMESPACE_X500: Self = Uuid([
468 0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
469 0xc8,
470 ]);
471
472 /// Returns the variant of the UUID structure.
473 ///
474 /// This determines the interpretation of the structure of the UUID.
475 /// This method simply reads the value of the variant byte. It doesn't
476 /// validate the rest of the UUID as conforming to that variant.
477 ///
478 /// # Examples
479 ///
480 /// Basic usage:
481 ///
482 /// ```
483 /// # use uuid::{Uuid, Variant};
484 /// # fn main() -> Result<(), uuid::Error> {
485 /// let my_uuid = Uuid::parse_str("02f09a3f-1624-3b1d-8409-44eff7708208")?;
486 ///
487 /// assert_eq!(Variant::RFC4122, my_uuid.get_variant());
488 /// # Ok(())
489 /// # }
490 /// ```
491 ///
492 /// # References
493 ///
494 /// * [Variant in RFC4122](http://tools.ietf.org/html/rfc4122#section-4.1.1)
495 pub const fn get_variant(&self) -> Variant {
496 match self.as_bytes()[8] {
497 x if x & 0x80 == 0x00 => Variant::NCS,
498 x if x & 0xc0 == 0x80 => Variant::RFC4122,
499 x if x & 0xe0 == 0xc0 => Variant::Microsoft,
500 x if x & 0xe0 == 0xe0 => Variant::Future,
501 // The above match arms are actually exhaustive
502 // We just return `Future` here because we can't
503 // use `unreachable!()` in a `const fn`
504 _ => Variant::Future,
505 }
506 }
507
508 /// Returns the version number of the UUID.
509 ///
510 /// This represents the algorithm used to generate the value.
511 /// This method is the future-proof alternative to [`Uuid::get_version`].
512 ///
513 /// # Examples
514 ///
515 /// Basic usage:
516 ///
517 /// ```
518 /// # use uuid::Uuid;
519 /// # fn main() -> Result<(), uuid::Error> {
520 /// let my_uuid = Uuid::parse_str("02f09a3f-1624-3b1d-8409-44eff7708208")?;
521 ///
522 /// assert_eq!(3, my_uuid.get_version_num());
523 /// # Ok(())
524 /// # }
525 /// ```
526 ///
527 /// # References
528 ///
529 /// * [Version in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.3)
530 pub const fn get_version_num(&self) -> usize {
531 (self.as_bytes()[6] >> 4) as usize
532 }
533
534 /// Returns the version of the UUID.
535 ///
536 /// This represents the algorithm used to generate the value.
537 /// If the version field doesn't contain a recognized version then `None`
538 /// is returned. If you're trying to read the version for a future extension
539 /// you can also use [`Uuid::get_version_num`] to unconditionally return a
540 /// number. Future extensions may start to return `Some` once they're
541 /// standardized and supported.
542 ///
543 /// # Examples
544 ///
545 /// Basic usage:
546 ///
547 /// ```
548 /// # use uuid::{Uuid, Version};
549 /// # fn main() -> Result<(), uuid::Error> {
550 /// let my_uuid = Uuid::parse_str("02f09a3f-1624-3b1d-8409-44eff7708208")?;
551 ///
552 /// assert_eq!(Some(Version::Md5), my_uuid.get_version());
553 /// # Ok(())
554 /// # }
555 /// ```
556 ///
557 /// # References
558 ///
559 /// * [Version in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.3)
560 pub const fn get_version(&self) -> Option<Version> {
561 match self.get_version_num() {
562 0 if self.is_nil() => Some(Version::Nil),
563 1 => Some(Version::Mac),
564 2 => Some(Version::Dce),
565 3 => Some(Version::Md5),
566 4 => Some(Version::Random),
567 5 => Some(Version::Sha1),
568 #[cfg(uuid_unstable)]
569 6 => Some(Version::SortMac),
570 #[cfg(uuid_unstable)]
571 7 => Some(Version::SortRand),
572 #[cfg(uuid_unstable)]
573 8 => Some(Version::Custom),
574 #[cfg(uuid_unstable)]
575 0xf => Some(Version::Max),
576 _ => None,
577 }
578 }
579
580 /// Returns the four field values of the UUID.
581 ///
582 /// These values can be passed to the [`Uuid::from_fields`] method to get
583 /// the original `Uuid` back.
584 ///
585 /// * The first field value represents the first group of (eight) hex
586 /// digits, taken as a big-endian `u32` value. For V1 UUIDs, this field
587 /// represents the low 32 bits of the timestamp.
588 /// * The second field value represents the second group of (four) hex
589 /// digits, taken as a big-endian `u16` value. For V1 UUIDs, this field
590 /// represents the middle 16 bits of the timestamp.
591 /// * The third field value represents the third group of (four) hex digits,
592 /// taken as a big-endian `u16` value. The 4 most significant bits give
593 /// the UUID version, and for V1 UUIDs, the last 12 bits represent the
594 /// high 12 bits of the timestamp.
595 /// * The last field value represents the last two groups of four and twelve
596 /// hex digits, taken in order. The first 1-3 bits of this indicate the
597 /// UUID variant, and for V1 UUIDs, the next 13-15 bits indicate the clock
598 /// sequence and the last 48 bits indicate the node ID.
599 ///
600 /// # Examples
601 ///
602 /// ```
603 /// # use uuid::Uuid;
604 /// # fn main() -> Result<(), uuid::Error> {
605 /// let uuid = Uuid::nil();
606 ///
607 /// assert_eq!(uuid.as_fields(), (0, 0, 0, &[0u8; 8]));
608 ///
609 /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
610 ///
611 /// assert_eq!(
612 /// uuid.as_fields(),
613 /// (
614 /// 0xa1a2a3a4,
615 /// 0xb1b2,
616 /// 0xc1c2,
617 /// &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8],
618 /// )
619 /// );
620 /// # Ok(())
621 /// # }
622 /// ```
623 pub fn as_fields(&self) -> (u32, u16, u16, &[u8; 8]) {
624 let bytes = self.as_bytes();
625
626 let d1 = (bytes[0] as u32) << 24
627 | (bytes[1] as u32) << 16
628 | (bytes[2] as u32) << 8
629 | (bytes[3] as u32);
630
631 let d2 = (bytes[4] as u16) << 8 | (bytes[5] as u16);
632
633 let d3 = (bytes[6] as u16) << 8 | (bytes[7] as u16);
634
635 let d4: &[u8; 8] = convert::TryInto::try_into(&bytes[8..16]).unwrap();
636 (d1, d2, d3, d4)
637 }
638
639 /// Returns the four field values of the UUID in little-endian order.
640 ///
641 /// The bytes in the returned integer fields will be converted from
642 /// big-endian order. This is based on the endianness of the UUID,
643 /// rather than the target environment so bytes will be flipped on both
644 /// big and little endian machines.
645 ///
646 /// # Examples
647 ///
648 /// ```
649 /// use uuid::Uuid;
650 ///
651 /// # fn main() -> Result<(), uuid::Error> {
652 /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
653 ///
654 /// assert_eq!(
655 /// uuid.to_fields_le(),
656 /// (
657 /// 0xa4a3a2a1,
658 /// 0xb2b1,
659 /// 0xc2c1,
660 /// &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8],
661 /// )
662 /// );
663 /// # Ok(())
664 /// # }
665 /// ```
666 pub fn to_fields_le(&self) -> (u32, u16, u16, &[u8; 8]) {
667 let d1 = (self.as_bytes()[0] as u32)
668 | (self.as_bytes()[1] as u32) << 8
669 | (self.as_bytes()[2] as u32) << 16
670 | (self.as_bytes()[3] as u32) << 24;
671
672 let d2 = (self.as_bytes()[4] as u16) | (self.as_bytes()[5] as u16) << 8;
673
674 let d3 = (self.as_bytes()[6] as u16) | (self.as_bytes()[7] as u16) << 8;
675
676 let d4: &[u8; 8] = convert::TryInto::try_into(&self.as_bytes()[8..16]).unwrap();
677 (d1, d2, d3, d4)
678 }
679
680 /// Returns a 128bit value containing the value.
681 ///
682 /// The bytes in the UUID will be packed directly into a `u128`.
683 ///
684 /// # Examples
685 ///
686 /// ```
687 /// # use uuid::Uuid;
688 /// # fn main() -> Result<(), uuid::Error> {
689 /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
690 ///
691 /// assert_eq!(
692 /// uuid.as_u128(),
693 /// 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8,
694 /// );
695 /// # Ok(())
696 /// # }
697 /// ```
698 pub const fn as_u128(&self) -> u128 {
699 u128::from_be_bytes(*self.as_bytes())
700 }
701
702 /// Returns a 128bit little-endian value containing the value.
703 ///
704 /// The bytes in the `u128` will be flipped to convert into big-endian
705 /// order. This is based on the endianness of the UUID, rather than the
706 /// target environment so bytes will be flipped on both big and little
707 /// endian machines.
708 ///
709 /// Note that this will produce a different result than
710 /// [`Uuid::to_fields_le`], because the entire UUID is reversed, rather
711 /// than reversing the individual fields in-place.
712 ///
713 /// # Examples
714 ///
715 /// ```
716 /// # use uuid::Uuid;
717 /// # fn main() -> Result<(), uuid::Error> {
718 /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
719 ///
720 /// assert_eq!(
721 /// uuid.to_u128_le(),
722 /// 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1,
723 /// );
724 /// # Ok(())
725 /// # }
726 /// ```
727 pub const fn to_u128_le(&self) -> u128 {
728 u128::from_le_bytes(*self.as_bytes())
729 }
730
731 /// Returns two 64bit values containing the value.
732 ///
733 /// The bytes in the UUID will be split into two `u64`.
734 /// The first u64 represents the 64 most significant bits,
735 /// the second one represents the 64 least significant.
736 ///
737 /// # Examples
738 ///
739 /// ```
740 /// # use uuid::Uuid;
741 /// # fn main() -> Result<(), uuid::Error> {
742 /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
743 /// assert_eq!(
744 /// uuid.as_u64_pair(),
745 /// (0xa1a2a3a4b1b2c1c2, 0xd1d2d3d4d5d6d7d8),
746 /// );
747 /// # Ok(())
748 /// # }
749 /// ```
750 pub const fn as_u64_pair(&self) -> (u64, u64) {
751 let value = self.as_u128();
752 ((value >> 64) as u64, value as u64)
753 }
754
755 /// Returns a slice of 16 octets containing the value.
756 ///
757 /// This method borrows the underlying byte value of the UUID.
758 ///
759 /// # Examples
760 ///
761 /// ```
762 /// # use uuid::Uuid;
763 /// let bytes1 = [
764 /// 0xa1, 0xa2, 0xa3, 0xa4,
765 /// 0xb1, 0xb2,
766 /// 0xc1, 0xc2,
767 /// 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
768 /// ];
769 /// let uuid1 = Uuid::from_bytes_ref(&bytes1);
770 ///
771 /// let bytes2 = uuid1.as_bytes();
772 /// let uuid2 = Uuid::from_bytes_ref(bytes2);
773 ///
774 /// assert_eq!(uuid1, uuid2);
775 ///
776 /// assert!(std::ptr::eq(
777 /// uuid2 as *const Uuid as *const u8,
778 /// &bytes1 as *const [u8; 16] as *const u8,
779 /// ));
780 /// ```
781 pub const fn as_bytes(&self) -> &Bytes {
782 &self.0
783 }
784
785 /// Consumes self and returns the underlying byte value of the UUID.
786 ///
787 /// # Examples
788 ///
789 /// ```
790 /// # use uuid::Uuid;
791 /// let bytes = [
792 /// 0xa1, 0xa2, 0xa3, 0xa4,
793 /// 0xb1, 0xb2,
794 /// 0xc1, 0xc2,
795 /// 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
796 /// ];
797 /// let uuid = Uuid::from_bytes(bytes);
798 /// assert_eq!(bytes, uuid.into_bytes());
799 /// ```
800 pub const fn into_bytes(self) -> Bytes {
801 self.0
802 }
803
804 /// Returns the bytes of the UUID in little-endian order.
805 ///
806 /// The bytes will be flipped to convert into little-endian order. This is
807 /// based on the endianness of the UUID, rather than the target environment
808 /// so bytes will be flipped on both big and little endian machines.
809 ///
810 /// # Examples
811 ///
812 /// ```
813 /// use uuid::Uuid;
814 ///
815 /// # fn main() -> Result<(), uuid::Error> {
816 /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
817 ///
818 /// assert_eq!(
819 /// uuid.to_bytes_le(),
820 /// ([
821 /// 0xa4, 0xa3, 0xa2, 0xa1, 0xb2, 0xb1, 0xc2, 0xc1, 0xd1, 0xd2,
822 /// 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8
823 /// ])
824 /// );
825 /// # Ok(())
826 /// # }
827 /// ```
828 pub const fn to_bytes_le(&self) -> Bytes {
829 [
830 self.0[3], self.0[2], self.0[1], self.0[0], self.0[5], self.0[4], self.0[7], self.0[6],
831 self.0[8], self.0[9], self.0[10], self.0[11], self.0[12], self.0[13], self.0[14],
832 self.0[15],
833 ]
834 }
835
836 /// Tests if the UUID is nil (all zeros).
837 pub const fn is_nil(&self) -> bool {
838 self.as_u128() == u128::MIN
839 }
840
841 /// Tests if the UUID is max (all ones).
842 #[cfg(uuid_unstable)]
843 pub const fn is_max(&self) -> bool {
844 self.as_u128() == u128::MAX
845 }
846
847 /// A buffer that can be used for `encode_...` calls, that is
848 /// guaranteed to be long enough for any of the format adapters.
849 ///
850 /// # Examples
851 ///
852 /// ```
853 /// # use uuid::Uuid;
854 /// let uuid = Uuid::nil();
855 ///
856 /// assert_eq!(
857 /// uuid.simple().encode_lower(&mut Uuid::encode_buffer()),
858 /// "00000000000000000000000000000000"
859 /// );
860 ///
861 /// assert_eq!(
862 /// uuid.hyphenated()
863 /// .encode_lower(&mut Uuid::encode_buffer()),
864 /// "00000000-0000-0000-0000-000000000000"
865 /// );
866 ///
867 /// assert_eq!(
868 /// uuid.urn().encode_lower(&mut Uuid::encode_buffer()),
869 /// "urn:uuid:00000000-0000-0000-0000-000000000000"
870 /// );
871 /// ```
872 pub const fn encode_buffer() -> [u8; fmt::Urn::LENGTH] {
873 [0; fmt::Urn::LENGTH]
874 }
875
876 /// If the UUID is the correct version (v1, v6, or v7) this will return
877 /// the timestamp and counter portion parsed from a V1 UUID.
878 ///
879 /// Returns `None` if the supplied UUID is not V1.
880 ///
881 /// The V1 timestamp format defined in RFC4122 specifies a 60-bit
882 /// integer representing the number of 100-nanosecond intervals
883 /// since 00:00:00.00, 15 Oct 1582.
884 ///
885 /// [`Timestamp`] offers several options for converting the raw RFC4122
886 /// value into more commonly-used formats, such as a unix timestamp.
887 ///
888 /// # Roundtripping
889 ///
890 /// This method is unlikely to roundtrip a timestamp in a UUID due to the way
891 /// UUIDs encode timestamps. The timestamp returned from this method will be truncated to
892 /// 100ns precision for version 1 and 6 UUIDs, and to millisecond precision for version 7 UUIDs.
893 ///
894 /// [`Timestamp`]: v1/struct.Timestamp.html
895 pub const fn get_timestamp(&self) -> Option<Timestamp> {
896 match self.get_version() {
897 Some(Version::Mac) => {
898 let (ticks, counter) = timestamp::decode_rfc4122_timestamp(self);
899
900 Some(Timestamp::from_rfc4122(ticks, counter))
901 }
902 #[cfg(uuid_unstable)]
903 Some(Version::SortMac) => {
904 let (ticks, counter) = timestamp::decode_sorted_rfc4122_timestamp(self);
905
906 Some(Timestamp::from_rfc4122(ticks, counter))
907 }
908 #[cfg(uuid_unstable)]
909 Some(Version::SortRand) => {
910 let millis = timestamp::decode_unix_timestamp_millis(self);
911
912 let seconds = millis / 1000;
913 let nanos = ((millis % 1000) * 1_000_000) as u32;
914
915 Some(Timestamp {
916 seconds,
917 nanos,
918 #[cfg(any(feature = "v1", feature = "v6"))]
919 counter: 0,
920 })
921 }
922 _ => None,
923 }
924 }
925}
926
927impl Default for Uuid {
928 #[inline]
929 fn default() -> Self {
930 Uuid::nil()
931 }
932}
933
934impl AsRef<[u8]> for Uuid {
935 #[inline]
936 fn as_ref(&self) -> &[u8] {
937 &self.0
938 }
939}
940
941#[cfg(feature = "serde")]
942pub mod serde {
943 //! Adapters for alternative `serde` formats.
944 //!
945 //! This module contains adapters you can use with [`#[serde(with)]`](https://serde.rs/field-attrs.html#with)
946 //! to change the way a [`Uuid`](../struct.Uuid.html) is serialized
947 //! and deserialized.
948
949 pub use crate::external::serde_support::compact;
950}
951
952#[cfg(test)]
953mod tests {
954 use super::*;
955
956 use crate::std::string::{String, ToString};
957
958 #[cfg(all(
959 target_arch = "wasm32",
960 target_vendor = "unknown",
961 target_os = "unknown"
962 ))]
963 use wasm_bindgen_test::*;
964
965 macro_rules! check {
966 ($buf:ident, $format:expr, $target:expr, $len:expr, $cond:expr) => {
967 $buf.clear();
968 write!($buf, $format, $target).unwrap();
969 assert!($buf.len() == $len);
970 assert!($buf.chars().all($cond), "{}", $buf);
971 };
972 }
973
974 pub const fn new() -> Uuid {
975 Uuid::from_bytes([
976 0xF9, 0x16, 0x8C, 0x5E, 0xCE, 0xB2, 0x4F, 0xAA, 0xB6, 0xBF, 0x32, 0x9B, 0xF3, 0x9F,
977 0xA1, 0xE4,
978 ])
979 }
980
981 pub const fn new2() -> Uuid {
982 Uuid::from_bytes([
983 0xF9, 0x16, 0x8C, 0x5E, 0xCE, 0xB2, 0x4F, 0xAB, 0xB6, 0xBF, 0x32, 0x9B, 0xF3, 0x9F,
984 0xA1, 0xE4,
985 ])
986 }
987
988 #[test]
989 #[cfg_attr(
990 all(
991 target_arch = "wasm32",
992 target_vendor = "unknown",
993 target_os = "unknown"
994 ),
995 wasm_bindgen_test
996 )]
997 fn test_uuid_compare() {
998 let uuid1 = new();
999 let uuid2 = new2();
1000
1001 assert_eq!(uuid1, uuid1);
1002 assert_eq!(uuid2, uuid2);
1003
1004 assert_ne!(uuid1, uuid2);
1005 assert_ne!(uuid2, uuid1);
1006 }
1007
1008 #[test]
1009 #[cfg_attr(
1010 all(
1011 target_arch = "wasm32",
1012 target_vendor = "unknown",
1013 target_os = "unknown"
1014 ),
1015 wasm_bindgen_test
1016 )]
1017 fn test_uuid_default() {
1018 let default_uuid = Uuid::default();
1019 let nil_uuid = Uuid::nil();
1020
1021 assert_eq!(default_uuid, nil_uuid);
1022 }
1023
1024 #[test]
1025 #[cfg_attr(
1026 all(
1027 target_arch = "wasm32",
1028 target_vendor = "unknown",
1029 target_os = "unknown"
1030 ),
1031 wasm_bindgen_test
1032 )]
1033 fn test_uuid_display() {
1034 use crate::std::fmt::Write;
1035
1036 let uuid = new();
1037 let s = uuid.to_string();
1038 let mut buffer = String::new();
1039
1040 assert_eq!(s, uuid.hyphenated().to_string());
1041
1042 check!(buffer, "{}", uuid, 36, |c| c.is_lowercase()
1043 || c.is_digit(10)
1044 || c == '-');
1045 }
1046
1047 #[test]
1048 #[cfg_attr(
1049 all(
1050 target_arch = "wasm32",
1051 target_vendor = "unknown",
1052 target_os = "unknown"
1053 ),
1054 wasm_bindgen_test
1055 )]
1056 fn test_uuid_lowerhex() {
1057 use crate::std::fmt::Write;
1058
1059 let mut buffer = String::new();
1060 let uuid = new();
1061
1062 check!(buffer, "{:x}", uuid, 36, |c| c.is_lowercase()
1063 || c.is_digit(10)
1064 || c == '-');
1065 }
1066
1067 // noinspection RsAssertEqual
1068 #[test]
1069 #[cfg_attr(
1070 all(
1071 target_arch = "wasm32",
1072 target_vendor = "unknown",
1073 target_os = "unknown"
1074 ),
1075 wasm_bindgen_test
1076 )]
1077 fn test_uuid_operator_eq() {
1078 let uuid1 = new();
1079 let uuid1_dup = uuid1.clone();
1080 let uuid2 = new2();
1081
1082 assert!(uuid1 == uuid1);
1083 assert!(uuid1 == uuid1_dup);
1084 assert!(uuid1_dup == uuid1);
1085
1086 assert!(uuid1 != uuid2);
1087 assert!(uuid2 != uuid1);
1088 assert!(uuid1_dup != uuid2);
1089 assert!(uuid2 != uuid1_dup);
1090 }
1091
1092 #[test]
1093 #[cfg_attr(
1094 all(
1095 target_arch = "wasm32",
1096 target_vendor = "unknown",
1097 target_os = "unknown"
1098 ),
1099 wasm_bindgen_test
1100 )]
1101 fn test_uuid_to_string() {
1102 use crate::std::fmt::Write;
1103
1104 let uuid = new();
1105 let s = uuid.to_string();
1106 let mut buffer = String::new();
1107
1108 assert_eq!(s.len(), 36);
1109
1110 check!(buffer, "{}", s, 36, |c| c.is_lowercase()
1111 || c.is_digit(10)
1112 || c == '-');
1113 }
1114
1115 #[test]
1116 #[cfg_attr(
1117 all(
1118 target_arch = "wasm32",
1119 target_vendor = "unknown",
1120 target_os = "unknown"
1121 ),
1122 wasm_bindgen_test
1123 )]
1124 fn test_non_conforming() {
1125 let from_bytes =
1126 Uuid::from_bytes([4, 54, 67, 12, 43, 2, 2, 76, 32, 50, 87, 5, 1, 33, 43, 87]);
1127
1128 assert_eq!(from_bytes.get_version(), None);
1129 }
1130
1131 #[test]
1132 #[cfg_attr(
1133 all(
1134 target_arch = "wasm32",
1135 target_vendor = "unknown",
1136 target_os = "unknown"
1137 ),
1138 wasm_bindgen_test
1139 )]
1140 fn test_nil() {
1141 let nil = Uuid::nil();
1142 let not_nil = new();
1143
1144 assert!(nil.is_nil());
1145 assert!(!not_nil.is_nil());
1146
1147 assert_eq!(nil.get_version(), Some(Version::Nil));
1148 assert_eq!(not_nil.get_version(), Some(Version::Random));
1149
1150 assert_eq!(
1151 nil,
1152 Builder::from_bytes([0; 16])
1153 .with_version(Version::Nil)
1154 .into_uuid()
1155 );
1156 }
1157
1158 #[test]
1159 #[cfg(uuid_unstable)]
1160 #[cfg_attr(
1161 all(
1162 target_arch = "wasm32",
1163 target_vendor = "unknown",
1164 target_os = "unknown"
1165 ),
1166 wasm_bindgen_test
1167 )]
1168 fn test_max() {
1169 let max = Uuid::max();
1170 let not_max = new();
1171
1172 assert!(max.is_max());
1173 assert!(!not_max.is_max());
1174
1175 assert_eq!(max.get_version(), Some(Version::Max));
1176 assert_eq!(not_max.get_version(), Some(Version::Random));
1177
1178 assert_eq!(
1179 max,
1180 Builder::from_bytes([0xff; 16])
1181 .with_version(Version::Max)
1182 .into_uuid()
1183 );
1184 }
1185
1186 #[test]
1187 #[cfg_attr(
1188 all(
1189 target_arch = "wasm32",
1190 target_vendor = "unknown",
1191 target_os = "unknown"
1192 ),
1193 wasm_bindgen_test
1194 )]
1195 fn test_predefined_namespaces() {
1196 assert_eq!(
1197 Uuid::NAMESPACE_DNS.hyphenated().to_string(),
1198 "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
1199 );
1200 assert_eq!(
1201 Uuid::NAMESPACE_URL.hyphenated().to_string(),
1202 "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
1203 );
1204 assert_eq!(
1205 Uuid::NAMESPACE_OID.hyphenated().to_string(),
1206 "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
1207 );
1208 assert_eq!(
1209 Uuid::NAMESPACE_X500.hyphenated().to_string(),
1210 "6ba7b814-9dad-11d1-80b4-00c04fd430c8"
1211 );
1212 }
1213
1214 #[cfg(feature = "v3")]
1215 #[test]
1216 #[cfg_attr(
1217 all(
1218 target_arch = "wasm32",
1219 target_vendor = "unknown",
1220 target_os = "unknown"
1221 ),
1222 wasm_bindgen_test
1223 )]
1224 fn test_get_version_v3() {
1225 let uuid = Uuid::new_v3(&Uuid::NAMESPACE_DNS, "rust-lang.org".as_bytes());
1226
1227 assert_eq!(uuid.get_version().unwrap(), Version::Md5);
1228 assert_eq!(uuid.get_version_num(), 3);
1229 }
1230
1231 #[test]
1232 #[cfg_attr(
1233 all(
1234 target_arch = "wasm32",
1235 target_vendor = "unknown",
1236 target_os = "unknown"
1237 ),
1238 wasm_bindgen_test
1239 )]
1240 fn test_get_variant() {
1241 let uuid1 = new();
1242 let uuid2 = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
1243 let uuid3 = Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8").unwrap();
1244 let uuid4 = Uuid::parse_str("936DA01F9ABD4d9dC0C702AF85C822A8").unwrap();
1245 let uuid5 = Uuid::parse_str("F9168C5E-CEB2-4faa-D6BF-329BF39FA1E4").unwrap();
1246 let uuid6 = Uuid::parse_str("f81d4fae-7dec-11d0-7765-00a0c91e6bf6").unwrap();
1247
1248 assert_eq!(uuid1.get_variant(), Variant::RFC4122);
1249 assert_eq!(uuid2.get_variant(), Variant::RFC4122);
1250 assert_eq!(uuid3.get_variant(), Variant::RFC4122);
1251 assert_eq!(uuid4.get_variant(), Variant::Microsoft);
1252 assert_eq!(uuid5.get_variant(), Variant::Microsoft);
1253 assert_eq!(uuid6.get_variant(), Variant::NCS);
1254 }
1255
1256 #[test]
1257 #[cfg_attr(
1258 all(
1259 target_arch = "wasm32",
1260 target_vendor = "unknown",
1261 target_os = "unknown"
1262 ),
1263 wasm_bindgen_test
1264 )]
1265 fn test_to_simple_string() {
1266 let uuid1 = new();
1267 let s = uuid1.simple().to_string();
1268
1269 assert_eq!(s.len(), 32);
1270 assert!(s.chars().all(|c| c.is_digit(16)));
1271 }
1272
1273 #[test]
1274 #[cfg_attr(
1275 all(
1276 target_arch = "wasm32",
1277 target_vendor = "unknown",
1278 target_os = "unknown"
1279 ),
1280 wasm_bindgen_test
1281 )]
1282 fn test_hyphenated_string() {
1283 let uuid1 = new();
1284 let s = uuid1.hyphenated().to_string();
1285
1286 assert_eq!(36, s.len());
1287 assert!(s.chars().all(|c| c.is_digit(16) || c == '-'));
1288 }
1289
1290 #[test]
1291 #[cfg_attr(
1292 all(
1293 target_arch = "wasm32",
1294 target_vendor = "unknown",
1295 target_os = "unknown"
1296 ),
1297 wasm_bindgen_test
1298 )]
1299 fn test_upper_lower_hex() {
1300 use std::fmt::Write;
1301
1302 let mut buf = String::new();
1303 let u = new();
1304
1305 macro_rules! check {
1306 ($buf:ident, $format:expr, $target:expr, $len:expr, $cond:expr) => {
1307 $buf.clear();
1308 write!($buf, $format, $target).unwrap();
1309 assert_eq!($len, buf.len());
1310 assert!($buf.chars().all($cond), "{}", $buf);
1311 };
1312 }
1313
1314 check!(buf, "{:x}", u, 36, |c| c.is_lowercase()
1315 || c.is_digit(10)
1316 || c == '-');
1317 check!(buf, "{:X}", u, 36, |c| c.is_uppercase()
1318 || c.is_digit(10)
1319 || c == '-');
1320 check!(buf, "{:#x}", u, 36, |c| c.is_lowercase()
1321 || c.is_digit(10)
1322 || c == '-');
1323 check!(buf, "{:#X}", u, 36, |c| c.is_uppercase()
1324 || c.is_digit(10)
1325 || c == '-');
1326
1327 check!(buf, "{:X}", u.hyphenated(), 36, |c| c.is_uppercase()
1328 || c.is_digit(10)
1329 || c == '-');
1330 check!(buf, "{:X}", u.simple(), 32, |c| c.is_uppercase()
1331 || c.is_digit(10));
1332 check!(buf, "{:#X}", u.hyphenated(), 36, |c| c.is_uppercase()
1333 || c.is_digit(10)
1334 || c == '-');
1335 check!(buf, "{:#X}", u.simple(), 32, |c| c.is_uppercase()
1336 || c.is_digit(10));
1337
1338 check!(buf, "{:x}", u.hyphenated(), 36, |c| c.is_lowercase()
1339 || c.is_digit(10)
1340 || c == '-');
1341 check!(buf, "{:x}", u.simple(), 32, |c| c.is_lowercase()
1342 || c.is_digit(10));
1343 check!(buf, "{:#x}", u.hyphenated(), 36, |c| c.is_lowercase()
1344 || c.is_digit(10)
1345 || c == '-');
1346 check!(buf, "{:#x}", u.simple(), 32, |c| c.is_lowercase()
1347 || c.is_digit(10));
1348 }
1349
1350 #[test]
1351 #[cfg_attr(
1352 all(
1353 target_arch = "wasm32",
1354 target_vendor = "unknown",
1355 target_os = "unknown"
1356 ),
1357 wasm_bindgen_test
1358 )]
1359 fn test_to_urn_string() {
1360 let uuid1 = new();
1361 let ss = uuid1.urn().to_string();
1362 let s = &ss[9..];
1363
1364 assert!(ss.starts_with("urn:uuid:"));
1365 assert_eq!(s.len(), 36);
1366 assert!(s.chars().all(|c| c.is_digit(16) || c == '-'));
1367 }
1368
1369 #[test]
1370 #[cfg_attr(
1371 all(
1372 target_arch = "wasm32",
1373 target_vendor = "unknown",
1374 target_os = "unknown"
1375 ),
1376 wasm_bindgen_test
1377 )]
1378 fn test_to_simple_string_matching() {
1379 let uuid1 = new();
1380
1381 let hs = uuid1.hyphenated().to_string();
1382 let ss = uuid1.simple().to_string();
1383
1384 let hsn = hs.chars().filter(|&c| c != '-').collect::<String>();
1385
1386 assert_eq!(hsn, ss);
1387 }
1388
1389 #[test]
1390 #[cfg_attr(
1391 all(
1392 target_arch = "wasm32",
1393 target_vendor = "unknown",
1394 target_os = "unknown"
1395 ),
1396 wasm_bindgen_test
1397 )]
1398 fn test_string_roundtrip() {
1399 let uuid = new();
1400
1401 let hs = uuid.hyphenated().to_string();
1402 let uuid_hs = Uuid::parse_str(&hs).unwrap();
1403 assert_eq!(uuid_hs, uuid);
1404
1405 let ss = uuid.to_string();
1406 let uuid_ss = Uuid::parse_str(&ss).unwrap();
1407 assert_eq!(uuid_ss, uuid);
1408 }
1409
1410 #[test]
1411 #[cfg_attr(
1412 all(
1413 target_arch = "wasm32",
1414 target_vendor = "unknown",
1415 target_os = "unknown"
1416 ),
1417 wasm_bindgen_test
1418 )]
1419 fn test_from_fields() {
1420 let d1: u32 = 0xa1a2a3a4;
1421 let d2: u16 = 0xb1b2;
1422 let d3: u16 = 0xc1c2;
1423 let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1424
1425 let u = Uuid::from_fields(d1, d2, d3, &d4);
1426
1427 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1428 let result = u.simple().to_string();
1429 assert_eq!(result, expected);
1430 }
1431
1432 #[test]
1433 #[cfg_attr(
1434 all(
1435 target_arch = "wasm32",
1436 target_vendor = "unknown",
1437 target_os = "unknown"
1438 ),
1439 wasm_bindgen_test
1440 )]
1441 fn test_from_fields_le() {
1442 let d1: u32 = 0xa4a3a2a1;
1443 let d2: u16 = 0xb2b1;
1444 let d3: u16 = 0xc2c1;
1445 let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1446
1447 let u = Uuid::from_fields_le(d1, d2, d3, &d4);
1448
1449 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1450 let result = u.simple().to_string();
1451 assert_eq!(result, expected);
1452 }
1453
1454 #[test]
1455 #[cfg_attr(
1456 all(
1457 target_arch = "wasm32",
1458 target_vendor = "unknown",
1459 target_os = "unknown"
1460 ),
1461 wasm_bindgen_test
1462 )]
1463 fn test_as_fields() {
1464 let u = new();
1465 let (d1, d2, d3, d4) = u.as_fields();
1466
1467 assert_ne!(d1, 0);
1468 assert_ne!(d2, 0);
1469 assert_ne!(d3, 0);
1470 assert_eq!(d4.len(), 8);
1471 assert!(!d4.iter().all(|&b| b == 0));
1472 }
1473
1474 #[test]
1475 #[cfg_attr(
1476 all(
1477 target_arch = "wasm32",
1478 target_vendor = "unknown",
1479 target_os = "unknown"
1480 ),
1481 wasm_bindgen_test
1482 )]
1483 fn test_fields_roundtrip() {
1484 let d1_in: u32 = 0xa1a2a3a4;
1485 let d2_in: u16 = 0xb1b2;
1486 let d3_in: u16 = 0xc1c2;
1487 let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1488
1489 let u = Uuid::from_fields(d1_in, d2_in, d3_in, d4_in);
1490 let (d1_out, d2_out, d3_out, d4_out) = u.as_fields();
1491
1492 assert_eq!(d1_in, d1_out);
1493 assert_eq!(d2_in, d2_out);
1494 assert_eq!(d3_in, d3_out);
1495 assert_eq!(d4_in, d4_out);
1496 }
1497
1498 #[test]
1499 #[cfg_attr(
1500 all(
1501 target_arch = "wasm32",
1502 target_vendor = "unknown",
1503 target_os = "unknown"
1504 ),
1505 wasm_bindgen_test
1506 )]
1507 fn test_fields_le_roundtrip() {
1508 let d1_in: u32 = 0xa4a3a2a1;
1509 let d2_in: u16 = 0xb2b1;
1510 let d3_in: u16 = 0xc2c1;
1511 let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1512
1513 let u = Uuid::from_fields_le(d1_in, d2_in, d3_in, d4_in);
1514 let (d1_out, d2_out, d3_out, d4_out) = u.to_fields_le();
1515
1516 assert_eq!(d1_in, d1_out);
1517 assert_eq!(d2_in, d2_out);
1518 assert_eq!(d3_in, d3_out);
1519 assert_eq!(d4_in, d4_out);
1520 }
1521
1522 #[test]
1523 #[cfg_attr(
1524 all(
1525 target_arch = "wasm32",
1526 target_vendor = "unknown",
1527 target_os = "unknown"
1528 ),
1529 wasm_bindgen_test
1530 )]
1531 fn test_fields_le_are_actually_le() {
1532 let d1_in: u32 = 0xa1a2a3a4;
1533 let d2_in: u16 = 0xb1b2;
1534 let d3_in: u16 = 0xc1c2;
1535 let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1536
1537 let u = Uuid::from_fields(d1_in, d2_in, d3_in, d4_in);
1538 let (d1_out, d2_out, d3_out, d4_out) = u.to_fields_le();
1539
1540 assert_eq!(d1_in, d1_out.swap_bytes());
1541 assert_eq!(d2_in, d2_out.swap_bytes());
1542 assert_eq!(d3_in, d3_out.swap_bytes());
1543 assert_eq!(d4_in, d4_out);
1544 }
1545
1546 #[test]
1547 #[cfg_attr(
1548 all(
1549 target_arch = "wasm32",
1550 target_vendor = "unknown",
1551 target_os = "unknown"
1552 ),
1553 wasm_bindgen_test
1554 )]
1555 fn test_from_u128() {
1556 let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
1557
1558 let u = Uuid::from_u128(v_in);
1559
1560 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1561 let result = u.simple().to_string();
1562 assert_eq!(result, expected);
1563 }
1564
1565 #[test]
1566 #[cfg_attr(
1567 all(
1568 target_arch = "wasm32",
1569 target_vendor = "unknown",
1570 target_os = "unknown"
1571 ),
1572 wasm_bindgen_test
1573 )]
1574 fn test_from_u128_le() {
1575 let v_in: u128 = 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1;
1576
1577 let u = Uuid::from_u128_le(v_in);
1578
1579 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1580 let result = u.simple().to_string();
1581 assert_eq!(result, expected);
1582 }
1583
1584 #[test]
1585 #[cfg_attr(
1586 all(
1587 target_arch = "wasm32",
1588 target_vendor = "unknown",
1589 target_os = "unknown"
1590 ),
1591 wasm_bindgen_test
1592 )]
1593 fn test_from_u64_pair() {
1594 let high_in: u64 = 0xa1a2a3a4b1b2c1c2;
1595 let low_in: u64 = 0xd1d2d3d4d5d6d7d8;
1596
1597 let u = Uuid::from_u64_pair(high_in, low_in);
1598
1599 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1600 let result = u.simple().to_string();
1601 assert_eq!(result, expected);
1602 }
1603
1604 #[test]
1605 #[cfg_attr(
1606 all(
1607 target_arch = "wasm32",
1608 target_vendor = "unknown",
1609 target_os = "unknown"
1610 ),
1611 wasm_bindgen_test
1612 )]
1613 fn test_u128_roundtrip() {
1614 let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
1615
1616 let u = Uuid::from_u128(v_in);
1617 let v_out = u.as_u128();
1618
1619 assert_eq!(v_in, v_out);
1620 }
1621
1622 #[test]
1623 #[cfg_attr(
1624 all(
1625 target_arch = "wasm32",
1626 target_vendor = "unknown",
1627 target_os = "unknown"
1628 ),
1629 wasm_bindgen_test
1630 )]
1631 fn test_u128_le_roundtrip() {
1632 let v_in: u128 = 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1;
1633
1634 let u = Uuid::from_u128_le(v_in);
1635 let v_out = u.to_u128_le();
1636
1637 assert_eq!(v_in, v_out);
1638 }
1639
1640 #[test]
1641 #[cfg_attr(
1642 all(
1643 target_arch = "wasm32",
1644 target_vendor = "unknown",
1645 target_os = "unknown"
1646 ),
1647 wasm_bindgen_test
1648 )]
1649 fn test_u64_pair_roundtrip() {
1650 let high_in: u64 = 0xa1a2a3a4b1b2c1c2;
1651 let low_in: u64 = 0xd1d2d3d4d5d6d7d8;
1652
1653 let u = Uuid::from_u64_pair(high_in, low_in);
1654 let (high_out, low_out) = u.as_u64_pair();
1655
1656 assert_eq!(high_in, high_out);
1657 assert_eq!(low_in, low_out);
1658 }
1659
1660 #[test]
1661 #[cfg_attr(
1662 all(
1663 target_arch = "wasm32",
1664 target_vendor = "unknown",
1665 target_os = "unknown"
1666 ),
1667 wasm_bindgen_test
1668 )]
1669 fn test_u128_le_is_actually_le() {
1670 let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
1671
1672 let u = Uuid::from_u128(v_in);
1673 let v_out = u.to_u128_le();
1674
1675 assert_eq!(v_in, v_out.swap_bytes());
1676 }
1677
1678 #[test]
1679 #[cfg_attr(
1680 all(
1681 target_arch = "wasm32",
1682 target_vendor = "unknown",
1683 target_os = "unknown"
1684 ),
1685 wasm_bindgen_test
1686 )]
1687 fn test_from_slice() {
1688 let b = [
1689 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
1690 0xd7, 0xd8,
1691 ];
1692
1693 let u = Uuid::from_slice(&b).unwrap();
1694 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1695
1696 assert_eq!(u.simple().to_string(), expected);
1697 }
1698
1699 #[test]
1700 #[cfg_attr(
1701 all(
1702 target_arch = "wasm32",
1703 target_vendor = "unknown",
1704 target_os = "unknown"
1705 ),
1706 wasm_bindgen_test
1707 )]
1708 fn test_from_bytes() {
1709 let b = [
1710 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
1711 0xd7, 0xd8,
1712 ];
1713
1714 let u = Uuid::from_bytes(b);
1715 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1716
1717 assert_eq!(u.simple().to_string(), expected);
1718 }
1719
1720 #[test]
1721 #[cfg_attr(
1722 all(
1723 target_arch = "wasm32",
1724 target_vendor = "unknown",
1725 target_os = "unknown"
1726 ),
1727 wasm_bindgen_test
1728 )]
1729 fn test_as_bytes() {
1730 let u = new();
1731 let ub = u.as_bytes();
1732 let ur = u.as_ref();
1733
1734 assert_eq!(ub.len(), 16);
1735 assert_eq!(ur.len(), 16);
1736 assert!(!ub.iter().all(|&b| b == 0));
1737 assert!(!ur.iter().all(|&b| b == 0));
1738 }
1739
1740 #[test]
1741 #[cfg_attr(
1742 all(
1743 target_arch = "wasm32",
1744 target_vendor = "unknown",
1745 target_os = "unknown"
1746 ),
1747 wasm_bindgen_test
1748 )]
1749 fn test_bytes_roundtrip() {
1750 let b_in: crate::Bytes = [
1751 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
1752 0xd7, 0xd8,
1753 ];
1754
1755 let u = Uuid::from_slice(&b_in).unwrap();
1756
1757 let b_out = u.as_bytes();
1758
1759 assert_eq!(&b_in, b_out);
1760 }
1761
1762 #[test]
1763 #[cfg_attr(
1764 all(
1765 target_arch = "wasm32",
1766 target_vendor = "unknown",
1767 target_os = "unknown"
1768 ),
1769 wasm_bindgen_test
1770 )]
1771 fn test_bytes_le_roundtrip() {
1772 let b = [
1773 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
1774 0xd7, 0xd8,
1775 ];
1776
1777 let u1 = Uuid::from_bytes(b);
1778
1779 let b_le = u1.to_bytes_le();
1780
1781 let u2 = Uuid::from_bytes_le(b_le);
1782
1783 assert_eq!(u1, u2);
1784 }
1785
1786 #[test]
1787 #[cfg_attr(
1788 all(
1789 target_arch = "wasm32",
1790 target_vendor = "unknown",
1791 target_os = "unknown"
1792 ),
1793 wasm_bindgen_test
1794 )]
1795 fn test_iterbytes_impl_for_uuid() {
1796 let mut set = std::collections::HashSet::new();
1797 let id1 = new();
1798 let id2 = new2();
1799 set.insert(id1.clone());
1800
1801 assert!(set.contains(&id1));
1802 assert!(!set.contains(&id2));
1803 }
1804}
1805