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 UUIDs.
13 //!
14 //! Provides support for Universally Unique Identifiers (UUIDs). A UUID is a
15 //! unique 128-bit number, stored as 16 octets. UUIDs are used to  assign
16 //! unique identifiers to entities without requiring a central allocating
17 //! authority.
18 //!
19 //! They are particularly useful in distributed systems, though can be used in
20 //! disparate areas, such as databases and network protocols.  Typically a UUID
21 //! is displayed in a readable string form as a sequence of hexadecimal digits,
22 //! separated into groups by hyphens.
23 //!
24 //! The uniqueness property is not strictly guaranteed, however for all
25 //! practical purposes, it can be assumed that an unintentional collision would
26 //! be extremely unlikely.
27 //!
28 //! # Dependencies
29 //!
30 //! By default, this crate depends on nothing but `std` and cannot generate
31 //! UUIDs. You need to enable the following Cargo features to enable
32 //! various pieces of functionality:
33 //!
34 //! * `v1` - adds the [`Uuid::new_v1`] function and the ability to create a V1
35 //!   using an implementation of [`v1::ClockSequence`] (usually
36 //! [`v1::Context`]) and a timestamp from `time::timespec`.
37 //! * `v3` - adds the [`Uuid::new_v3`] function and the ability to create a V3
38 //!   UUID based on the MD5 hash of some data.
39 //! * `v4` - adds the [`Uuid::new_v4`] function and the ability to randomly
40 //!   generate a UUID.
41 //! * `v5` - adds the [`Uuid::new_v5`] function and the ability to create a V5
42 //!   UUID based on the SHA1 hash of some data.
43 //! * `serde` - adds the ability to serialize and deserialize a UUID using the
44 //!   `serde` crate.
45 //!
46 //! You need to enable one of the following Cargo features together with
47 //! `v3`, `v4` or `v5` feature if you're targeting `wasm32` architecture:
48 //!
49 //! * `stdweb` - enables support for `OsRng` on `wasm32-unknown-unknown` via
50 //!   [`stdweb`] combined with [`cargo-web`]
51 //! * `wasm-bindgen` - enables support for `OsRng` on `wasm32-unknown-unknown`
52 //!   via [`wasm-bindgen`]
53 //!
54 //! By default, `uuid` can be depended on with:
55 //!
56 //! ```toml
57 //! [dependencies]
58 //! uuid = "0.8"
59 //! ```
60 //!
61 //! To activate various features, use syntax like:
62 //!
63 //! ```toml
64 //! [dependencies]
65 //! uuid = { version = "0.8", features = ["serde", "v4"] }
66 //! ```
67 //!
68 //! You can disable default features with:
69 //!
70 //! ```toml
71 //! [dependencies]
72 //! uuid = { version = "0.8", default-features = false }
73 //! ```
74 //!
75 //! # Examples
76 //!
77 //! To parse a UUID given in the simple format and print it as a urn:
78 //!
79 //! ```rust
80 //! use uuid::Uuid;
81 //!
82 //! fn main() {
83 //!     let my_uuid =
84 //!         Uuid::parse_str("936DA01F9ABD4d9d80C702AF85C822A8").unwrap();
85 //!     println!("{}", my_uuid.to_urn());
86 //! }
87 //! ```
88 //!
89 //! To create a new random (V4) UUID and print it out in hexadecimal form:
90 //!
91 //! ```ignore,rust
92 //! // Note that this requires the `v4` feature enabled in the uuid crate.
93 //!
94 //! use uuid::Uuid;
95 //!
96 //! fn main() {
97 //!     let my_uuid = Uuid::new_v4();
98 //!     println!("{}", my_uuid);
99 //! }
100 //! ```
101 //!
102 //! # Strings
103 //!
104 //! Examples of string representations:
105 //!
106 //! * simple: `936DA01F9ABD4d9d80C702AF85C822A8`
107 //! * hyphenated: `550e8400-e29b-41d4-a716-446655440000`
108 //! * urn: `urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4`
109 //!
110 //! # References
111 //!
112 //! * [Wikipedia: Universally Unique
113 //!   Identifier](http://en.wikipedia.org/wiki/Universally_unique_identifier)
114 //! * [RFC4122: A Universally Unique IDentifier (UUID) URN
115 //!   Namespace](http://tools.ietf.org/html/rfc4122)
116 //!
117 //! [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
118 //! [`cargo-web`]: https://crates.io/crates/cargo-web
119 //! [`stdweb`]: https://crates.io/crates/stdweb
120 //! [`Uuid`]: struct.Uuid.html
121 //! [`Uuid::new_v1`]: struct.Uuid.html#method.new_v1
122 //! [`Uuid::new_v3`]: struct.Uuid.html#method.new_v3
123 //! [`Uuid::new_v4`]: struct.Uuid.html#method.new_v4
124 //! [`Uuid::new_v5`]: struct.Uuid.html#method.new_v5
125 //! [`v1::ClockSequence`]: v1/trait.ClockSequence.html
126 //! [`v1::Context`]: v1/struct.Context.html
127 
128 #![no_std]
129 #![deny(missing_debug_implementations, missing_docs)]
130 #![doc(
131     html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
132     html_favicon_url = "https://www.rust-lang.org/favicon.ico",
133     html_root_url = "https://docs.rs/uuid/0.8.1"
134 )]
135 
136 #[cfg(any(feature = "std", test))]
137 #[macro_use]
138 extern crate std;
139 
140 #[cfg(all(not(feature = "std"), not(test)))]
141 #[macro_use]
142 extern crate core as std;
143 
144 mod builder;
145 mod error;
146 mod parser;
147 mod prelude;
148 
149 pub mod adapter;
150 #[cfg(feature = "v1")]
151 pub mod v1;
152 
153 #[cfg(feature = "serde")]
154 mod serde_support;
155 #[cfg(feature = "slog")]
156 mod slog_support;
157 #[cfg(test)]
158 mod test_util;
159 #[cfg(all(
160     feature = "v3",
161     any(
162         not(target_arch = "wasm32"),
163         all(
164             target_arch = "wasm32",
165             any(feature = "stdweb", feature = "wasm-bindgen")
166         )
167     )
168 ))]
169 mod v3;
170 #[cfg(all(
171     feature = "v4",
172     any(
173         not(target_arch = "wasm32"),
174         all(
175             target_arch = "wasm32",
176             any(feature = "stdweb", feature = "wasm-bindgen")
177         )
178     )
179 ))]
180 mod v4;
181 #[cfg(all(
182     feature = "v5",
183     any(
184         not(target_arch = "wasm32"),
185         all(
186             target_arch = "wasm32",
187             any(feature = "stdweb", feature = "wasm-bindgen")
188         )
189     )
190 ))]
191 mod v5;
192 #[cfg(all(windows, feature = "winapi"))]
193 mod winapi_support;
194 
195 use crate::std::{fmt, str};
196 
197 pub use crate::{builder::Builder, error::Error};
198 
199 /// A 128-bit (16 byte) buffer containing the ID.
200 pub type Bytes = [u8; 16];
201 
202 /// The version of the UUID, denoting the generating algorithm.
203 #[derive(Clone, Copy, Debug, PartialEq)]
204 pub enum Version {
205     /// Special case for `nil` UUID.
206     Nil = 0,
207     /// Version 1: MAC address.
208     Mac,
209     /// Version 2: DCE Security.
210     Dce,
211     /// Version 3: MD5 hash.
212     Md5,
213     /// Version 4: Random.
214     Random,
215     /// Version 5: SHA-1 hash.
216     Sha1,
217 }
218 
219 /// The reserved variants of UUIDs.
220 #[derive(Clone, Copy, Debug, PartialEq)]
221 pub enum Variant {
222     /// Reserved by the NCS for backward compatibility.
223     NCS = 0,
224     /// As described in the RFC4122 Specification (default).
225     RFC4122,
226     /// Reserved by Microsoft for backward compatibility.
227     Microsoft,
228     /// Reserved for future expansion.
229     Future,
230 }
231 
232 /// A Universally Unique Identifier (UUID).
233 #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
234 pub struct Uuid(Bytes);
235 
236 impl Uuid {
237     /// UUID namespace for Domain Name System (DNS).
238     pub const NAMESPACE_DNS: Self = Uuid([
239         0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0,
240         0x4f, 0xd4, 0x30, 0xc8,
241     ]);
242 
243     /// UUID namespace for ISO Object Identifiers (OIDs).
244     pub const NAMESPACE_OID: Self = Uuid([
245         0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0,
246         0x4f, 0xd4, 0x30, 0xc8,
247     ]);
248 
249     /// UUID namespace for Uniform Resource Locators (URLs).
250     pub const NAMESPACE_URL: Self = Uuid([
251         0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0,
252         0x4f, 0xd4, 0x30, 0xc8,
253     ]);
254 
255     /// UUID namespace for X.500 Distinguished Names (DNs).
256     pub const NAMESPACE_X500: Self = Uuid([
257         0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0,
258         0x4f, 0xd4, 0x30, 0xc8,
259     ]);
260 
261     /// Returns the variant of the UUID structure.
262     ///
263     /// This determines the interpretation of the structure of the UUID.
264     /// Currently only the RFC4122 variant is generated by this module.
265     ///
266     /// * [Variant Reference](http://tools.ietf.org/html/rfc4122#section-4.1.1)
get_variant(&self) -> Option<Variant>267     pub fn get_variant(&self) -> Option<Variant> {
268         match self.as_bytes()[8] {
269             x if x & 0x80 == 0x00 => Some(Variant::NCS),
270             x if x & 0xc0 == 0x80 => Some(Variant::RFC4122),
271             x if x & 0xe0 == 0xc0 => Some(Variant::Microsoft),
272             x if x & 0xe0 == 0xe0 => Some(Variant::Future),
273             _ => None,
274         }
275     }
276 
277     /// Returns the version number of the UUID.
278     ///
279     /// This represents the algorithm used to generate the contents.
280     ///
281     /// Currently only the Random (V4) algorithm is supported by this
282     /// module.  There are security and privacy implications for using
283     /// older versions - see [Wikipedia: Universally Unique Identifier](
284     /// http://en.wikipedia.org/wiki/Universally_unique_identifier) for
285     /// details.
286     ///
287     /// * [Version Reference](http://tools.ietf.org/html/rfc4122#section-4.1.3)
get_version_num(&self) -> usize288     pub const fn get_version_num(&self) -> usize {
289         (self.as_bytes()[6] >> 4) as usize
290     }
291 
292     /// Returns the version of the UUID.
293     ///
294     /// This represents the algorithm used to generate the contents
get_version(&self) -> Option<Version>295     pub fn get_version(&self) -> Option<Version> {
296         let v = self.as_bytes()[6] >> 4;
297         match v {
298             0 if self.is_nil() => Some(Version::Nil),
299             1 => Some(Version::Mac),
300             2 => Some(Version::Dce),
301             3 => Some(Version::Md5),
302             4 => Some(Version::Random),
303             5 => Some(Version::Sha1),
304             _ => None,
305         }
306     }
307 
308     /// Returns the four field values of the UUID in big-endian order.
309     ///
310     /// These values can be passed to the `from_fields()` method to get the
311     /// original `Uuid` back.
312     ///
313     /// * The first field value represents the first group of (eight) hex
314     ///   digits, taken as a big-endian `u32` value.  For V1 UUIDs, this field
315     ///   represents the low 32 bits of the timestamp.
316     /// * The second field value represents the second group of (four) hex
317     ///   digits, taken as a big-endian `u16` value.  For V1 UUIDs, this field
318     ///   represents the middle 16 bits of the timestamp.
319     /// * The third field value represents the third group of (four) hex digits,
320     ///   taken as a big-endian `u16` value.  The 4 most significant bits give
321     ///   the UUID version, and for V1 UUIDs, the last 12 bits represent the
322     ///   high 12 bits of the timestamp.
323     /// * The last field value represents the last two groups of four and twelve
324     ///   hex digits, taken in order.  The first 1-3 bits of this indicate the
325     ///   UUID variant, and for V1 UUIDs, the next 13-15 bits indicate the clock
326     ///   sequence and the last 48 bits indicate the node ID.
327     ///
328     /// # Examples
329     ///
330     /// ```
331     /// use uuid::Uuid;
332     ///
333     /// let uuid = Uuid::nil();
334     /// assert_eq!(uuid.as_fields(), (0, 0, 0, &[0u8; 8]));
335     ///
336     /// let uuid = Uuid::parse_str("936DA01F-9ABD-4D9D-80C7-02AF85C822A8").unwrap();
337     /// assert_eq!(
338     ///     uuid.as_fields(),
339     ///     (
340     ///         0x936DA01F,
341     ///         0x9ABD,
342     ///         0x4D9D,
343     ///         b"\x80\xC7\x02\xAF\x85\xC8\x22\xA8"
344     ///     )
345     /// );
346     /// ```
as_fields(&self) -> (u32, u16, u16, &[u8; 8])347     pub fn as_fields(&self) -> (u32, u16, u16, &[u8; 8]) {
348         let d1 = u32::from(self.as_bytes()[0]) << 24
349             | u32::from(self.as_bytes()[1]) << 16
350             | u32::from(self.as_bytes()[2]) << 8
351             | u32::from(self.as_bytes()[3]);
352 
353         let d2 =
354             u16::from(self.as_bytes()[4]) << 8 | u16::from(self.as_bytes()[5]);
355 
356         let d3 =
357             u16::from(self.as_bytes()[6]) << 8 | u16::from(self.as_bytes()[7]);
358 
359         let d4: &[u8; 8] =
360             unsafe { &*(self.as_bytes()[8..16].as_ptr() as *const [u8; 8]) };
361         (d1, d2, d3, d4)
362     }
363 
364     /// Returns the four field values of the UUID in little-endian order.
365     ///
366     /// The bytes in the returned integer fields will
367     /// be converted from big-endian order.
368     ///
369     /// # Examples
370     ///
371     /// ```
372     /// use uuid::Uuid;
373     ///
374     /// let uuid = Uuid::parse_str("936DA01F-9ABD-4D9D-80C7-02AF85C822A8").unwrap();
375     /// assert_eq!(
376     ///     uuid.to_fields_le(),
377     ///     (
378     ///         0x1FA06D93,
379     ///         0xBD9A,
380     ///         0x9D4D,
381     ///         b"\x80\xC7\x02\xAF\x85\xC8\x22\xA8"
382     ///     )
383     /// );
384     /// ```
to_fields_le(&self) -> (u32, u16, u16, &[u8; 8])385     pub fn to_fields_le(&self) -> (u32, u16, u16, &[u8; 8]) {
386         let d1 = u32::from(self.as_bytes()[0])
387             | u32::from(self.as_bytes()[1]) << 8
388             | u32::from(self.as_bytes()[2]) << 16
389             | u32::from(self.as_bytes()[3]) << 24;
390 
391         let d2 =
392             u16::from(self.as_bytes()[4]) | u16::from(self.as_bytes()[5]) << 8;
393 
394         let d3 =
395             u16::from(self.as_bytes()[6]) | u16::from(self.as_bytes()[7]) << 8;
396 
397         let d4: &[u8; 8] =
398             unsafe { &*(self.as_bytes()[8..16].as_ptr() as *const [u8; 8]) };
399         (d1, d2, d3, d4)
400     }
401 
402     /// Returns a 128bit value containing the UUID data.
403     ///
404     /// The bytes in the UUID will be packed into a `u128`, like the
405     /// [`Uuid::as_bytes`] method.
406     ///
407     /// # Examples
408     ///
409     /// ```
410     /// use uuid::Uuid;
411     ///
412     /// let uuid = Uuid::parse_str("936DA01F-9ABD-4D9D-80C7-02AF85C822A8").unwrap();
413     /// assert_eq!(
414     ///     uuid.as_u128(),
415     ///     0x936DA01F9ABD4D9D80C702AF85C822A8,
416     /// )
417     /// ```
as_u128(&self) -> u128418     pub fn as_u128(&self) -> u128 {
419         u128::from(self.as_bytes()[0]) << 120
420             | u128::from(self.as_bytes()[1]) << 112
421             | u128::from(self.as_bytes()[2]) << 104
422             | u128::from(self.as_bytes()[3]) << 96
423             | u128::from(self.as_bytes()[4]) << 88
424             | u128::from(self.as_bytes()[5]) << 80
425             | u128::from(self.as_bytes()[6]) << 72
426             | u128::from(self.as_bytes()[7]) << 64
427             | u128::from(self.as_bytes()[8]) << 56
428             | u128::from(self.as_bytes()[9]) << 48
429             | u128::from(self.as_bytes()[10]) << 40
430             | u128::from(self.as_bytes()[11]) << 32
431             | u128::from(self.as_bytes()[12]) << 24
432             | u128::from(self.as_bytes()[13]) << 16
433             | u128::from(self.as_bytes()[14]) << 8
434             | u128::from(self.as_bytes()[15])
435     }
436 
437     /// Returns a 128bit little-endian value containing the UUID data.
438     ///
439     /// The bytes in the UUID will be reversed and packed into a `u128`.
440     /// Note that this will produce a different result than
441     /// [`Uuid::to_fields_le`], because the entire UUID is reversed, rather
442     /// than reversing the individual fields in-place.
443     ///
444     /// # Examples
445     ///
446     /// ```
447     /// use uuid::Uuid;
448     ///
449     /// let uuid = Uuid::parse_str("936DA01F-9ABD-4D9D-80C7-02AF85C822A8").unwrap();
450     ///
451     /// assert_eq!(
452     ///     uuid.to_u128_le(),
453     ///     0xA822C885AF02C7809D4DBD9A1FA06D93,
454     /// )
455     /// ```
to_u128_le(&self) -> u128456     pub fn to_u128_le(&self) -> u128 {
457         u128::from(self.as_bytes()[0])
458             | u128::from(self.as_bytes()[1]) << 8
459             | u128::from(self.as_bytes()[2]) << 16
460             | u128::from(self.as_bytes()[3]) << 24
461             | u128::from(self.as_bytes()[4]) << 32
462             | u128::from(self.as_bytes()[5]) << 40
463             | u128::from(self.as_bytes()[6]) << 48
464             | u128::from(self.as_bytes()[7]) << 56
465             | u128::from(self.as_bytes()[8]) << 64
466             | u128::from(self.as_bytes()[9]) << 72
467             | u128::from(self.as_bytes()[10]) << 80
468             | u128::from(self.as_bytes()[11]) << 88
469             | u128::from(self.as_bytes()[12]) << 96
470             | u128::from(self.as_bytes()[13]) << 104
471             | u128::from(self.as_bytes()[14]) << 112
472             | u128::from(self.as_bytes()[15]) << 120
473     }
474 
475     /// Returns an array of 16 octets containing the UUID data.
as_bytes(&self) -> &Bytes476     pub const fn as_bytes(&self) -> &Bytes {
477         &self.0
478     }
479 
480     /// Tests if the UUID is nil.
is_nil(&self) -> bool481     pub fn is_nil(&self) -> bool {
482         self.as_bytes().iter().all(|&b| b == 0)
483     }
484 
485     /// A buffer that can be used for `encode_...` calls, that is
486     /// guaranteed to be long enough for any of the adapters.
487     ///
488     /// # Examples
489     ///
490     /// ```rust
491     /// use uuid::Uuid;
492     ///
493     /// let uuid = Uuid::nil();
494     ///
495     /// assert_eq!(
496     ///     uuid.to_simple().encode_lower(&mut Uuid::encode_buffer()),
497     ///     "00000000000000000000000000000000"
498     /// );
499     ///
500     /// assert_eq!(
501     ///     uuid.to_hyphenated()
502     ///         .encode_lower(&mut Uuid::encode_buffer()),
503     ///     "00000000-0000-0000-0000-000000000000"
504     /// );
505     ///
506     /// assert_eq!(
507     ///     uuid.to_urn().encode_lower(&mut Uuid::encode_buffer()),
508     ///     "urn:uuid:00000000-0000-0000-0000-000000000000"
509     /// );
510     /// ```
encode_buffer() -> [u8; adapter::Urn::LENGTH]511     pub const fn encode_buffer() -> [u8; adapter::Urn::LENGTH] {
512         [0; adapter::Urn::LENGTH]
513     }
514 }
515 
516 impl fmt::Debug for Uuid {
517     #[inline]
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result518     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
519         fmt::LowerHex::fmt(self, f)
520     }
521 }
522 
523 impl fmt::Display for Uuid {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result524     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
525         fmt::LowerHex::fmt(self, f)
526     }
527 }
528 
529 impl fmt::Display for Variant {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result530     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
531         match *self {
532             Variant::NCS => write!(f, "NCS"),
533             Variant::RFC4122 => write!(f, "RFC4122"),
534             Variant::Microsoft => write!(f, "Microsoft"),
535             Variant::Future => write!(f, "Future"),
536         }
537     }
538 }
539 
540 impl fmt::LowerHex for Uuid {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result541     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
542         fmt::LowerHex::fmt(&self.to_hyphenated_ref(), f)
543     }
544 }
545 
546 impl fmt::UpperHex for Uuid {
547     #[inline]
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result548     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
549         fmt::UpperHex::fmt(&self.to_hyphenated_ref(), f)
550     }
551 }
552 
553 impl str::FromStr for Uuid {
554     type Err = Error;
555 
from_str(uuid_str: &str) -> Result<Self, Self::Err>556     fn from_str(uuid_str: &str) -> Result<Self, Self::Err> {
557         Uuid::parse_str(uuid_str)
558     }
559 }
560 
561 impl Default for Uuid {
562     #[inline]
default() -> Self563     fn default() -> Self {
564         Uuid::nil()
565     }
566 }
567 
568 #[cfg(test)]
569 mod tests {
570     use crate::{
571         prelude::*,
572         std::string::{String, ToString},
573         test_util,
574     };
575 
576     macro_rules! check {
577         ($buf:ident, $format:expr, $target:expr, $len:expr, $cond:expr) => {
578             $buf.clear();
579             write!($buf, $format, $target).unwrap();
580             assert!($buf.len() == $len);
581             assert!($buf.chars().all($cond), "{}", $buf);
582         };
583     }
584 
585     #[test]
test_uuid_compare()586     fn test_uuid_compare() {
587         let uuid1 = test_util::new();
588         let uuid2 = test_util::new2();
589 
590         assert_eq!(uuid1, uuid1);
591         assert_eq!(uuid2, uuid2);
592 
593         assert_ne!(uuid1, uuid2);
594         assert_ne!(uuid2, uuid1);
595     }
596 
597     #[test]
test_uuid_default()598     fn test_uuid_default() {
599         let default_uuid = Uuid::default();
600         let nil_uuid = Uuid::nil();
601 
602         assert_eq!(default_uuid, nil_uuid);
603     }
604 
605     #[test]
test_uuid_display()606     fn test_uuid_display() {
607         use super::fmt::Write;
608 
609         let uuid = test_util::new();
610         let s = uuid.to_string();
611         let mut buffer = String::new();
612 
613         assert_eq!(s, uuid.to_hyphenated().to_string());
614 
615         check!(buffer, "{}", uuid, 36, |c| c.is_lowercase()
616             || c.is_digit(10)
617             || c == '-');
618     }
619 
620     #[test]
test_uuid_lowerhex()621     fn test_uuid_lowerhex() {
622         use super::fmt::Write;
623 
624         let mut buffer = String::new();
625         let uuid = test_util::new();
626 
627         check!(buffer, "{:x}", uuid, 36, |c| c.is_lowercase()
628             || c.is_digit(10)
629             || c == '-');
630     }
631 
632     // noinspection RsAssertEqual
633     #[test]
test_uuid_operator_eq()634     fn test_uuid_operator_eq() {
635         let uuid1 = test_util::new();
636         let uuid1_dup = uuid1.clone();
637         let uuid2 = test_util::new2();
638 
639         assert!(uuid1 == uuid1);
640         assert!(uuid1 == uuid1_dup);
641         assert!(uuid1_dup == uuid1);
642 
643         assert!(uuid1 != uuid2);
644         assert!(uuid2 != uuid1);
645         assert!(uuid1_dup != uuid2);
646         assert!(uuid2 != uuid1_dup);
647     }
648 
649     #[test]
test_uuid_to_string()650     fn test_uuid_to_string() {
651         use super::fmt::Write;
652 
653         let uuid = test_util::new();
654         let s = uuid.to_string();
655         let mut buffer = String::new();
656 
657         assert_eq!(s.len(), 36);
658 
659         check!(buffer, "{}", s, 36, |c| c.is_lowercase()
660             || c.is_digit(10)
661             || c == '-');
662     }
663 
664     #[test]
test_uuid_upperhex()665     fn test_uuid_upperhex() {
666         use super::fmt::Write;
667 
668         let mut buffer = String::new();
669         let uuid = test_util::new();
670 
671         check!(buffer, "{:X}", uuid, 36, |c| c.is_uppercase()
672             || c.is_digit(10)
673             || c == '-');
674     }
675 
676     #[test]
test_nil()677     fn test_nil() {
678         let nil = Uuid::nil();
679         let not_nil = test_util::new();
680         let from_bytes = Uuid::from_bytes([
681             4, 54, 67, 12, 43, 2, 2, 76, 32, 50, 87, 5, 1, 33, 43, 87,
682         ]);
683 
684         assert_eq!(from_bytes.get_version(), None);
685 
686         assert!(nil.is_nil());
687         assert!(!not_nil.is_nil());
688 
689         assert_eq!(nil.get_version(), Some(Version::Nil));
690         assert_eq!(not_nil.get_version(), Some(Version::Random))
691     }
692 
693     #[test]
test_predefined_namespaces()694     fn test_predefined_namespaces() {
695         assert_eq!(
696             Uuid::NAMESPACE_DNS.to_hyphenated().to_string(),
697             "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
698         );
699         assert_eq!(
700             Uuid::NAMESPACE_URL.to_hyphenated().to_string(),
701             "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
702         );
703         assert_eq!(
704             Uuid::NAMESPACE_OID.to_hyphenated().to_string(),
705             "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
706         );
707         assert_eq!(
708             Uuid::NAMESPACE_X500.to_hyphenated().to_string(),
709             "6ba7b814-9dad-11d1-80b4-00c04fd430c8"
710         );
711     }
712 
713     #[cfg(feature = "v3")]
714     #[test]
test_get_version_v3()715     fn test_get_version_v3() {
716         let uuid =
717             Uuid::new_v3(&Uuid::NAMESPACE_DNS, "rust-lang.org".as_bytes());
718 
719         assert_eq!(uuid.get_version().unwrap(), Version::Md5);
720         assert_eq!(uuid.get_version_num(), 3);
721     }
722 
723     #[test]
test_get_variant()724     fn test_get_variant() {
725         let uuid1 = test_util::new();
726         let uuid2 =
727             Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
728         let uuid3 =
729             Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8").unwrap();
730         let uuid4 =
731             Uuid::parse_str("936DA01F9ABD4d9dC0C702AF85C822A8").unwrap();
732         let uuid5 =
733             Uuid::parse_str("F9168C5E-CEB2-4faa-D6BF-329BF39FA1E4").unwrap();
734         let uuid6 =
735             Uuid::parse_str("f81d4fae-7dec-11d0-7765-00a0c91e6bf6").unwrap();
736 
737         assert_eq!(uuid1.get_variant().unwrap(), Variant::RFC4122);
738         assert_eq!(uuid2.get_variant().unwrap(), Variant::RFC4122);
739         assert_eq!(uuid3.get_variant().unwrap(), Variant::RFC4122);
740         assert_eq!(uuid4.get_variant().unwrap(), Variant::Microsoft);
741         assert_eq!(uuid5.get_variant().unwrap(), Variant::Microsoft);
742         assert_eq!(uuid6.get_variant().unwrap(), Variant::NCS);
743     }
744 
745     #[test]
test_to_simple_string()746     fn test_to_simple_string() {
747         let uuid1 = test_util::new();
748         let s = uuid1.to_simple().to_string();
749 
750         assert_eq!(s.len(), 32);
751         assert!(s.chars().all(|c| c.is_digit(16)));
752     }
753 
754     #[test]
test_to_hyphenated_string()755     fn test_to_hyphenated_string() {
756         let uuid1 = test_util::new();
757         let s = uuid1.to_hyphenated().to_string();
758 
759         assert!(s.len() == 36);
760         assert!(s.chars().all(|c| c.is_digit(16) || c == '-'));
761     }
762 
763     #[test]
test_upper_lower_hex()764     fn test_upper_lower_hex() {
765         use std::fmt::Write;
766 
767         let mut buf = String::new();
768         let u = test_util::new();
769 
770         macro_rules! check {
771             ($buf:ident, $format:expr, $target:expr, $len:expr, $cond:expr) => {
772                 $buf.clear();
773                 write!($buf, $format, $target).unwrap();
774                 assert!(buf.len() == $len);
775                 assert!($buf.chars().all($cond), "{}", $buf);
776             };
777         }
778 
779         check!(buf, "{:X}", u, 36, |c| c.is_uppercase()
780             || c.is_digit(10)
781             || c == '-');
782         check!(buf, "{:X}", u.to_hyphenated(), 36, |c| c.is_uppercase()
783             || c.is_digit(10)
784             || c == '-');
785         check!(buf, "{:X}", u.to_simple(), 32, |c| c.is_uppercase()
786             || c.is_digit(10));
787 
788         check!(buf, "{:x}", u.to_hyphenated(), 36, |c| c.is_lowercase()
789             || c.is_digit(10)
790             || c == '-');
791         check!(buf, "{:x}", u.to_simple(), 32, |c| c.is_lowercase()
792             || c.is_digit(10));
793     }
794 
795     #[test]
test_to_urn_string()796     fn test_to_urn_string() {
797         let uuid1 = test_util::new();
798         let ss = uuid1.to_urn().to_string();
799         let s = &ss[9..];
800 
801         assert!(ss.starts_with("urn:uuid:"));
802         assert_eq!(s.len(), 36);
803         assert!(s.chars().all(|c| c.is_digit(16) || c == '-'));
804     }
805 
806     #[test]
test_to_simple_string_matching()807     fn test_to_simple_string_matching() {
808         let uuid1 = test_util::new();
809 
810         let hs = uuid1.to_hyphenated().to_string();
811         let ss = uuid1.to_simple().to_string();
812 
813         let hsn = hs.chars().filter(|&c| c != '-').collect::<String>();
814 
815         assert_eq!(hsn, ss);
816     }
817 
818     #[test]
test_string_roundtrip()819     fn test_string_roundtrip() {
820         let uuid = test_util::new();
821 
822         let hs = uuid.to_hyphenated().to_string();
823         let uuid_hs = Uuid::parse_str(&hs).unwrap();
824         assert_eq!(uuid_hs, uuid);
825 
826         let ss = uuid.to_string();
827         let uuid_ss = Uuid::parse_str(&ss).unwrap();
828         assert_eq!(uuid_ss, uuid);
829     }
830 
831     #[test]
test_from_fields()832     fn test_from_fields() {
833         let d1: u32 = 0xa1a2a3a4;
834         let d2: u16 = 0xb1b2;
835         let d3: u16 = 0xc1c2;
836         let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
837 
838         let u = Uuid::from_fields(d1, d2, d3, &d4).unwrap();
839 
840         let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
841         let result = u.to_simple().to_string();
842         assert_eq!(result, expected);
843     }
844 
845     #[test]
test_from_fields_le()846     fn test_from_fields_le() {
847         let d1: u32 = 0xa4a3a2a1;
848         let d2: u16 = 0xb2b1;
849         let d3: u16 = 0xc2c1;
850         let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
851 
852         let u = Uuid::from_fields_le(d1, d2, d3, &d4).unwrap();
853 
854         let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
855         let result = u.to_simple().to_string();
856         assert_eq!(result, expected);
857     }
858 
859     #[test]
test_as_fields()860     fn test_as_fields() {
861         let u = test_util::new();
862         let (d1, d2, d3, d4) = u.as_fields();
863 
864         assert_ne!(d1, 0);
865         assert_ne!(d2, 0);
866         assert_ne!(d3, 0);
867         assert_eq!(d4.len(), 8);
868         assert!(!d4.iter().all(|&b| b == 0));
869     }
870 
871     #[test]
test_fields_roundtrip()872     fn test_fields_roundtrip() {
873         let d1_in: u32 = 0xa1a2a3a4;
874         let d2_in: u16 = 0xb1b2;
875         let d3_in: u16 = 0xc1c2;
876         let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
877 
878         let u = Uuid::from_fields(d1_in, d2_in, d3_in, d4_in).unwrap();
879         let (d1_out, d2_out, d3_out, d4_out) = u.as_fields();
880 
881         assert_eq!(d1_in, d1_out);
882         assert_eq!(d2_in, d2_out);
883         assert_eq!(d3_in, d3_out);
884         assert_eq!(d4_in, d4_out);
885     }
886 
887     #[test]
test_fields_le_roundtrip()888     fn test_fields_le_roundtrip() {
889         let d1_in: u32 = 0xa4a3a2a1;
890         let d2_in: u16 = 0xb2b1;
891         let d3_in: u16 = 0xc2c1;
892         let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
893 
894         let u = Uuid::from_fields_le(d1_in, d2_in, d3_in, d4_in).unwrap();
895         let (d1_out, d2_out, d3_out, d4_out) = u.to_fields_le();
896 
897         assert_eq!(d1_in, d1_out);
898         assert_eq!(d2_in, d2_out);
899         assert_eq!(d3_in, d3_out);
900         assert_eq!(d4_in, d4_out);
901     }
902 
903     #[test]
test_fields_le_are_actually_le()904     fn test_fields_le_are_actually_le() {
905         let d1_in: u32 = 0xa1a2a3a4;
906         let d2_in: u16 = 0xb1b2;
907         let d3_in: u16 = 0xc1c2;
908         let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
909 
910         let u = Uuid::from_fields(d1_in, d2_in, d3_in, d4_in).unwrap();
911         let (d1_out, d2_out, d3_out, d4_out) = u.to_fields_le();
912 
913         assert_eq!(d1_in, d1_out.swap_bytes());
914         assert_eq!(d2_in, d2_out.swap_bytes());
915         assert_eq!(d3_in, d3_out.swap_bytes());
916         assert_eq!(d4_in, d4_out);
917     }
918 
919     #[test]
test_from_u128()920     fn test_from_u128() {
921         let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
922 
923         let u = Uuid::from_u128(v_in);
924 
925         let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
926         let result = u.to_simple().to_string();
927         assert_eq!(result, expected);
928     }
929 
930     #[test]
test_from_u128_le()931     fn test_from_u128_le() {
932         let v_in: u128 = 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1;
933 
934         let u = Uuid::from_u128_le(v_in);
935 
936         let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
937         let result = u.to_simple().to_string();
938         assert_eq!(result, expected);
939     }
940 
941     #[test]
test_u128_roundtrip()942     fn test_u128_roundtrip() {
943         let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
944 
945         let u = Uuid::from_u128(v_in);
946         let v_out = u.as_u128();
947 
948         assert_eq!(v_in, v_out);
949     }
950 
951     #[test]
test_u128_le_roundtrip()952     fn test_u128_le_roundtrip() {
953         let v_in: u128 = 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1;
954 
955         let u = Uuid::from_u128_le(v_in);
956         let v_out = u.to_u128_le();
957 
958         assert_eq!(v_in, v_out);
959     }
960 
961     #[test]
test_u128_le_is_actually_le()962     fn test_u128_le_is_actually_le() {
963         let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
964 
965         let u = Uuid::from_u128(v_in);
966         let v_out = u.to_u128_le();
967 
968         assert_eq!(v_in, v_out.swap_bytes());
969     }
970 
971     #[test]
test_from_slice()972     fn test_from_slice() {
973         let b = [
974             0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3,
975             0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
976         ];
977 
978         let u = Uuid::from_slice(&b).unwrap();
979         let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
980 
981         assert_eq!(u.to_simple().to_string(), expected);
982     }
983 
984     #[test]
test_from_bytes()985     fn test_from_bytes() {
986         let b = [
987             0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3,
988             0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
989         ];
990 
991         let u = Uuid::from_bytes(b);
992         let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
993 
994         assert_eq!(u.to_simple().to_string(), expected);
995     }
996 
997     #[test]
test_as_bytes()998     fn test_as_bytes() {
999         let u = test_util::new();
1000         let ub = u.as_bytes();
1001 
1002         assert_eq!(ub.len(), 16);
1003         assert!(!ub.iter().all(|&b| b == 0));
1004     }
1005 
1006     #[test]
test_bytes_roundtrip()1007     fn test_bytes_roundtrip() {
1008         let b_in: crate::Bytes = [
1009             0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3,
1010             0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
1011         ];
1012 
1013         let u = Uuid::from_slice(&b_in).unwrap();
1014 
1015         let b_out = u.as_bytes();
1016 
1017         assert_eq!(&b_in, b_out);
1018     }
1019 
1020     #[test]
test_iterbytes_impl_for_uuid()1021     fn test_iterbytes_impl_for_uuid() {
1022         let mut set = std::collections::HashSet::new();
1023         let id1 = test_util::new();
1024         let id2 = test_util::new2();
1025         set.insert(id1.clone());
1026 
1027         assert!(set.contains(&id1));
1028         assert!(!set.contains(&id2));
1029     }
1030 }
1031