uuid/
lib.rs

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