1 // Copyright 2013-2014 The Rust Project Developers.
2 // Copyright 2018 The Uuid Project Developers.
3 //
4 // See the COPYRIGHT file at the top-level directory of this distribution.
5 //
6 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
7 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
8 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
9 // option. This file may not be copied, modified, or distributed
10 // except according to those terms.
11 
12 //! Generate and parse universally unique identifiers (UUIDs).
13 //!
14 //! Here's an example of a UUID:
15 //!
16 //! ```text
17 //! 67e55044-10b1-426f-9247-bb680e5fe0c8
18 //! ```
19 //!
20 //! A UUID is a unique 128-bit value, stored as 16 octets, and regularly
21 //! formatted as a hex string in five groups. UUIDs are used to assign unique
22 //! identifiers to entities without requiring a central allocating authority.
23 //!
24 //! They are particularly useful in distributed systems, though can be used in
25 //! disparate areas, such as databases and network protocols.  Typically a UUID
26 //! is displayed in a readable string form as a sequence of hexadecimal digits,
27 //! separated into groups by hyphens.
28 //!
29 //! The uniqueness property is not strictly guaranteed, however for all
30 //! practical purposes, it can be assumed that an unintentional collision would
31 //! be extremely unlikely.
32 //!
33 //! UUIDs have a number of standardized encodings that are specified in [RFC4122](http://tools.ietf.org/html/rfc4122),
34 //! with recent additions [in draft](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04).
35 //!
36 //! # Getting started
37 //!
38 //! Add the following to your `Cargo.toml`:
39 //!
40 //! ```toml
41 //! [dependencies.uuid]
42 //! version = "1.7.0"
43 //! features = [
44 //!     "v4",                # Lets you generate random UUIDs
45 //!     "fast-rng",          # Use a faster (but still sufficiently random) RNG
46 //!     "macro-diagnostics", # Enable better diagnostics for compile-time UUIDs
47 //! ]
48 //! ```
49 //!
50 //! When you want a UUID, you can generate one:
51 //!
52 //! ```
53 //! # fn main() {
54 //! # #[cfg(feature = "v4")]
55 //! # {
56 //! use uuid::Uuid;
57 //!
58 //! let id = Uuid::new_v4();
59 //! # }
60 //! # }
61 //! ```
62 //!
63 //! If you have a UUID value, you can use its string literal form inline:
64 //!
65 //! ```
66 //! use uuid::{uuid, Uuid};
67 //!
68 //! const ID: Uuid = uuid!("67e55044-10b1-426f-9247-bb680e5fe0c8");
69 //! ```
70 //!
71 //! # Working with different UUID versions
72 //!
73 //! This library supports all standardized methods for generating UUIDs through individual Cargo features.
74 //!
75 //! By default, this crate depends on nothing but the Rust standard library and can parse and format
76 //! UUIDs, but cannot generate them. Depending on the kind of UUID you'd like to work with, there
77 //! are Cargo features that enable generating them:
78 //!
79 //! * `v1` - Version 1 UUIDs using a timestamp and monotonic counter.
80 //! * `v3` - Version 3 UUIDs based on the MD5 hash of some data.
81 //! * `v4` - Version 4 UUIDs with random data.
82 //! * `v5` - Version 5 UUIDs based on the SHA1 hash of some data.
83 //! * `v6` - Version 6 UUIDs using a timestamp and monotonic counter.
84 //! * `v7` - Version 7 UUIDs using a Unix timestamp.
85 //! * `v8` - Version 8 UUIDs using user-defined data.
86 //!
87 //! Versions that are in draft are also supported. See the _unstable features_ section for details.
88 //!
89 //! This library also includes a [`Builder`] type that can be used to help construct UUIDs of any
90 //! version without any additional dependencies or features. It's a lower-level API than [`Uuid`]
91 //! that can be used when you need control over implicit requirements on things like a source
92 //! of randomness.
93 //!
94 //! ## Which UUID version should I use?
95 //!
96 //! If you just want to generate unique identifiers then consider version 4 (`v4`) UUIDs. If you want
97 //! to use UUIDs as database keys or need to sort them then consider version 7 (`v7`) UUIDs.
98 //! Other versions should generally be avoided unless there's an existing need for them.
99 //!
100 //! Some UUID versions supersede others. Prefer version 6 over version 1 and version 5 over version 3.
101 //!
102 //! # Other features
103 //!
104 //! Other crate features can also be useful beyond the version support:
105 //!
106 //! * `macro-diagnostics` - enhances the diagnostics of `uuid!` macro.
107 //! * `serde` - adds the ability to serialize and deserialize a UUID using
108 //!   `serde`.
109 //! * `borsh` - adds the ability to serialize and deserialize a UUID using
110 //!   `borsh`.
111 //! * `arbitrary` - adds an `Arbitrary` trait implementation to `Uuid` for
112 //!   fuzzing.
113 //! * `fast-rng` - uses a faster algorithm for generating random UUIDs.
114 //!   This feature requires more dependencies to compile, but is just as suitable for
115 //!   UUIDs as the default algorithm.
116 //! * `bytemuck` - adds a `Pod` trait implementation to `Uuid` for byte manipulation
117 //!
118 //! # Unstable features
119 //!
120 //! Some features are unstable. They may be incomplete or depend on other
121 //! unstable libraries. These include:
122 //!
123 //! * `zerocopy` - adds support for zero-copy deserialization using the
124 //!   `zerocopy` library.
125 //!
126 //! Unstable features may break between minor releases.
127 //!
128 //! To allow unstable features, you'll need to enable the Cargo feature as
129 //! normal, but also pass an additional flag through your environment to opt-in
130 //! to unstable `uuid` features:
131 //!
132 //! ```text
133 //! RUSTFLAGS="--cfg uuid_unstable"
134 //! ```
135 //!
136 //! # Building for other targets
137 //!
138 //! ## WebAssembly
139 //!
140 //! For WebAssembly, enable the `js` feature:
141 //!
142 //! ```toml
143 //! [dependencies.uuid]
144 //! version = "1.7.0"
145 //! features = [
146 //!     "v4",
147 //!     "v7",
148 //!     "js",
149 //! ]
150 //! ```
151 //!
152 //! ## Embedded
153 //!
154 //! For embedded targets without the standard library, you'll need to
155 //! disable default features when building `uuid`:
156 //!
157 //! ```toml
158 //! [dependencies.uuid]
159 //! version = "1.7.0"
160 //! default-features = false
161 //! ```
162 //!
163 //! Some additional features are supported in no-std environments:
164 //!
165 //! * `v1`, `v3`, `v5`, `v6`, and `v8`.
166 //! * `serde`.
167 //!
168 //! If you need to use `v4` or `v7` in a no-std environment, you'll need to
169 //! follow [`getrandom`'s docs] on configuring a source of randomness
170 //! on currently unsupported targets. Alternatively, you can produce
171 //! random bytes yourself and then pass them to [`Builder::from_random_bytes`]
172 //! without enabling the `v4` or `v7` features.
173 //!
174 //! # Examples
175 //!
176 //! Parse a UUID given in the simple format and print it as a URN:
177 //!
178 //! ```
179 //! # use uuid::Uuid;
180 //! # fn main() -> Result<(), uuid::Error> {
181 //! let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
182 //!
183 //! println!("{}", my_uuid.urn());
184 //! # Ok(())
185 //! # }
186 //! ```
187 //!
188 //! Generate a random UUID and print it out in hexadecimal form:
189 //!
190 //! ```
191 //! // Note that this requires the `v4` feature to be enabled.
192 //! # use uuid::Uuid;
193 //! # fn main() {
194 //! # #[cfg(feature = "v4")] {
195 //! let my_uuid = Uuid::new_v4();
196 //!
197 //! println!("{}", my_uuid);
198 //! # }
199 //! # }
200 //! ```
201 //!
202 //! # References
203 //!
204 //! * [Wikipedia: Universally Unique Identifier](http://en.wikipedia.org/wiki/Universally_unique_identifier)
205 //! * [RFC4122: A Universally Unique Identifier (UUID) URN Namespace](http://tools.ietf.org/html/rfc4122)
206 //! * [Draft RFC: New UUID Formats, Version 4](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04)
207 //!
208 //! [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
209 //! [`cargo-web`]: https://crates.io/crates/cargo-web
210 //! [`getrandom`'s docs]: https://docs.rs/getrandom
211 
212 #![no_std]
213 #![deny(missing_debug_implementations, missing_docs)]
214 #![doc(
215     html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
216     html_favicon_url = "https://www.rust-lang.org/favicon.ico",
217     html_root_url = "https://docs.rs/uuid/1.7.0"
218 )]
219 
220 #[cfg(any(feature = "std", test))]
221 #[macro_use]
222 extern crate std;
223 
224 #[cfg(all(not(feature = "std"), not(test)))]
225 #[macro_use]
226 extern crate core as std;
227 
228 #[cfg(all(uuid_unstable, feature = "zerocopy"))]
229 use zerocopy::{AsBytes, FromBytes, Unaligned};
230 
231 mod builder;
232 mod error;
233 mod parser;
234 
235 pub mod fmt;
236 pub mod timestamp;
237 
238 pub use timestamp::{context::NoContext, ClockSequence, Timestamp};
239 
240 #[cfg(any(feature = "v1", feature = "v6"))]
241 pub use timestamp::context::Context;
242 
243 #[cfg(feature = "v1")]
244 #[doc(hidden)]
245 // Soft-deprecated (Rust doesn't support deprecating re-exports)
246 // Use `Context` from the crate root instead
247 pub mod v1;
248 #[cfg(feature = "v3")]
249 mod v3;
250 #[cfg(feature = "v4")]
251 mod v4;
252 #[cfg(feature = "v5")]
253 mod v5;
254 #[cfg(feature = "v6")]
255 mod v6;
256 #[cfg(feature = "v7")]
257 mod v7;
258 #[cfg(feature = "v8")]
259 mod v8;
260 
261 #[cfg(feature = "md5")]
262 mod md5;
263 #[cfg(feature = "rng")]
264 mod rng;
265 #[cfg(feature = "sha1")]
266 mod sha1;
267 
268 mod external;
269 
270 #[macro_use]
271 mod macros;
272 
273 #[doc(hidden)]
274 #[cfg(feature = "macro-diagnostics")]
275 pub extern crate uuid_macro_internal;
276 
277 #[doc(hidden)]
278 pub mod __macro_support {
279     pub use crate::std::result::Result::{Err, Ok};
280 }
281 
282 use crate::std::convert;
283 
284 pub use crate::{builder::Builder, error::Error};
285 
286 /// A 128-bit (16 byte) buffer containing the UUID.
287 ///
288 /// # ABI
289 ///
290 /// The `Bytes` type is always guaranteed to be have the same ABI as [`Uuid`].
291 pub type Bytes = [u8; 16];
292 
293 /// The version of the UUID, denoting the generating algorithm.
294 ///
295 /// # References
296 ///
297 /// * [Version in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.3)
298 #[derive(Clone, Copy, Debug, PartialEq)]
299 #[non_exhaustive]
300 #[repr(u8)]
301 pub enum Version {
302     /// The "nil" (all zeros) UUID.
303     Nil = 0u8,
304     /// Version 1: Timestamp and node ID.
305     Mac = 1,
306     /// Version 2: DCE Security.
307     Dce = 2,
308     /// Version 3: MD5 hash.
309     Md5 = 3,
310     /// Version 4: Random.
311     Random = 4,
312     /// Version 5: SHA-1 hash.
313     Sha1 = 5,
314     /// Version 6: Sortable Timestamp and node ID.
315     SortMac = 6,
316     /// Version 7: Timestamp and random.
317     SortRand = 7,
318     /// Version 8: Custom.
319     Custom = 8,
320     /// The "max" (all ones) UUID.
321     Max = 0xff,
322 }
323 
324 /// The reserved variants of UUIDs.
325 ///
326 /// # References
327 ///
328 /// * [Variant in RFC4122](http://tools.ietf.org/html/rfc4122#section-4.1.1)
329 #[derive(Clone, Copy, Debug, PartialEq)]
330 #[non_exhaustive]
331 #[repr(u8)]
332 pub enum Variant {
333     /// Reserved by the NCS for backward compatibility.
334     NCS = 0u8,
335     /// As described in the RFC4122 Specification (default).
336     RFC4122,
337     /// Reserved by Microsoft for backward compatibility.
338     Microsoft,
339     /// Reserved for future expansion.
340     Future,
341 }
342 
343 /// A Universally Unique Identifier (UUID).
344 ///
345 /// # Examples
346 ///
347 /// Parse a UUID given in the simple format and print it as a urn:
348 ///
349 /// ```
350 /// # use uuid::Uuid;
351 /// # fn main() -> Result<(), uuid::Error> {
352 /// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
353 ///
354 /// println!("{}", my_uuid.urn());
355 /// # Ok(())
356 /// # }
357 /// ```
358 ///
359 /// Create a new random (V4) UUID and print it out in hexadecimal form:
360 ///
361 /// ```
362 /// // Note that this requires the `v4` feature enabled in the uuid crate.
363 /// # use uuid::Uuid;
364 /// # fn main() {
365 /// # #[cfg(feature = "v4")] {
366 /// let my_uuid = Uuid::new_v4();
367 ///
368 /// println!("{}", my_uuid);
369 /// # }
370 /// # }
371 /// ```
372 ///
373 /// # Formatting
374 ///
375 /// A UUID can be formatted in one of a few ways:
376 ///
377 /// * [`simple`](#method.simple): `a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8`.
378 /// * [`hyphenated`](#method.hyphenated):
379 ///   `a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8`.
380 /// * [`urn`](#method.urn): `urn:uuid:A1A2A3A4-B1B2-C1C2-D1D2-D3D4D5D6D7D8`.
381 /// * [`braced`](#method.braced): `{a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8}`.
382 ///
383 /// The default representation when formatting a UUID with `Display` is
384 /// hyphenated:
385 ///
386 /// ```
387 /// # use uuid::Uuid;
388 /// # fn main() -> Result<(), uuid::Error> {
389 /// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
390 ///
391 /// assert_eq!(
392 ///     "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
393 ///     my_uuid.to_string(),
394 /// );
395 /// # Ok(())
396 /// # }
397 /// ```
398 ///
399 /// Other formats can be specified using adapter methods on the UUID:
400 ///
401 /// ```
402 /// # use uuid::Uuid;
403 /// # fn main() -> Result<(), uuid::Error> {
404 /// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
405 ///
406 /// assert_eq!(
407 ///     "urn:uuid:a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
408 ///     my_uuid.urn().to_string(),
409 /// );
410 /// # Ok(())
411 /// # }
412 /// ```
413 ///
414 /// # Endianness
415 ///
416 /// The specification for UUIDs encodes the integer fields that make up the
417 /// value in big-endian order. This crate assumes integer inputs are already in
418 /// the correct order by default, regardless of the endianness of the
419 /// environment. Most methods that accept integers have a `_le` variant (such as
420 /// `from_fields_le`) that assumes any integer values will need to have their
421 /// bytes flipped, regardless of the endianness of the environment.
422 ///
423 /// Most users won't need to worry about endianness unless they need to operate
424 /// on individual fields (such as when converting between Microsoft GUIDs). The
425 /// important things to remember are:
426 ///
427 /// - The endianness is in terms of the fields of the UUID, not the environment.
428 /// - The endianness is assumed to be big-endian when there's no `_le` suffix
429 ///   somewhere.
430 /// - Byte-flipping in `_le` methods applies to each integer.
431 /// - Endianness roundtrips, so if you create a UUID with `from_fields_le`
432 ///   you'll get the same values back out with `to_fields_le`.
433 ///
434 /// # ABI
435 ///
436 /// The `Uuid` type is always guaranteed to be have the same ABI as [`Bytes`].
437 #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
438 #[cfg_attr(
439     all(uuid_unstable, feature = "zerocopy"),
440     derive(AsBytes, FromBytes, Unaligned)
441 )]
442 #[cfg_attr(
443     feature = "borsh",
444     derive(borsh_derive::BorshDeserialize, borsh_derive::BorshSerialize)
445 )]
446 #[repr(transparent)]
447 #[cfg_attr(
448     feature = "bytemuck",
449     derive(bytemuck::Zeroable, bytemuck::Pod, bytemuck::TransparentWrapper)
450 )]
451 pub struct Uuid(Bytes);
452 
453 impl 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 in RFC4122](http://tools.ietf.org/html/rfc4122#section-4.1.1)
get_variant(&self) -> Variant501     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 in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.3)
get_version_num(&self) -> usize536     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 in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.3)
get_version(&self) -> Option<Version>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     /// ```
as_fields(&self) -> (u32, u16, u16, &[u8; 8])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     /// ```
to_fields_le(&self) -> (u32, u16, u16, &[u8; 8])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     /// ```
as_u128(&self) -> u128700     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     /// ```
to_u128_le(&self) -> u128729     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     /// ```
as_u64_pair(&self) -> (u64, u64)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]
as_bytes(&self) -> &Bytes784     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]
into_bytes(self) -> Bytes804     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     /// ```
to_bytes_le(&self) -> Bytes832     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).
is_nil(&self) -> bool841     pub const fn is_nil(&self) -> bool {
842         self.as_u128() == u128::MIN
843     }
844 
845     /// Tests if the UUID is max (all ones).
is_max(&self) -> bool846     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     /// ```
encode_buffer() -> [u8; fmt::Urn::LENGTH]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 and counter portion parsed from a V1 UUID.
881     ///
882     /// Returns `None` if the supplied UUID is not V1.
883     ///
884     /// The V1 timestamp format defined in RFC4122 specifies a 60-bit
885     /// integer representing the number of 100-nanosecond intervals
886     /// since 00:00:00.00, 15 Oct 1582.
887     ///
888     /// [`Timestamp`] offers several options for converting the raw RFC4122
889     /// value into more commonly-used formats, such as a unix timestamp.
890     ///
891     /// # Roundtripping
892     ///
893     /// This method is unlikely to roundtrip a timestamp in a UUID due to the way
894     /// UUIDs encode timestamps. The timestamp returned from this method will be truncated to
895     /// 100ns precision for version 1 and 6 UUIDs, and to millisecond precision for version 7 UUIDs.
896     ///
897     /// [`Timestamp`]: v1/struct.Timestamp.html
get_timestamp(&self) -> Option<Timestamp>898     pub const fn get_timestamp(&self) -> Option<Timestamp> {
899         match self.get_version() {
900             Some(Version::Mac) => {
901                 let (ticks, counter) = timestamp::decode_rfc4122_timestamp(self);
902 
903                 Some(Timestamp::from_rfc4122(ticks, counter))
904             }
905             Some(Version::SortMac) => {
906                 let (ticks, counter) = timestamp::decode_sorted_rfc4122_timestamp(self);
907 
908                 Some(Timestamp::from_rfc4122(ticks, counter))
909             }
910             Some(Version::SortRand) => {
911                 let millis = timestamp::decode_unix_timestamp_millis(self);
912 
913                 let seconds = millis / 1000;
914                 let nanos = ((millis % 1000) * 1_000_000) as u32;
915 
916                 Some(Timestamp {
917                     seconds,
918                     nanos,
919                     #[cfg(any(feature = "v1", feature = "v6"))]
920                     counter: 0,
921                 })
922             }
923             _ => None,
924         }
925     }
926 }
927 
928 impl Default for Uuid {
929     #[inline]
default() -> Self930     fn default() -> Self {
931         Uuid::nil()
932     }
933 }
934 
935 impl AsRef<[u8]> for Uuid {
936     #[inline]
as_ref(&self) -> &[u8]937     fn as_ref(&self) -> &[u8] {
938         &self.0
939     }
940 }
941 
942 #[cfg(feature = "std")]
943 impl From<Uuid> for std::vec::Vec<u8> {
from(value: Uuid) -> Self944     fn from(value: Uuid) -> Self {
945         value.0.to_vec()
946     }
947 }
948 
949 #[cfg(feature = "std")]
950 impl std::convert::TryFrom<std::vec::Vec<u8>> for Uuid {
951     type Error = Error;
952 
try_from(value: std::vec::Vec<u8>) -> Result<Self, Self::Error>953     fn try_from(value: std::vec::Vec<u8>) -> Result<Self, Self::Error> {
954         Uuid::from_slice(&value)
955     }
956 }
957 
958 #[cfg(feature = "serde")]
959 pub mod serde {
960     //! Adapters for alternative `serde` formats.
961     //!
962     //! This module contains adapters you can use with [`#[serde(with)]`](https://serde.rs/field-attrs.html#with)
963     //! to change the way a [`Uuid`](../struct.Uuid.html) is serialized
964     //! and deserialized.
965 
966     pub use crate::external::serde_support::compact;
967 }
968 
969 #[cfg(test)]
970 mod tests {
971     use super::*;
972 
973     use crate::std::string::{String, ToString};
974 
975     #[cfg(all(
976         target_arch = "wasm32",
977         target_vendor = "unknown",
978         target_os = "unknown"
979     ))]
980     use wasm_bindgen_test::*;
981 
982     macro_rules! check {
983         ($buf:ident, $format:expr, $target:expr, $len:expr, $cond:expr) => {
984             $buf.clear();
985             write!($buf, $format, $target).unwrap();
986             assert!($buf.len() == $len);
987             assert!($buf.chars().all($cond), "{}", $buf);
988         };
989     }
990 
new() -> Uuid991     pub const fn new() -> Uuid {
992         Uuid::from_bytes([
993             0xF9, 0x16, 0x8C, 0x5E, 0xCE, 0xB2, 0x4F, 0xAA, 0xB6, 0xBF, 0x32, 0x9B, 0xF3, 0x9F,
994             0xA1, 0xE4,
995         ])
996     }
997 
new2() -> Uuid998     pub const fn new2() -> Uuid {
999         Uuid::from_bytes([
1000             0xF9, 0x16, 0x8C, 0x5E, 0xCE, 0xB2, 0x4F, 0xAB, 0xB6, 0xBF, 0x32, 0x9B, 0xF3, 0x9F,
1001             0xA1, 0xE4,
1002         ])
1003     }
1004 
1005     #[test]
1006     #[cfg_attr(
1007         all(
1008             target_arch = "wasm32",
1009             target_vendor = "unknown",
1010             target_os = "unknown"
1011         ),
1012         wasm_bindgen_test
1013     )]
test_uuid_compare()1014     fn test_uuid_compare() {
1015         let uuid1 = new();
1016         let uuid2 = new2();
1017 
1018         assert_eq!(uuid1, uuid1);
1019         assert_eq!(uuid2, uuid2);
1020 
1021         assert_ne!(uuid1, uuid2);
1022         assert_ne!(uuid2, uuid1);
1023     }
1024 
1025     #[test]
1026     #[cfg_attr(
1027         all(
1028             target_arch = "wasm32",
1029             target_vendor = "unknown",
1030             target_os = "unknown"
1031         ),
1032         wasm_bindgen_test
1033     )]
test_uuid_default()1034     fn test_uuid_default() {
1035         let default_uuid = Uuid::default();
1036         let nil_uuid = Uuid::nil();
1037 
1038         assert_eq!(default_uuid, nil_uuid);
1039     }
1040 
1041     #[test]
1042     #[cfg_attr(
1043         all(
1044             target_arch = "wasm32",
1045             target_vendor = "unknown",
1046             target_os = "unknown"
1047         ),
1048         wasm_bindgen_test
1049     )]
test_uuid_display()1050     fn test_uuid_display() {
1051         use crate::std::fmt::Write;
1052 
1053         let uuid = new();
1054         let s = uuid.to_string();
1055         let mut buffer = String::new();
1056 
1057         assert_eq!(s, uuid.hyphenated().to_string());
1058 
1059         check!(buffer, "{}", uuid, 36, |c| c.is_lowercase()
1060             || c.is_digit(10)
1061             || c == '-');
1062     }
1063 
1064     #[test]
1065     #[cfg_attr(
1066         all(
1067             target_arch = "wasm32",
1068             target_vendor = "unknown",
1069             target_os = "unknown"
1070         ),
1071         wasm_bindgen_test
1072     )]
test_uuid_lowerhex()1073     fn test_uuid_lowerhex() {
1074         use crate::std::fmt::Write;
1075 
1076         let mut buffer = String::new();
1077         let uuid = new();
1078 
1079         check!(buffer, "{:x}", uuid, 36, |c| c.is_lowercase()
1080             || c.is_digit(10)
1081             || c == '-');
1082     }
1083 
1084     // noinspection RsAssertEqual
1085     #[test]
1086     #[cfg_attr(
1087         all(
1088             target_arch = "wasm32",
1089             target_vendor = "unknown",
1090             target_os = "unknown"
1091         ),
1092         wasm_bindgen_test
1093     )]
test_uuid_operator_eq()1094     fn test_uuid_operator_eq() {
1095         let uuid1 = new();
1096         let uuid1_dup = uuid1.clone();
1097         let uuid2 = new2();
1098 
1099         assert!(uuid1 == uuid1);
1100         assert!(uuid1 == uuid1_dup);
1101         assert!(uuid1_dup == uuid1);
1102 
1103         assert!(uuid1 != uuid2);
1104         assert!(uuid2 != uuid1);
1105         assert!(uuid1_dup != uuid2);
1106         assert!(uuid2 != uuid1_dup);
1107     }
1108 
1109     #[test]
1110     #[cfg_attr(
1111         all(
1112             target_arch = "wasm32",
1113             target_vendor = "unknown",
1114             target_os = "unknown"
1115         ),
1116         wasm_bindgen_test
1117     )]
test_uuid_to_string()1118     fn test_uuid_to_string() {
1119         use crate::std::fmt::Write;
1120 
1121         let uuid = new();
1122         let s = uuid.to_string();
1123         let mut buffer = String::new();
1124 
1125         assert_eq!(s.len(), 36);
1126 
1127         check!(buffer, "{}", s, 36, |c| c.is_lowercase()
1128             || c.is_digit(10)
1129             || c == '-');
1130     }
1131 
1132     #[test]
1133     #[cfg_attr(
1134         all(
1135             target_arch = "wasm32",
1136             target_vendor = "unknown",
1137             target_os = "unknown"
1138         ),
1139         wasm_bindgen_test
1140     )]
test_non_conforming()1141     fn test_non_conforming() {
1142         let from_bytes =
1143             Uuid::from_bytes([4, 54, 67, 12, 43, 2, 2, 76, 32, 50, 87, 5, 1, 33, 43, 87]);
1144 
1145         assert_eq!(from_bytes.get_version(), None);
1146     }
1147 
1148     #[test]
1149     #[cfg_attr(
1150         all(
1151             target_arch = "wasm32",
1152             target_vendor = "unknown",
1153             target_os = "unknown"
1154         ),
1155         wasm_bindgen_test
1156     )]
test_nil()1157     fn test_nil() {
1158         let nil = Uuid::nil();
1159         let not_nil = new();
1160 
1161         assert!(nil.is_nil());
1162         assert!(!not_nil.is_nil());
1163 
1164         assert_eq!(nil.get_version(), Some(Version::Nil));
1165         assert_eq!(not_nil.get_version(), Some(Version::Random));
1166 
1167         assert_eq!(
1168             nil,
1169             Builder::from_bytes([0; 16])
1170                 .with_version(Version::Nil)
1171                 .into_uuid()
1172         );
1173     }
1174 
1175     #[test]
1176     #[cfg_attr(
1177         all(
1178             target_arch = "wasm32",
1179             target_vendor = "unknown",
1180             target_os = "unknown"
1181         ),
1182         wasm_bindgen_test
1183     )]
test_max()1184     fn test_max() {
1185         let max = Uuid::max();
1186         let not_max = new();
1187 
1188         assert!(max.is_max());
1189         assert!(!not_max.is_max());
1190 
1191         assert_eq!(max.get_version(), Some(Version::Max));
1192         assert_eq!(not_max.get_version(), Some(Version::Random));
1193 
1194         assert_eq!(
1195             max,
1196             Builder::from_bytes([0xff; 16])
1197                 .with_version(Version::Max)
1198                 .into_uuid()
1199         );
1200     }
1201 
1202     #[test]
1203     #[cfg_attr(
1204         all(
1205             target_arch = "wasm32",
1206             target_vendor = "unknown",
1207             target_os = "unknown"
1208         ),
1209         wasm_bindgen_test
1210     )]
test_predefined_namespaces()1211     fn test_predefined_namespaces() {
1212         assert_eq!(
1213             Uuid::NAMESPACE_DNS.hyphenated().to_string(),
1214             "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
1215         );
1216         assert_eq!(
1217             Uuid::NAMESPACE_URL.hyphenated().to_string(),
1218             "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
1219         );
1220         assert_eq!(
1221             Uuid::NAMESPACE_OID.hyphenated().to_string(),
1222             "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
1223         );
1224         assert_eq!(
1225             Uuid::NAMESPACE_X500.hyphenated().to_string(),
1226             "6ba7b814-9dad-11d1-80b4-00c04fd430c8"
1227         );
1228     }
1229 
1230     #[cfg(feature = "v3")]
1231     #[test]
1232     #[cfg_attr(
1233         all(
1234             target_arch = "wasm32",
1235             target_vendor = "unknown",
1236             target_os = "unknown"
1237         ),
1238         wasm_bindgen_test
1239     )]
test_get_version_v3()1240     fn test_get_version_v3() {
1241         let uuid = Uuid::new_v3(&Uuid::NAMESPACE_DNS, "rust-lang.org".as_bytes());
1242 
1243         assert_eq!(uuid.get_version().unwrap(), Version::Md5);
1244         assert_eq!(uuid.get_version_num(), 3);
1245     }
1246 
1247     #[test]
1248     #[cfg_attr(
1249         all(
1250             target_arch = "wasm32",
1251             target_vendor = "unknown",
1252             target_os = "unknown"
1253         ),
1254         wasm_bindgen_test
1255     )]
test_get_variant()1256     fn test_get_variant() {
1257         let uuid1 = new();
1258         let uuid2 = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
1259         let uuid3 = Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8").unwrap();
1260         let uuid4 = Uuid::parse_str("936DA01F9ABD4d9dC0C702AF85C822A8").unwrap();
1261         let uuid5 = Uuid::parse_str("F9168C5E-CEB2-4faa-D6BF-329BF39FA1E4").unwrap();
1262         let uuid6 = Uuid::parse_str("f81d4fae-7dec-11d0-7765-00a0c91e6bf6").unwrap();
1263 
1264         assert_eq!(uuid1.get_variant(), Variant::RFC4122);
1265         assert_eq!(uuid2.get_variant(), Variant::RFC4122);
1266         assert_eq!(uuid3.get_variant(), Variant::RFC4122);
1267         assert_eq!(uuid4.get_variant(), Variant::Microsoft);
1268         assert_eq!(uuid5.get_variant(), Variant::Microsoft);
1269         assert_eq!(uuid6.get_variant(), Variant::NCS);
1270     }
1271 
1272     #[test]
1273     #[cfg_attr(
1274         all(
1275             target_arch = "wasm32",
1276             target_vendor = "unknown",
1277             target_os = "unknown"
1278         ),
1279         wasm_bindgen_test
1280     )]
test_to_simple_string()1281     fn test_to_simple_string() {
1282         let uuid1 = new();
1283         let s = uuid1.simple().to_string();
1284 
1285         assert_eq!(s.len(), 32);
1286         assert!(s.chars().all(|c| c.is_digit(16)));
1287     }
1288 
1289     #[test]
1290     #[cfg_attr(
1291         all(
1292             target_arch = "wasm32",
1293             target_vendor = "unknown",
1294             target_os = "unknown"
1295         ),
1296         wasm_bindgen_test
1297     )]
test_hyphenated_string()1298     fn test_hyphenated_string() {
1299         let uuid1 = new();
1300         let s = uuid1.hyphenated().to_string();
1301 
1302         assert_eq!(36, s.len());
1303         assert!(s.chars().all(|c| c.is_digit(16) || c == '-'));
1304     }
1305 
1306     #[test]
1307     #[cfg_attr(
1308         all(
1309             target_arch = "wasm32",
1310             target_vendor = "unknown",
1311             target_os = "unknown"
1312         ),
1313         wasm_bindgen_test
1314     )]
test_upper_lower_hex()1315     fn test_upper_lower_hex() {
1316         use std::fmt::Write;
1317 
1318         let mut buf = String::new();
1319         let u = new();
1320 
1321         macro_rules! check {
1322             ($buf:ident, $format:expr, $target:expr, $len:expr, $cond:expr) => {
1323                 $buf.clear();
1324                 write!($buf, $format, $target).unwrap();
1325                 assert_eq!($len, buf.len());
1326                 assert!($buf.chars().all($cond), "{}", $buf);
1327             };
1328         }
1329 
1330         check!(buf, "{:x}", u, 36, |c| c.is_lowercase()
1331             || c.is_digit(10)
1332             || c == '-');
1333         check!(buf, "{:X}", u, 36, |c| c.is_uppercase()
1334             || c.is_digit(10)
1335             || c == '-');
1336         check!(buf, "{:#x}", u, 36, |c| c.is_lowercase()
1337             || c.is_digit(10)
1338             || c == '-');
1339         check!(buf, "{:#X}", u, 36, |c| c.is_uppercase()
1340             || c.is_digit(10)
1341             || c == '-');
1342 
1343         check!(buf, "{:X}", u.hyphenated(), 36, |c| c.is_uppercase()
1344             || c.is_digit(10)
1345             || c == '-');
1346         check!(buf, "{:X}", u.simple(), 32, |c| c.is_uppercase()
1347             || c.is_digit(10));
1348         check!(buf, "{:#X}", u.hyphenated(), 36, |c| c.is_uppercase()
1349             || c.is_digit(10)
1350             || c == '-');
1351         check!(buf, "{:#X}", u.simple(), 32, |c| c.is_uppercase()
1352             || c.is_digit(10));
1353 
1354         check!(buf, "{:x}", u.hyphenated(), 36, |c| c.is_lowercase()
1355             || c.is_digit(10)
1356             || c == '-');
1357         check!(buf, "{:x}", u.simple(), 32, |c| c.is_lowercase()
1358             || c.is_digit(10));
1359         check!(buf, "{:#x}", u.hyphenated(), 36, |c| c.is_lowercase()
1360             || c.is_digit(10)
1361             || c == '-');
1362         check!(buf, "{:#x}", u.simple(), 32, |c| c.is_lowercase()
1363             || c.is_digit(10));
1364     }
1365 
1366     #[test]
1367     #[cfg_attr(
1368         all(
1369             target_arch = "wasm32",
1370             target_vendor = "unknown",
1371             target_os = "unknown"
1372         ),
1373         wasm_bindgen_test
1374     )]
test_to_urn_string()1375     fn test_to_urn_string() {
1376         let uuid1 = new();
1377         let ss = uuid1.urn().to_string();
1378         let s = &ss[9..];
1379 
1380         assert!(ss.starts_with("urn:uuid:"));
1381         assert_eq!(s.len(), 36);
1382         assert!(s.chars().all(|c| c.is_digit(16) || c == '-'));
1383     }
1384 
1385     #[test]
1386     #[cfg_attr(
1387         all(
1388             target_arch = "wasm32",
1389             target_vendor = "unknown",
1390             target_os = "unknown"
1391         ),
1392         wasm_bindgen_test
1393     )]
test_to_simple_string_matching()1394     fn test_to_simple_string_matching() {
1395         let uuid1 = new();
1396 
1397         let hs = uuid1.hyphenated().to_string();
1398         let ss = uuid1.simple().to_string();
1399 
1400         let hsn = hs.chars().filter(|&c| c != '-').collect::<String>();
1401 
1402         assert_eq!(hsn, ss);
1403     }
1404 
1405     #[test]
1406     #[cfg_attr(
1407         all(
1408             target_arch = "wasm32",
1409             target_vendor = "unknown",
1410             target_os = "unknown"
1411         ),
1412         wasm_bindgen_test
1413     )]
test_string_roundtrip()1414     fn test_string_roundtrip() {
1415         let uuid = new();
1416 
1417         let hs = uuid.hyphenated().to_string();
1418         let uuid_hs = Uuid::parse_str(&hs).unwrap();
1419         assert_eq!(uuid_hs, uuid);
1420 
1421         let ss = uuid.to_string();
1422         let uuid_ss = Uuid::parse_str(&ss).unwrap();
1423         assert_eq!(uuid_ss, uuid);
1424     }
1425 
1426     #[test]
1427     #[cfg_attr(
1428         all(
1429             target_arch = "wasm32",
1430             target_vendor = "unknown",
1431             target_os = "unknown"
1432         ),
1433         wasm_bindgen_test
1434     )]
test_from_fields()1435     fn test_from_fields() {
1436         let d1: u32 = 0xa1a2a3a4;
1437         let d2: u16 = 0xb1b2;
1438         let d3: u16 = 0xc1c2;
1439         let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1440 
1441         let u = Uuid::from_fields(d1, d2, d3, &d4);
1442 
1443         let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1444         let result = u.simple().to_string();
1445         assert_eq!(result, expected);
1446     }
1447 
1448     #[test]
1449     #[cfg_attr(
1450         all(
1451             target_arch = "wasm32",
1452             target_vendor = "unknown",
1453             target_os = "unknown"
1454         ),
1455         wasm_bindgen_test
1456     )]
test_from_fields_le()1457     fn test_from_fields_le() {
1458         let d1: u32 = 0xa4a3a2a1;
1459         let d2: u16 = 0xb2b1;
1460         let d3: u16 = 0xc2c1;
1461         let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1462 
1463         let u = Uuid::from_fields_le(d1, d2, d3, &d4);
1464 
1465         let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1466         let result = u.simple().to_string();
1467         assert_eq!(result, expected);
1468     }
1469 
1470     #[test]
1471     #[cfg_attr(
1472         all(
1473             target_arch = "wasm32",
1474             target_vendor = "unknown",
1475             target_os = "unknown"
1476         ),
1477         wasm_bindgen_test
1478     )]
test_as_fields()1479     fn test_as_fields() {
1480         let u = new();
1481         let (d1, d2, d3, d4) = u.as_fields();
1482 
1483         assert_ne!(d1, 0);
1484         assert_ne!(d2, 0);
1485         assert_ne!(d3, 0);
1486         assert_eq!(d4.len(), 8);
1487         assert!(!d4.iter().all(|&b| b == 0));
1488     }
1489 
1490     #[test]
1491     #[cfg_attr(
1492         all(
1493             target_arch = "wasm32",
1494             target_vendor = "unknown",
1495             target_os = "unknown"
1496         ),
1497         wasm_bindgen_test
1498     )]
test_fields_roundtrip()1499     fn test_fields_roundtrip() {
1500         let d1_in: u32 = 0xa1a2a3a4;
1501         let d2_in: u16 = 0xb1b2;
1502         let d3_in: u16 = 0xc1c2;
1503         let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1504 
1505         let u = Uuid::from_fields(d1_in, d2_in, d3_in, d4_in);
1506         let (d1_out, d2_out, d3_out, d4_out) = u.as_fields();
1507 
1508         assert_eq!(d1_in, d1_out);
1509         assert_eq!(d2_in, d2_out);
1510         assert_eq!(d3_in, d3_out);
1511         assert_eq!(d4_in, d4_out);
1512     }
1513 
1514     #[test]
1515     #[cfg_attr(
1516         all(
1517             target_arch = "wasm32",
1518             target_vendor = "unknown",
1519             target_os = "unknown"
1520         ),
1521         wasm_bindgen_test
1522     )]
test_fields_le_roundtrip()1523     fn test_fields_le_roundtrip() {
1524         let d1_in: u32 = 0xa4a3a2a1;
1525         let d2_in: u16 = 0xb2b1;
1526         let d3_in: u16 = 0xc2c1;
1527         let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1528 
1529         let u = Uuid::from_fields_le(d1_in, d2_in, d3_in, d4_in);
1530         let (d1_out, d2_out, d3_out, d4_out) = u.to_fields_le();
1531 
1532         assert_eq!(d1_in, d1_out);
1533         assert_eq!(d2_in, d2_out);
1534         assert_eq!(d3_in, d3_out);
1535         assert_eq!(d4_in, d4_out);
1536     }
1537 
1538     #[test]
1539     #[cfg_attr(
1540         all(
1541             target_arch = "wasm32",
1542             target_vendor = "unknown",
1543             target_os = "unknown"
1544         ),
1545         wasm_bindgen_test
1546     )]
test_fields_le_are_actually_le()1547     fn test_fields_le_are_actually_le() {
1548         let d1_in: u32 = 0xa1a2a3a4;
1549         let d2_in: u16 = 0xb1b2;
1550         let d3_in: u16 = 0xc1c2;
1551         let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1552 
1553         let u = Uuid::from_fields(d1_in, d2_in, d3_in, d4_in);
1554         let (d1_out, d2_out, d3_out, d4_out) = u.to_fields_le();
1555 
1556         assert_eq!(d1_in, d1_out.swap_bytes());
1557         assert_eq!(d2_in, d2_out.swap_bytes());
1558         assert_eq!(d3_in, d3_out.swap_bytes());
1559         assert_eq!(d4_in, d4_out);
1560     }
1561 
1562     #[test]
1563     #[cfg_attr(
1564         all(
1565             target_arch = "wasm32",
1566             target_vendor = "unknown",
1567             target_os = "unknown"
1568         ),
1569         wasm_bindgen_test
1570     )]
test_from_u128()1571     fn test_from_u128() {
1572         let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
1573 
1574         let u = Uuid::from_u128(v_in);
1575 
1576         let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1577         let result = u.simple().to_string();
1578         assert_eq!(result, expected);
1579     }
1580 
1581     #[test]
1582     #[cfg_attr(
1583         all(
1584             target_arch = "wasm32",
1585             target_vendor = "unknown",
1586             target_os = "unknown"
1587         ),
1588         wasm_bindgen_test
1589     )]
test_from_u128_le()1590     fn test_from_u128_le() {
1591         let v_in: u128 = 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1;
1592 
1593         let u = Uuid::from_u128_le(v_in);
1594 
1595         let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1596         let result = u.simple().to_string();
1597         assert_eq!(result, expected);
1598     }
1599 
1600     #[test]
1601     #[cfg_attr(
1602         all(
1603             target_arch = "wasm32",
1604             target_vendor = "unknown",
1605             target_os = "unknown"
1606         ),
1607         wasm_bindgen_test
1608     )]
test_from_u64_pair()1609     fn test_from_u64_pair() {
1610         let high_in: u64 = 0xa1a2a3a4b1b2c1c2;
1611         let low_in: u64 = 0xd1d2d3d4d5d6d7d8;
1612 
1613         let u = Uuid::from_u64_pair(high_in, low_in);
1614 
1615         let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1616         let result = u.simple().to_string();
1617         assert_eq!(result, expected);
1618     }
1619 
1620     #[test]
1621     #[cfg_attr(
1622         all(
1623             target_arch = "wasm32",
1624             target_vendor = "unknown",
1625             target_os = "unknown"
1626         ),
1627         wasm_bindgen_test
1628     )]
test_u128_roundtrip()1629     fn test_u128_roundtrip() {
1630         let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
1631 
1632         let u = Uuid::from_u128(v_in);
1633         let v_out = u.as_u128();
1634 
1635         assert_eq!(v_in, v_out);
1636     }
1637 
1638     #[test]
1639     #[cfg_attr(
1640         all(
1641             target_arch = "wasm32",
1642             target_vendor = "unknown",
1643             target_os = "unknown"
1644         ),
1645         wasm_bindgen_test
1646     )]
test_u128_le_roundtrip()1647     fn test_u128_le_roundtrip() {
1648         let v_in: u128 = 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1;
1649 
1650         let u = Uuid::from_u128_le(v_in);
1651         let v_out = u.to_u128_le();
1652 
1653         assert_eq!(v_in, v_out);
1654     }
1655 
1656     #[test]
1657     #[cfg_attr(
1658         all(
1659             target_arch = "wasm32",
1660             target_vendor = "unknown",
1661             target_os = "unknown"
1662         ),
1663         wasm_bindgen_test
1664     )]
test_u64_pair_roundtrip()1665     fn test_u64_pair_roundtrip() {
1666         let high_in: u64 = 0xa1a2a3a4b1b2c1c2;
1667         let low_in: u64 = 0xd1d2d3d4d5d6d7d8;
1668 
1669         let u = Uuid::from_u64_pair(high_in, low_in);
1670         let (high_out, low_out) = u.as_u64_pair();
1671 
1672         assert_eq!(high_in, high_out);
1673         assert_eq!(low_in, low_out);
1674     }
1675 
1676     #[test]
1677     #[cfg_attr(
1678         all(
1679             target_arch = "wasm32",
1680             target_vendor = "unknown",
1681             target_os = "unknown"
1682         ),
1683         wasm_bindgen_test
1684     )]
test_u128_le_is_actually_le()1685     fn test_u128_le_is_actually_le() {
1686         let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
1687 
1688         let u = Uuid::from_u128(v_in);
1689         let v_out = u.to_u128_le();
1690 
1691         assert_eq!(v_in, v_out.swap_bytes());
1692     }
1693 
1694     #[test]
1695     #[cfg_attr(
1696         all(
1697             target_arch = "wasm32",
1698             target_vendor = "unknown",
1699             target_os = "unknown"
1700         ),
1701         wasm_bindgen_test
1702     )]
test_from_slice()1703     fn test_from_slice() {
1704         let b = [
1705             0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
1706             0xd7, 0xd8,
1707         ];
1708 
1709         let u = Uuid::from_slice(&b).unwrap();
1710         let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1711 
1712         assert_eq!(u.simple().to_string(), expected);
1713     }
1714 
1715     #[test]
1716     #[cfg_attr(
1717         all(
1718             target_arch = "wasm32",
1719             target_vendor = "unknown",
1720             target_os = "unknown"
1721         ),
1722         wasm_bindgen_test
1723     )]
test_from_bytes()1724     fn test_from_bytes() {
1725         let b = [
1726             0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
1727             0xd7, 0xd8,
1728         ];
1729 
1730         let u = Uuid::from_bytes(b);
1731         let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1732 
1733         assert_eq!(u.simple().to_string(), expected);
1734     }
1735 
1736     #[test]
1737     #[cfg_attr(
1738         all(
1739             target_arch = "wasm32",
1740             target_vendor = "unknown",
1741             target_os = "unknown"
1742         ),
1743         wasm_bindgen_test
1744     )]
test_as_bytes()1745     fn test_as_bytes() {
1746         let u = new();
1747         let ub = u.as_bytes();
1748         let ur = u.as_ref();
1749 
1750         assert_eq!(ub.len(), 16);
1751         assert_eq!(ur.len(), 16);
1752         assert!(!ub.iter().all(|&b| b == 0));
1753         assert!(!ur.iter().all(|&b| b == 0));
1754     }
1755 
1756     #[test]
1757     #[cfg(feature = "std")]
1758     #[cfg_attr(
1759         all(
1760             target_arch = "wasm32",
1761             target_vendor = "unknown",
1762             target_os = "unknown"
1763         ),
1764         wasm_bindgen_test
1765     )]
test_convert_vec()1766     fn test_convert_vec() {
1767         use crate::std::{convert::TryInto, vec::Vec};
1768 
1769         let u = new();
1770         let ub = u.as_ref();
1771 
1772         let v: Vec<u8> = u.into();
1773 
1774         assert_eq!(&v, ub);
1775 
1776         let uv: Uuid = v.try_into().unwrap();
1777 
1778         assert_eq!(uv, u);
1779     }
1780 
1781     #[test]
1782     #[cfg_attr(
1783         all(
1784             target_arch = "wasm32",
1785             target_vendor = "unknown",
1786             target_os = "unknown"
1787         ),
1788         wasm_bindgen_test
1789     )]
test_bytes_roundtrip()1790     fn test_bytes_roundtrip() {
1791         let b_in: crate::Bytes = [
1792             0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
1793             0xd7, 0xd8,
1794         ];
1795 
1796         let u = Uuid::from_slice(&b_in).unwrap();
1797 
1798         let b_out = u.as_bytes();
1799 
1800         assert_eq!(&b_in, b_out);
1801     }
1802 
1803     #[test]
1804     #[cfg_attr(
1805         all(
1806             target_arch = "wasm32",
1807             target_vendor = "unknown",
1808             target_os = "unknown"
1809         ),
1810         wasm_bindgen_test
1811     )]
test_bytes_le_roundtrip()1812     fn test_bytes_le_roundtrip() {
1813         let b = [
1814             0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
1815             0xd7, 0xd8,
1816         ];
1817 
1818         let u1 = Uuid::from_bytes(b);
1819 
1820         let b_le = u1.to_bytes_le();
1821 
1822         let u2 = Uuid::from_bytes_le(b_le);
1823 
1824         assert_eq!(u1, u2);
1825     }
1826 
1827     #[test]
1828     #[cfg_attr(
1829         all(
1830             target_arch = "wasm32",
1831             target_vendor = "unknown",
1832             target_os = "unknown"
1833         ),
1834         wasm_bindgen_test
1835     )]
test_iterbytes_impl_for_uuid()1836     fn test_iterbytes_impl_for_uuid() {
1837         let mut set = std::collections::HashSet::new();
1838         let id1 = new();
1839         let id2 = new2();
1840         set.insert(id1.clone());
1841 
1842         assert!(set.contains(&id1));
1843         assert!(!set.contains(&id2));
1844     }
1845 }
1846