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//! # Getting started
34//!
35//! Add the following to your `Cargo.toml`:
36//!
37//! ```toml
38//! [dependencies.uuid]
39//! version = "1.1.2"
40//! features = [
41//!     "v4",                # Lets you generate random UUIDs
42//!     "fast-rng",          # Use a faster (but still sufficiently random) RNG
43//!     "macro-diagnostics", # Enable better diagnostics for compile-time UUIDs
44//! ]
45//! ```
46//!
47//! When you want a UUID, you can generate one:
48//!
49//! ```
50//! # fn main() {
51//! # #[cfg(feature = "v4")]
52//! # {
53//! use uuid::Uuid;
54//!
55//! let id = Uuid::new_v4();
56//! # }
57//! # }
58//! ```
59//!
60//! If you have a UUID value, you can use its string literal form inline:
61//!
62//! ```
63//! use uuid::{uuid, Uuid};
64//!
65//! const ID: Uuid = uuid!("67e55044-10b1-426f-9247-bb680e5fe0c8");
66//! ```
67//!
68//! # Dependencies
69//!
70//! By default, this crate depends on nothing but `std` and can parse and format
71//! UUIDs, but cannot generate them. You need to enable the following Cargo
72//! features to enable various pieces of functionality:
73//!
74//! * `v1` - adds the [`Uuid::new_v1`] function and the ability to create a V1
75//!   UUID using an implementation of [`v1::ClockSequence`] (usually
76//! [`v1::Context`]) and a UNIX timestamp.
77//! * `v3` - adds the [`Uuid::new_v3`] function and the ability to create a V3
78//!   UUID based on the MD5 hash of some data.
79//! * `v4` - adds the [`Uuid::new_v4`] function and the ability to randomly
80//!   generate a UUID.
81//! * `v5` - adds the [`Uuid::new_v5`] function and the ability to create a V5
82//!   UUID based on the SHA1 hash of some data.
83//!
84//! Other crate features can also be useful beyond the version support:
85//!
86//! * `macro-diagnostics` - enhances the diagnostics of `uuid!` macro.
87//! * `serde` - adds the ability to serialize and deserialize a UUID using
88//!   `serde`.
89//! * `arbitrary` - adds an `Arbitrary` trait implementation to `Uuid` for
90//!   fuzzing.
91//! * `fast-rng` - when combined with `v4` uses a faster algorithm for
92//!   generating random UUIDs. This feature requires more dependencies to
93//!   compile, but is just as suitable for UUIDs as the default algorithm.
94//!
95//! ## Unstable features
96//!
97//! Some features are unstable. They may be incomplete or depend on other
98//! unstable libraries. These include:
99//!
100//! * `zerocopy` - adds support for zero-copy deserialization using the
101//!   `zerocopy` library.
102//!
103//! Unstable features may break between minor releases.
104//!
105//! To allow unstable features, you'll need to enable the Cargo feature as
106//! normal, but also pass an additional flag through your environment to opt-in
107//! to unstable `uuid` features:
108//!
109//! ```text
110//! RUSTFLAGS="--cfg uuid_unstable"
111//! ```
112//!
113//! # Building for other targets
114//!
115//! ## WebAssembly
116//!
117//! For WebAssembly, enable the `js` feature along with `v4` for a
118//! source of randomness:
119//!
120//! ```toml
121//! [dependencies.uuid]
122//! version = "1"
123//! features = [
124//!     "v4",
125//!     "js",
126//! ]
127//! ```
128//!
129//! You don't need the `js` feature to use `uuid` in WebAssembly if you're
130//! not also enabling `v4`.
131//!
132//! ## Embedded
133//!
134//! For embedded targets without the standard library, you'll need to
135//! disable default features when building `uuid`:
136//!
137//! ```toml
138//! [dependencies.uuid]
139//! version = "1"
140//! default-features = false
141//! ```
142//!
143//! Some additional features are supported in no-std environments:
144//!
145//! * `v1`, `v3`, and `v5`
146//! * `serde`
147//!
148//! If you need to use `v4` in a no-std environment, you'll need to
149//! follow [`getrandom`'s docs] on configuring a source of randomness
150//! on currently unsupported targets. Alternatively, you can produce
151//! random bytes yourself and then pass them to [`Builder::from_random_bytes`]
152//! without enabling the `v4` feature.
153//!
154//! # Examples
155//!
156//! To parse a UUID given in the simple format and print it as a urn:
157//!
158//! ```
159//! # use uuid::Uuid;
160//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
161//! let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
162//!
163//! println!("{}", my_uuid.urn());
164//! # Ok(())
165//! # }
166//! ```
167//!
168//! To create a new random (V4) UUID and print it out in hexadecimal form:
169//!
170//! ```
171//! // Note that this requires the `v4` feature to be enabled.
172//! # use uuid::Uuid;
173//! # fn main() {
174//! # #[cfg(feature = "v4")] {
175//! let my_uuid = Uuid::new_v4();
176//!
177//! println!("{}", my_uuid);
178//! # }
179//! # }
180//! ```
181//!
182//! # References
183//!
184//! * [Wikipedia: Universally Unique Identifier](http://en.wikipedia.org/wiki/Universally_unique_identifier)
185//! * [RFC4122: A Universally Unique IDentifier (UUID) URN Namespace](http://tools.ietf.org/html/rfc4122)
186//!
187//! [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
188//! [`cargo-web`]: https://crates.io/crates/cargo-web
189//! [`Uuid`]: struct.Uuid.html
190//! [`Uuid::new_v1`]: struct.Uuid.html#method.new_v1
191//! [`Uuid::new_v3`]: struct.Uuid.html#method.new_v3
192//! [`Uuid::new_v4`]: struct.Uuid.html#method.new_v4
193//! [`Uuid::new_v5`]: struct.Uuid.html#method.new_v5
194//! [`v1::ClockSequence`]: v1/trait.ClockSequence.html
195//! [`v1::Context`]: v1/struct.Context.html
196//! [`getrandom`'s docs]: https://docs.rs/getrandom
197
198#![no_std]
199#![deny(missing_debug_implementations, missing_docs)]
200#![doc(
201    html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
202    html_favicon_url = "https://www.rust-lang.org/favicon.ico",
203    html_root_url = "https://docs.rs/uuid/1.1.2"
204)]
205
206#[cfg(any(feature = "std", test))]
207#[macro_use]
208extern crate std;
209
210#[cfg(all(not(feature = "std"), not(test)))]
211#[macro_use]
212extern crate core as std;
213
214// Check that unstable features are accompanied by a the `uuid_unstable` cfg
215#[cfg(all(not(uuid_unstable), feature = "zerocopy"))]
216compile_error!("The `zerocopy` feature is unstable and may break between releases. Please also pass `RUSTFLAGS=\"--cfg uuid_unstable\"` to allow it.");
217
218#[cfg(feature = "zerocopy")]
219use zerocopy::{AsBytes, FromBytes, Unaligned};
220
221mod builder;
222mod error;
223mod parser;
224
225pub mod fmt;
226
227#[cfg(feature = "v1")]
228pub mod v1;
229#[cfg(feature = "v3")]
230mod v3;
231#[cfg(feature = "v4")]
232mod v4;
233#[cfg(feature = "v5")]
234mod v5;
235
236#[cfg(feature = "md5")]
237mod md5;
238#[cfg(feature = "rng")]
239mod rng;
240#[cfg(feature = "sha1")]
241mod sha1;
242
243mod external;
244
245#[macro_use]
246mod macros;
247
248#[doc(hidden)]
249#[cfg(feature = "macro-diagnostics")]
250pub extern crate private_uuid_macro_internal;
251
252use crate::std::convert;
253
254pub use crate::{builder::Builder, error::Error};
255
256/// A 128-bit (16 byte) buffer containing the UUID.
257///
258/// # ABI
259///
260/// The `Bytes` type is always guaranteed to be have the same ABI as [`Uuid`].
261pub type Bytes = [u8; 16];
262
263/// The version of the UUID, denoting the generating algorithm.
264///
265/// # References
266///
267/// * [Version in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.3)
268#[derive(Clone, Copy, Debug, PartialEq)]
269#[non_exhaustive]
270pub enum Version {
271    /// Special case for `nil` UUID.
272    Nil = 0,
273    /// Version 1: MAC address.
274    Mac,
275    /// Version 2: DCE Security.
276    Dce,
277    /// Version 3: MD5 hash.
278    Md5,
279    /// Version 4: Random.
280    Random,
281    /// Version 5: SHA-1 hash.
282    Sha1,
283}
284
285/// The reserved variants of UUIDs.
286///
287/// # References
288///
289/// * [Variant in RFC4122](http://tools.ietf.org/html/rfc4122#section-4.1.1)
290#[derive(Clone, Copy, Debug, PartialEq)]
291#[non_exhaustive]
292pub enum Variant {
293    /// Reserved by the NCS for backward compatibility.
294    NCS = 0,
295    /// As described in the RFC4122 Specification (default).
296    RFC4122,
297    /// Reserved by Microsoft for backward compatibility.
298    Microsoft,
299    /// Reserved for future expansion.
300    Future,
301}
302
303/// A Universally Unique Identifier (UUID).
304///
305/// # Examples
306///
307/// Parse a UUID given in the simple format and print it as a urn:
308///
309/// ```
310/// # use uuid::Uuid;
311/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
312/// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
313///
314/// println!("{}", my_uuid.urn());
315/// # Ok(())
316/// # }
317/// ```
318///
319/// Create a new random (V4) UUID and print it out in hexadecimal form:
320///
321/// ```
322/// // Note that this requires the `v4` feature enabled in the uuid crate.
323/// # use uuid::Uuid;
324/// # fn main() {
325/// # #[cfg(feature = "v4")] {
326/// let my_uuid = Uuid::new_v4();
327///
328/// println!("{}", my_uuid);
329/// # }
330/// # }
331/// ```
332///
333/// # Formatting
334///
335/// A UUID can be formatted in one of a few ways:
336///
337/// * [`simple`](#method.simple): `a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8`.
338/// * [`hyphenated`](#method.hyphenated):
339///   `a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8`.
340/// * [`urn`](#method.urn): `urn:uuid:A1A2A3A4-B1B2-C1C2-D1D2-D3D4D5D6D7D8`.
341/// * [`braced`](#method.braced): `{a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8}`.
342///
343/// The default representation when formatting a UUID with `Display` is
344/// hyphenated:
345///
346/// ```
347/// # use uuid::Uuid;
348/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
349/// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
350///
351/// assert_eq!(
352///     "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
353///     my_uuid.to_string(),
354/// );
355/// # Ok(())
356/// # }
357/// ```
358///
359/// Other formats can be specified using adapter methods on the UUID:
360///
361/// ```
362/// # use uuid::Uuid;
363/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
364/// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
365///
366/// assert_eq!(
367///     "urn:uuid:a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
368///     my_uuid.urn().to_string(),
369/// );
370/// # Ok(())
371/// # }
372/// ```
373///
374/// # Endianness
375///
376/// The specification for UUIDs encodes the integer fields that make up the
377/// value in big-endian order. This crate assumes integer inputs are already in
378/// the correct order by default, regardless of the endianness of the
379/// environment. Most methods that accept integers have a `_le` variant (such as
380/// `from_fields_le`) that assumes any integer values will need to have their
381/// bytes flipped, regardless of the endianness of the environment.
382///
383/// Most users won't need to worry about endianness unless they need to operate
384/// on individual fields (such as when converting between Microsoft GUIDs). The
385/// important things to remember are:
386///
387/// - The endianness is in terms of the fields of the UUID, not the environment.
388/// - The endianness is assumed to be big-endian when there's no `_le` suffix
389///   somewhere.
390/// - Byte-flipping in `_le` methods applies to each integer.
391/// - Endianness roundtrips, so if you create a UUID with `from_fields_le`
392///   you'll get the same values back out with `to_fields_le`.
393///
394/// # ABI
395///
396/// The `Uuid` type is always guaranteed to be have the same ABI as [`Bytes`].
397#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
398#[cfg_attr(feature = "zerocopy", derive(AsBytes, FromBytes, Unaligned))]
399#[repr(transparent)]
400pub struct Uuid(Bytes);
401
402impl Uuid {
403    /// UUID namespace for Domain Name System (DNS).
404    pub const NAMESPACE_DNS: Self = Uuid([
405        0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0,
406        0x4f, 0xd4, 0x30, 0xc8,
407    ]);
408
409    /// UUID namespace for ISO Object Identifiers (OIDs).
410    pub const NAMESPACE_OID: Self = Uuid([
411        0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0,
412        0x4f, 0xd4, 0x30, 0xc8,
413    ]);
414
415    /// UUID namespace for Uniform Resource Locators (URLs).
416    pub const NAMESPACE_URL: Self = Uuid([
417        0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0,
418        0x4f, 0xd4, 0x30, 0xc8,
419    ]);
420
421    /// UUID namespace for X.500 Distinguished Names (DNs).
422    pub const NAMESPACE_X500: Self = Uuid([
423        0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0,
424        0x4f, 0xd4, 0x30, 0xc8,
425    ]);
426
427    /// Returns the variant of the UUID structure.
428    ///
429    /// This determines the interpretation of the structure of the UUID.
430    /// This method simply reads the value of the variant byte. It doesn't
431    /// validate the rest of the UUID as conforming to that variant.
432    ///
433    /// # Examples
434    ///
435    /// Basic usage:
436    ///
437    /// ```
438    /// # use uuid::{Uuid, Variant};
439    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
440    /// let my_uuid = Uuid::parse_str("02f09a3f-1624-3b1d-8409-44eff7708208")?;
441    ///
442    /// assert_eq!(Variant::RFC4122, my_uuid.get_variant());
443    /// # Ok(())
444    /// # }
445    /// ```
446    ///
447    /// # References
448    ///
449    /// * [Variant in RFC4122](http://tools.ietf.org/html/rfc4122#section-4.1.1)
450    pub const fn get_variant(&self) -> Variant {
451        match self.as_bytes()[8] {
452            x if x & 0x80 == 0x00 => Variant::NCS,
453            x if x & 0xc0 == 0x80 => Variant::RFC4122,
454            x if x & 0xe0 == 0xc0 => Variant::Microsoft,
455            x if x & 0xe0 == 0xe0 => Variant::Future,
456            // The above match arms are actually exhaustive
457            // We just return `Future` here because we can't
458            // use `unreachable!()` in a `const fn`
459            _ => Variant::Future,
460        }
461    }
462
463    /// Returns the version number of the UUID.
464    ///
465    /// This represents the algorithm used to generate the value.
466    /// This method is the future-proof alternative to [`Uuid::get_version`].
467    ///
468    /// # Examples
469    ///
470    /// Basic usage:
471    ///
472    /// ```
473    /// # use uuid::Uuid;
474    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
475    /// let my_uuid = Uuid::parse_str("02f09a3f-1624-3b1d-8409-44eff7708208")?;
476    ///
477    /// assert_eq!(3, my_uuid.get_version_num());
478    /// # Ok(())
479    /// # }
480    /// ```
481    ///
482    /// # References
483    ///
484    /// * [Version in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.3)
485    pub const fn get_version_num(&self) -> usize {
486        (self.as_bytes()[6] >> 4) as usize
487    }
488
489    /// Returns the version of the UUID.
490    ///
491    /// This represents the algorithm used to generate the value.
492    /// If the version field doesn't contain a recognized version then `None`
493    /// is returned. If you're trying to read the version for a future extension
494    /// you can also use [`Uuid::get_version_num`] to unconditionally return a
495    /// number. Future extensions may start to return `Some` once they're
496    /// standardized and supported.
497    ///
498    /// # Examples
499    ///
500    /// Basic usage:
501    ///
502    /// ```
503    /// # use uuid::{Uuid, Version};
504    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
505    /// let my_uuid = Uuid::parse_str("02f09a3f-1624-3b1d-8409-44eff7708208")?;
506    ///
507    /// assert_eq!(Some(Version::Md5), my_uuid.get_version());
508    /// # Ok(())
509    /// # }
510    /// ```
511    ///
512    /// # References
513    ///
514    /// * [Version in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.3)
515    pub const fn get_version(&self) -> Option<Version> {
516        match self.get_version_num() {
517            0 if self.is_nil() => Some(Version::Nil),
518            1 => Some(Version::Mac),
519            2 => Some(Version::Dce),
520            3 => Some(Version::Md5),
521            4 => Some(Version::Random),
522            5 => Some(Version::Sha1),
523            _ => None,
524        }
525    }
526
527    /// Returns the four field values of the UUID.
528    ///
529    /// These values can be passed to the [`Uuid::from_fields`] method to get
530    /// the original `Uuid` back.
531    ///
532    /// * The first field value represents the first group of (eight) hex
533    ///   digits, taken as a big-endian `u32` value.  For V1 UUIDs, this field
534    ///   represents the low 32 bits of the timestamp.
535    /// * The second field value represents the second group of (four) hex
536    ///   digits, taken as a big-endian `u16` value.  For V1 UUIDs, this field
537    ///   represents the middle 16 bits of the timestamp.
538    /// * The third field value represents the third group of (four) hex digits,
539    ///   taken as a big-endian `u16` value.  The 4 most significant bits give
540    ///   the UUID version, and for V1 UUIDs, the last 12 bits represent the
541    ///   high 12 bits of the timestamp.
542    /// * The last field value represents the last two groups of four and twelve
543    ///   hex digits, taken in order.  The first 1-3 bits of this indicate the
544    ///   UUID variant, and for V1 UUIDs, the next 13-15 bits indicate the clock
545    ///   sequence and the last 48 bits indicate the node ID.
546    ///
547    /// # Examples
548    ///
549    /// ```
550    /// # use uuid::Uuid;
551    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
552    /// let uuid = Uuid::nil();
553    ///
554    /// assert_eq!(uuid.as_fields(), (0, 0, 0, &[0u8; 8]));
555    ///
556    /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
557    ///
558    /// assert_eq!(
559    ///     uuid.as_fields(),
560    ///     (
561    ///         0xa1a2a3a4,
562    ///         0xb1b2,
563    ///         0xc1c2,
564    ///         &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8],
565    ///     )
566    /// );
567    /// # Ok(())
568    /// # }
569    /// ```
570    pub fn as_fields(&self) -> (u32, u16, u16, &[u8; 8]) {
571        let bytes = self.as_bytes();
572
573        let d1 = (bytes[0] as u32) << 24
574            | (bytes[1] as u32) << 16
575            | (bytes[2] as u32) << 8
576            | (bytes[3] as u32);
577
578        let d2 = (bytes[4] as u16) << 8 | (bytes[5] as u16);
579
580        let d3 = (bytes[6] as u16) << 8 | (bytes[7] as u16);
581
582        let d4: &[u8; 8] = convert::TryInto::try_into(&bytes[8..16]).unwrap();
583        (d1, d2, d3, d4)
584    }
585
586    /// Returns the four field values of the UUID in little-endian order.
587    ///
588    /// The bytes in the returned integer fields will be converted from
589    /// big-endian order. This is based on the endianness of the UUID,
590    /// rather than the target environment so bytes will be flipped on both
591    /// big and little endian machines.
592    ///
593    /// # Examples
594    ///
595    /// ```
596    /// use uuid::Uuid;
597    ///
598    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
599    /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
600    ///
601    /// assert_eq!(
602    ///     uuid.to_fields_le(),
603    ///     (
604    ///         0xa4a3a2a1,
605    ///         0xb2b1,
606    ///         0xc2c1,
607    ///         &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8],
608    ///     )
609    /// );
610    /// # Ok(())
611    /// # }
612    /// ```
613    pub fn to_fields_le(&self) -> (u32, u16, u16, &[u8; 8]) {
614        let d1 = (self.as_bytes()[0] as u32)
615            | (self.as_bytes()[1] as u32) << 8
616            | (self.as_bytes()[2] as u32) << 16
617            | (self.as_bytes()[3] as u32) << 24;
618
619        let d2 = (self.as_bytes()[4] as u16) | (self.as_bytes()[5] as u16) << 8;
620
621        let d3 = (self.as_bytes()[6] as u16) | (self.as_bytes()[7] as u16) << 8;
622
623        let d4: &[u8; 8] =
624            convert::TryInto::try_into(&self.as_bytes()[8..16]).unwrap();
625        (d1, d2, d3, d4)
626    }
627
628    /// Returns a 128bit value containing the value.
629    ///
630    /// The bytes in the UUID will be packed directly into a `u128`.
631    ///
632    /// # Examples
633    ///
634    /// ```
635    /// # use uuid::Uuid;
636    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
637    /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
638    ///
639    /// assert_eq!(
640    ///     uuid.as_u128(),
641    ///     0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8,
642    /// );
643    /// # Ok(())
644    /// # }
645    /// ```
646    pub const fn as_u128(&self) -> u128 {
647        (self.as_bytes()[0] as u128) << 120
648            | (self.as_bytes()[1] as u128) << 112
649            | (self.as_bytes()[2] as u128) << 104
650            | (self.as_bytes()[3] as u128) << 96
651            | (self.as_bytes()[4] as u128) << 88
652            | (self.as_bytes()[5] as u128) << 80
653            | (self.as_bytes()[6] as u128) << 72
654            | (self.as_bytes()[7] as u128) << 64
655            | (self.as_bytes()[8] as u128) << 56
656            | (self.as_bytes()[9] as u128) << 48
657            | (self.as_bytes()[10] as u128) << 40
658            | (self.as_bytes()[11] as u128) << 32
659            | (self.as_bytes()[12] as u128) << 24
660            | (self.as_bytes()[13] as u128) << 16
661            | (self.as_bytes()[14] as u128) << 8
662            | (self.as_bytes()[15] as u128)
663    }
664
665    /// Returns a 128bit little-endian value containing the value.
666    ///
667    /// The bytes in the `u128` will be flipped to convert into big-endian
668    /// order. This is based on the endianness of the UUID, rather than the
669    /// target environment so bytes will be flipped on both big and little
670    /// endian machines.
671    ///
672    /// Note that this will produce a different result than
673    /// [`Uuid::to_fields_le`], because the entire UUID is reversed, rather
674    /// than reversing the individual fields in-place.
675    ///
676    /// # Examples
677    ///
678    /// ```
679    /// # use uuid::Uuid;
680    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
681    /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
682    ///
683    /// assert_eq!(
684    ///     uuid.to_u128_le(),
685    ///     0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1,
686    /// );
687    /// # Ok(())
688    /// # }
689    /// ```
690    pub const fn to_u128_le(&self) -> u128 {
691        (self.as_bytes()[0] as u128)
692            | (self.as_bytes()[1] as u128) << 8
693            | (self.as_bytes()[2] as u128) << 16
694            | (self.as_bytes()[3] as u128) << 24
695            | (self.as_bytes()[4] as u128) << 32
696            | (self.as_bytes()[5] as u128) << 40
697            | (self.as_bytes()[6] as u128) << 48
698            | (self.as_bytes()[7] as u128) << 56
699            | (self.as_bytes()[8] as u128) << 64
700            | (self.as_bytes()[9] as u128) << 72
701            | (self.as_bytes()[10] as u128) << 80
702            | (self.as_bytes()[11] as u128) << 88
703            | (self.as_bytes()[12] as u128) << 96
704            | (self.as_bytes()[13] as u128) << 104
705            | (self.as_bytes()[14] as u128) << 112
706            | (self.as_bytes()[15] as u128) << 120
707    }
708
709    /// Returns two 64bit values containing the value.
710    ///
711    /// The bytes in the UUID will be split into two `u64`.
712    /// The first u64 represents the 64 most significant bits,
713    /// the second one represents the 64 least significant.
714    ///
715    /// # Examples
716    ///
717    /// ```
718    /// # use uuid::Uuid;
719    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
720    /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
721    /// assert_eq!(
722    ///     uuid.as_u64_pair(),
723    ///     (0xa1a2a3a4b1b2c1c2, 0xd1d2d3d4d5d6d7d8),
724    /// );
725    /// # Ok(())
726    /// # }
727    /// ```
728    pub const fn as_u64_pair(&self) -> (u64, u64) {
729        let value = self.as_u128();
730        ((value >> 64) as u64, value as u64)
731    }
732
733    /// Returns a slice of 16 octets containing the value.
734    ///
735    /// This method borrows the underlying byte value of the UUID.
736    ///
737    /// # Examples
738    ///
739    /// ```
740    /// # use uuid::Uuid;
741    /// let bytes1 = [
742    ///     0xa1, 0xa2, 0xa3, 0xa4,
743    ///     0xb1, 0xb2,
744    ///     0xc1, 0xc2,
745    ///     0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
746    /// ];
747    /// let uuid1 = Uuid::from_bytes_ref(&bytes1);
748    ///
749    /// let bytes2 = uuid1.as_bytes();
750    /// let uuid2 = Uuid::from_bytes_ref(bytes2);
751    ///
752    /// assert_eq!(uuid1, uuid2);
753    ///
754    /// assert!(std::ptr::eq(
755    ///     uuid2 as *const Uuid as *const u8,
756    ///     &bytes1 as *const [u8; 16] as *const u8,
757    /// ));
758    /// ```
759    pub const fn as_bytes(&self) -> &Bytes {
760        &self.0
761    }
762
763    /// Consumes self and returns the underlying byte value of the UUID.
764    ///
765    /// # Examples
766    ///
767    /// ```
768    /// # use uuid::Uuid;
769    /// let bytes = [
770    ///     0xa1, 0xa2, 0xa3, 0xa4,
771    ///     0xb1, 0xb2,
772    ///     0xc1, 0xc2,
773    ///     0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
774    /// ];
775    /// let uuid = Uuid::from_bytes(bytes);
776    /// assert_eq!(bytes, uuid.into_bytes());
777    /// ```
778    pub const fn into_bytes(self) -> Bytes {
779        self.0
780    }
781
782    /// Returns the bytes of the UUID in little-endian order.
783    ///
784    /// The bytes will be flipped to convert into little-endian order. This is
785    /// based on the endianness of the UUID, rather than the target environment
786    /// so bytes will be flipped on both big and little endian machines.
787    ///
788    /// # Examples
789    ///
790    /// ```
791    /// use uuid::Uuid;
792    ///
793    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
794    /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
795    ///
796    /// assert_eq!(
797    ///     uuid.to_bytes_le(),
798    ///     ([
799    ///         0xa4, 0xa3, 0xa2, 0xa1, 0xb2, 0xb1, 0xc2, 0xc1, 0xd1, 0xd2,
800    ///         0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8
801    ///     ])
802    /// );
803    /// # Ok(())
804    /// # }
805    /// ```
806    pub const fn to_bytes_le(&self) -> Bytes {
807        [
808            self.0[3], self.0[2], self.0[1], self.0[0], self.0[5], self.0[4],
809            self.0[7], self.0[6], self.0[8], self.0[9], self.0[10], self.0[11],
810            self.0[12], self.0[13], self.0[14], self.0[15],
811        ]
812    }
813
814    /// Tests if the UUID is nil.
815    pub const fn is_nil(&self) -> bool {
816        self.as_u128() == 0
817    }
818
819    /// A buffer that can be used for `encode_...` calls, that is
820    /// guaranteed to be long enough for any of the format adapters.
821    ///
822    /// # Examples
823    ///
824    /// ```
825    /// # use uuid::Uuid;
826    /// let uuid = Uuid::nil();
827    ///
828    /// assert_eq!(
829    ///     uuid.simple().encode_lower(&mut Uuid::encode_buffer()),
830    ///     "00000000000000000000000000000000"
831    /// );
832    ///
833    /// assert_eq!(
834    ///     uuid.hyphenated()
835    ///         .encode_lower(&mut Uuid::encode_buffer()),
836    ///     "00000000-0000-0000-0000-000000000000"
837    /// );
838    ///
839    /// assert_eq!(
840    ///     uuid.urn().encode_lower(&mut Uuid::encode_buffer()),
841    ///     "urn:uuid:00000000-0000-0000-0000-000000000000"
842    /// );
843    /// ```
844    pub const fn encode_buffer() -> [u8; fmt::Urn::LENGTH] {
845        [0; fmt::Urn::LENGTH]
846    }
847}
848
849impl Default for Uuid {
850    #[inline]
851    fn default() -> Self {
852        Uuid::nil()
853    }
854}
855
856impl AsRef<[u8]> for Uuid {
857    #[inline]
858    fn as_ref(&self) -> &[u8] {
859        &self.0
860    }
861}
862
863#[cfg(feature = "serde")]
864pub mod serde {
865    //! Adapters for alternative `serde` formats.
866    //!
867    //! This module contains adapters you can use with [`#[serde(with)]`](https://serde.rs/field-attrs.html#with)
868    //! to change the way a [`Uuid`](../struct.Uuid.html) is serialized
869    //! and deserialized.
870
871    pub use crate::external::serde_support::compact;
872}
873
874#[cfg(test)]
875mod tests {
876    use super::*;
877
878    use crate::std::string::{String, ToString};
879
880    #[cfg(target_arch = "wasm32")]
881    use wasm_bindgen_test::*;
882
883    macro_rules! check {
884        ($buf:ident, $format:expr, $target:expr, $len:expr, $cond:expr) => {
885            $buf.clear();
886            write!($buf, $format, $target).unwrap();
887            assert!($buf.len() == $len);
888            assert!($buf.chars().all($cond), "{}", $buf);
889        };
890    }
891
892    pub const fn new() -> Uuid {
893        Uuid::from_bytes([
894            0xF9, 0x16, 0x8C, 0x5E, 0xCE, 0xB2, 0x4F, 0xAA, 0xB6, 0xBF, 0x32,
895            0x9B, 0xF3, 0x9F, 0xA1, 0xE4,
896        ])
897    }
898
899    pub const fn new2() -> Uuid {
900        Uuid::from_bytes([
901            0xF9, 0x16, 0x8C, 0x5E, 0xCE, 0xB2, 0x4F, 0xAB, 0xB6, 0xBF, 0x32,
902            0x9B, 0xF3, 0x9F, 0xA1, 0xE4,
903        ])
904    }
905
906    #[test]
907    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
908    fn test_uuid_compare() {
909        let uuid1 = new();
910        let uuid2 = new2();
911
912        assert_eq!(uuid1, uuid1);
913        assert_eq!(uuid2, uuid2);
914
915        assert_ne!(uuid1, uuid2);
916        assert_ne!(uuid2, uuid1);
917    }
918
919    #[test]
920    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
921    fn test_uuid_default() {
922        let default_uuid = Uuid::default();
923        let nil_uuid = Uuid::nil();
924
925        assert_eq!(default_uuid, nil_uuid);
926    }
927
928    #[test]
929    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
930    fn test_uuid_display() {
931        use crate::std::fmt::Write;
932
933        let uuid = new();
934        let s = uuid.to_string();
935        let mut buffer = String::new();
936
937        assert_eq!(s, uuid.hyphenated().to_string());
938
939        check!(buffer, "{}", uuid, 36, |c| c.is_lowercase()
940            || c.is_digit(10)
941            || c == '-');
942    }
943
944    #[test]
945    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
946    fn test_uuid_lowerhex() {
947        use crate::std::fmt::Write;
948
949        let mut buffer = String::new();
950        let uuid = new();
951
952        check!(buffer, "{:x}", uuid, 36, |c| c.is_lowercase()
953            || c.is_digit(10)
954            || c == '-');
955    }
956
957    // noinspection RsAssertEqual
958    #[test]
959    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
960    fn test_uuid_operator_eq() {
961        let uuid1 = new();
962        let uuid1_dup = uuid1.clone();
963        let uuid2 = new2();
964
965        assert!(uuid1 == uuid1);
966        assert!(uuid1 == uuid1_dup);
967        assert!(uuid1_dup == uuid1);
968
969        assert!(uuid1 != uuid2);
970        assert!(uuid2 != uuid1);
971        assert!(uuid1_dup != uuid2);
972        assert!(uuid2 != uuid1_dup);
973    }
974
975    #[test]
976    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
977    fn test_uuid_to_string() {
978        use crate::std::fmt::Write;
979
980        let uuid = new();
981        let s = uuid.to_string();
982        let mut buffer = String::new();
983
984        assert_eq!(s.len(), 36);
985
986        check!(buffer, "{}", s, 36, |c| c.is_lowercase()
987            || c.is_digit(10)
988            || c == '-');
989    }
990
991    #[test]
992    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
993    fn test_nil() {
994        let nil = Uuid::nil();
995        let not_nil = new();
996        let from_bytes = Uuid::from_bytes([
997            4, 54, 67, 12, 43, 2, 2, 76, 32, 50, 87, 5, 1, 33, 43, 87,
998        ]);
999
1000        assert_eq!(from_bytes.get_version(), None);
1001
1002        assert!(nil.is_nil());
1003        assert!(!not_nil.is_nil());
1004
1005        assert_eq!(nil.get_version(), Some(Version::Nil));
1006        assert_eq!(not_nil.get_version(), Some(Version::Random))
1007    }
1008
1009    #[test]
1010    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1011    fn test_predefined_namespaces() {
1012        assert_eq!(
1013            Uuid::NAMESPACE_DNS.hyphenated().to_string(),
1014            "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
1015        );
1016        assert_eq!(
1017            Uuid::NAMESPACE_URL.hyphenated().to_string(),
1018            "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
1019        );
1020        assert_eq!(
1021            Uuid::NAMESPACE_OID.hyphenated().to_string(),
1022            "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
1023        );
1024        assert_eq!(
1025            Uuid::NAMESPACE_X500.hyphenated().to_string(),
1026            "6ba7b814-9dad-11d1-80b4-00c04fd430c8"
1027        );
1028    }
1029
1030    #[cfg(feature = "v3")]
1031    #[test]
1032    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1033    fn test_get_version_v3() {
1034        let uuid =
1035            Uuid::new_v3(&Uuid::NAMESPACE_DNS, "rust-lang.org".as_bytes());
1036
1037        assert_eq!(uuid.get_version().unwrap(), Version::Md5);
1038        assert_eq!(uuid.get_version_num(), 3);
1039    }
1040
1041    #[test]
1042    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1043    fn test_get_variant() {
1044        let uuid1 = new();
1045        let uuid2 =
1046            Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
1047        let uuid3 =
1048            Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8").unwrap();
1049        let uuid4 =
1050            Uuid::parse_str("936DA01F9ABD4d9dC0C702AF85C822A8").unwrap();
1051        let uuid5 =
1052            Uuid::parse_str("F9168C5E-CEB2-4faa-D6BF-329BF39FA1E4").unwrap();
1053        let uuid6 =
1054            Uuid::parse_str("f81d4fae-7dec-11d0-7765-00a0c91e6bf6").unwrap();
1055
1056        assert_eq!(uuid1.get_variant(), Variant::RFC4122);
1057        assert_eq!(uuid2.get_variant(), Variant::RFC4122);
1058        assert_eq!(uuid3.get_variant(), Variant::RFC4122);
1059        assert_eq!(uuid4.get_variant(), Variant::Microsoft);
1060        assert_eq!(uuid5.get_variant(), Variant::Microsoft);
1061        assert_eq!(uuid6.get_variant(), Variant::NCS);
1062    }
1063
1064    #[test]
1065    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1066    fn test_to_simple_string() {
1067        let uuid1 = new();
1068        let s = uuid1.simple().to_string();
1069
1070        assert_eq!(s.len(), 32);
1071        assert!(s.chars().all(|c| c.is_digit(16)));
1072    }
1073
1074    #[test]
1075    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1076    fn test_hyphenated_string() {
1077        let uuid1 = new();
1078        let s = uuid1.hyphenated().to_string();
1079
1080        assert!(s.len() == 36);
1081        assert!(s.chars().all(|c| c.is_digit(16) || c == '-'));
1082    }
1083
1084    #[test]
1085    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1086    fn test_upper_lower_hex() {
1087        use std::fmt::Write;
1088
1089        let mut buf = String::new();
1090        let u = new();
1091
1092        macro_rules! check {
1093            ($buf:ident, $format:expr, $target:expr, $len:expr, $cond:expr) => {
1094                $buf.clear();
1095                write!($buf, $format, $target).unwrap();
1096                assert_eq!($len, buf.len());
1097                assert!($buf.chars().all($cond), "{}", $buf);
1098            };
1099        }
1100
1101        check!(buf, "{:x}", u, 36, |c| c.is_lowercase()
1102            || c.is_digit(10)
1103            || c == '-');
1104        check!(buf, "{:X}", u, 36, |c| c.is_uppercase()
1105            || c.is_digit(10)
1106            || c == '-');
1107        check!(buf, "{:#x}", u, 32, |c| c.is_lowercase() || c.is_digit(10));
1108        check!(buf, "{:#X}", u, 32, |c| c.is_uppercase() || c.is_digit(10));
1109
1110        check!(buf, "{:X}", u.hyphenated(), 36, |c| c.is_uppercase()
1111            || c.is_digit(10)
1112            || c == '-');
1113        check!(buf, "{:X}", u.simple(), 32, |c| c.is_uppercase()
1114            || c.is_digit(10));
1115        check!(buf, "{:#X}", u.hyphenated(), 36, |c| c.is_uppercase()
1116            || c.is_digit(10)
1117            || c == '-');
1118        check!(buf, "{:#X}", u.simple(), 32, |c| c.is_uppercase()
1119            || c.is_digit(10));
1120
1121        check!(buf, "{:x}", u.hyphenated(), 36, |c| c.is_lowercase()
1122            || c.is_digit(10)
1123            || c == '-');
1124        check!(buf, "{:x}", u.simple(), 32, |c| c.is_lowercase()
1125            || c.is_digit(10));
1126        check!(buf, "{:#x}", u.hyphenated(), 36, |c| c.is_lowercase()
1127            || c.is_digit(10)
1128            || c == '-');
1129        check!(buf, "{:#x}", u.simple(), 32, |c| c.is_lowercase()
1130            || c.is_digit(10));
1131    }
1132
1133    #[test]
1134    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1135    fn test_to_urn_string() {
1136        let uuid1 = new();
1137        let ss = uuid1.urn().to_string();
1138        let s = &ss[9..];
1139
1140        assert!(ss.starts_with("urn:uuid:"));
1141        assert_eq!(s.len(), 36);
1142        assert!(s.chars().all(|c| c.is_digit(16) || c == '-'));
1143    }
1144
1145    #[test]
1146    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1147    fn test_to_simple_string_matching() {
1148        let uuid1 = new();
1149
1150        let hs = uuid1.hyphenated().to_string();
1151        let ss = uuid1.simple().to_string();
1152
1153        let hsn = hs.chars().filter(|&c| c != '-').collect::<String>();
1154
1155        assert_eq!(hsn, ss);
1156    }
1157
1158    #[test]
1159    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1160    fn test_string_roundtrip() {
1161        let uuid = new();
1162
1163        let hs = uuid.hyphenated().to_string();
1164        let uuid_hs = Uuid::parse_str(&hs).unwrap();
1165        assert_eq!(uuid_hs, uuid);
1166
1167        let ss = uuid.to_string();
1168        let uuid_ss = Uuid::parse_str(&ss).unwrap();
1169        assert_eq!(uuid_ss, uuid);
1170    }
1171
1172    #[test]
1173    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1174    fn test_from_fields() {
1175        let d1: u32 = 0xa1a2a3a4;
1176        let d2: u16 = 0xb1b2;
1177        let d3: u16 = 0xc1c2;
1178        let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1179
1180        let u = Uuid::from_fields(d1, d2, d3, &d4);
1181
1182        let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1183        let result = u.simple().to_string();
1184        assert_eq!(result, expected);
1185    }
1186
1187    #[test]
1188    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1189    fn test_from_fields_le() {
1190        let d1: u32 = 0xa4a3a2a1;
1191        let d2: u16 = 0xb2b1;
1192        let d3: u16 = 0xc2c1;
1193        let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1194
1195        let u = Uuid::from_fields_le(d1, d2, d3, &d4);
1196
1197        let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1198        let result = u.simple().to_string();
1199        assert_eq!(result, expected);
1200    }
1201
1202    #[test]
1203    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1204    fn test_as_fields() {
1205        let u = new();
1206        let (d1, d2, d3, d4) = u.as_fields();
1207
1208        assert_ne!(d1, 0);
1209        assert_ne!(d2, 0);
1210        assert_ne!(d3, 0);
1211        assert_eq!(d4.len(), 8);
1212        assert!(!d4.iter().all(|&b| b == 0));
1213    }
1214
1215    #[test]
1216    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1217    fn test_fields_roundtrip() {
1218        let d1_in: u32 = 0xa1a2a3a4;
1219        let d2_in: u16 = 0xb1b2;
1220        let d3_in: u16 = 0xc1c2;
1221        let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1222
1223        let u = Uuid::from_fields(d1_in, d2_in, d3_in, d4_in);
1224        let (d1_out, d2_out, d3_out, d4_out) = u.as_fields();
1225
1226        assert_eq!(d1_in, d1_out);
1227        assert_eq!(d2_in, d2_out);
1228        assert_eq!(d3_in, d3_out);
1229        assert_eq!(d4_in, d4_out);
1230    }
1231
1232    #[test]
1233    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1234    fn test_fields_le_roundtrip() {
1235        let d1_in: u32 = 0xa4a3a2a1;
1236        let d2_in: u16 = 0xb2b1;
1237        let d3_in: u16 = 0xc2c1;
1238        let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1239
1240        let u = Uuid::from_fields_le(d1_in, d2_in, d3_in, d4_in);
1241        let (d1_out, d2_out, d3_out, d4_out) = u.to_fields_le();
1242
1243        assert_eq!(d1_in, d1_out);
1244        assert_eq!(d2_in, d2_out);
1245        assert_eq!(d3_in, d3_out);
1246        assert_eq!(d4_in, d4_out);
1247    }
1248
1249    #[test]
1250    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1251    fn test_fields_le_are_actually_le() {
1252        let d1_in: u32 = 0xa1a2a3a4;
1253        let d2_in: u16 = 0xb1b2;
1254        let d3_in: u16 = 0xc1c2;
1255        let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1256
1257        let u = Uuid::from_fields(d1_in, d2_in, d3_in, d4_in);
1258        let (d1_out, d2_out, d3_out, d4_out) = u.to_fields_le();
1259
1260        assert_eq!(d1_in, d1_out.swap_bytes());
1261        assert_eq!(d2_in, d2_out.swap_bytes());
1262        assert_eq!(d3_in, d3_out.swap_bytes());
1263        assert_eq!(d4_in, d4_out);
1264    }
1265
1266    #[test]
1267    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1268    fn test_from_u128() {
1269        let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
1270
1271        let u = Uuid::from_u128(v_in);
1272
1273        let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1274        let result = u.simple().to_string();
1275        assert_eq!(result, expected);
1276    }
1277
1278    #[test]
1279    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1280    fn test_from_u128_le() {
1281        let v_in: u128 = 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1;
1282
1283        let u = Uuid::from_u128_le(v_in);
1284
1285        let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1286        let result = u.simple().to_string();
1287        assert_eq!(result, expected);
1288    }
1289
1290    #[test]
1291    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1292    fn test_from_u64_pair() {
1293        let high_in: u64 = 0xa1a2a3a4b1b2c1c2;
1294        let low_in: u64 = 0xd1d2d3d4d5d6d7d8;
1295
1296        let u = Uuid::from_u64_pair(high_in, low_in);
1297
1298        let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1299        let result = u.simple().to_string();
1300        assert_eq!(result, expected);
1301    }
1302
1303    #[test]
1304    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1305    fn test_u128_roundtrip() {
1306        let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
1307
1308        let u = Uuid::from_u128(v_in);
1309        let v_out = u.as_u128();
1310
1311        assert_eq!(v_in, v_out);
1312    }
1313
1314    #[test]
1315    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1316    fn test_u128_le_roundtrip() {
1317        let v_in: u128 = 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1;
1318
1319        let u = Uuid::from_u128_le(v_in);
1320        let v_out = u.to_u128_le();
1321
1322        assert_eq!(v_in, v_out);
1323    }
1324
1325    #[test]
1326    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1327    fn test_u64_pair_roundtrip() {
1328        let high_in: u64 = 0xa1a2a3a4b1b2c1c2;
1329        let low_in: u64 = 0xd1d2d3d4d5d6d7d8;
1330
1331        let u = Uuid::from_u64_pair(high_in, low_in);
1332        let (high_out, low_out) = u.as_u64_pair();
1333
1334        assert_eq!(high_in, high_out);
1335        assert_eq!(low_in, low_out);
1336    }
1337
1338    #[test]
1339    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1340    fn test_u128_le_is_actually_le() {
1341        let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
1342
1343        let u = Uuid::from_u128(v_in);
1344        let v_out = u.to_u128_le();
1345
1346        assert_eq!(v_in, v_out.swap_bytes());
1347    }
1348
1349    #[test]
1350    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1351    fn test_from_slice() {
1352        let b = [
1353            0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3,
1354            0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
1355        ];
1356
1357        let u = Uuid::from_slice(&b).unwrap();
1358        let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1359
1360        assert_eq!(u.simple().to_string(), expected);
1361    }
1362
1363    #[test]
1364    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1365    fn test_from_bytes() {
1366        let b = [
1367            0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3,
1368            0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
1369        ];
1370
1371        let u = Uuid::from_bytes(b);
1372        let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1373
1374        assert_eq!(u.simple().to_string(), expected);
1375    }
1376
1377    #[test]
1378    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1379    fn test_as_bytes() {
1380        let u = new();
1381        let ub = u.as_bytes();
1382        let ur = u.as_ref();
1383
1384        assert_eq!(ub.len(), 16);
1385        assert_eq!(ur.len(), 16);
1386        assert!(!ub.iter().all(|&b| b == 0));
1387        assert!(!ur.iter().all(|&b| b == 0));
1388    }
1389
1390    #[test]
1391    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1392    fn test_bytes_roundtrip() {
1393        let b_in: crate::Bytes = [
1394            0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3,
1395            0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
1396        ];
1397
1398        let u = Uuid::from_slice(&b_in).unwrap();
1399
1400        let b_out = u.as_bytes();
1401
1402        assert_eq!(&b_in, b_out);
1403    }
1404
1405    #[test]
1406    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1407    fn test_bytes_le_roundtrip() {
1408        let b = [
1409            0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3,
1410            0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
1411        ];
1412
1413        let u1 = Uuid::from_bytes(b);
1414
1415        let b_le = u1.to_bytes_le();
1416
1417        let u2 = Uuid::from_bytes_le(b_le);
1418
1419        assert_eq!(u1, u2);
1420    }
1421
1422    #[test]
1423    #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
1424    fn test_iterbytes_impl_for_uuid() {
1425        let mut set = std::collections::HashSet::new();
1426        let id1 = new();
1427        let id2 = new2();
1428        set.insert(id1.clone());
1429
1430        assert!(set.contains(&id1));
1431        assert!(!set.contains(&id2));
1432    }
1433}