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