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