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//! UUIDs have a number of standardized encodings that are specified in [RFC 9562](https://www.ietf.org/rfc/rfc9562.html).
34//!
35//! # Getting started
36//!
37//! Add the following to your `Cargo.toml`:
38//!
39//! ```toml
40//! [dependencies.uuid]
41//! version = "1.11.0"
42//! features = [
43//! "v4", # Lets you generate random UUIDs
44//! "fast-rng", # Use a faster (but still sufficiently random) RNG
45//! "macro-diagnostics", # Enable better diagnostics for compile-time UUIDs
46//! ]
47//! ```
48//!
49//! When you want a UUID, you can generate one:
50//!
51//! ```
52//! # fn main() {
53//! # #[cfg(feature = "v4")]
54//! # {
55//! use uuid::Uuid;
56//!
57//! let id = Uuid::new_v4();
58//! # }
59//! # }
60//! ```
61//!
62//! If you have a UUID value, you can use its string literal form inline:
63//!
64//! ```
65//! use uuid::{uuid, Uuid};
66//!
67//! const ID: Uuid = uuid!("67e55044-10b1-426f-9247-bb680e5fe0c8");
68//! ```
69//!
70//! # Working with different UUID versions
71//!
72//! This library supports all standardized methods for generating UUIDs through individual Cargo features.
73//!
74//! By default, this crate depends on nothing but the Rust standard library and can parse and format
75//! UUIDs, but cannot generate them. Depending on the kind of UUID you'd like to work with, there
76//! are Cargo features that enable generating them:
77//!
78//! * `v1` - Version 1 UUIDs using a timestamp and monotonic counter.
79//! * `v3` - Version 3 UUIDs based on the MD5 hash of some data.
80//! * `v4` - Version 4 UUIDs with random data.
81//! * `v5` - Version 5 UUIDs based on the SHA1 hash of some data.
82//! * `v6` - Version 6 UUIDs using a timestamp and monotonic counter.
83//! * `v7` - Version 7 UUIDs using a Unix timestamp.
84//! * `v8` - Version 8 UUIDs using user-defined data.
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//! * `borsh` - adds the ability to serialize and deserialize a UUID using
107//! `borsh`.
108//! * `arbitrary` - adds an `Arbitrary` trait implementation to `Uuid` for
109//! fuzzing.
110//! * `fast-rng` - uses a faster algorithm for generating random UUIDs.
111//! This feature requires more dependencies to compile, but is just as suitable for
112//! UUIDs as the default algorithm.
113//! * `bytemuck` - adds a `Pod` trait implementation to `Uuid` for byte manipulation
114//!
115//! # Unstable features
116//!
117//! Some features are unstable. They may be incomplete or depend on other
118//! unstable libraries. These include:
119//!
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.11.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.11.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` or `v7` features.
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//! * [RFC 9562: Universally Unique IDentifiers (UUID)](https://www.ietf.org/rfc/rfc9562.html).
203//!
204//! [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen
205//! [`cargo-web`]: https://crates.io/crates/cargo-web
206//! [`getrandom`'s docs]: https://docs.rs/getrandom
207
208#![no_std]
209#![deny(missing_debug_implementations, missing_docs)]
210#![allow(clippy::mixed_attributes_style)]
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.11.0"
215)]
216
217#[cfg(any(feature = "std", test))]
218#[macro_use]
219extern crate std;
220
221#[cfg(all(not(feature = "std"), not(test)))]
222#[macro_use]
223extern crate core as std;
224
225#[cfg(all(uuid_unstable, feature = "zerocopy"))]
226use zerocopy::{IntoBytes, FromBytes, Immutable, KnownLayout, Unaligned};
227
228mod builder;
229mod error;
230mod parser;
231
232pub mod fmt;
233pub mod timestamp;
234
235pub use timestamp::{context::NoContext, ClockSequence, Timestamp};
236
237#[cfg(any(feature = "v1", feature = "v6"))]
238pub use timestamp::context::Context;
239
240#[cfg(feature = "v7")]
241pub use timestamp::context::ContextV7;
242
243#[cfg(feature = "v1")]
244#[doc(hidden)]
245// Soft-deprecated (Rust doesn't support deprecating re-exports)
246// Use `Context` from the crate root instead
247pub mod v1;
248#[cfg(feature = "v3")]
249mod v3;
250#[cfg(feature = "v4")]
251mod v4;
252#[cfg(feature = "v5")]
253mod v5;
254#[cfg(feature = "v6")]
255mod v6;
256#[cfg(feature = "v7")]
257mod v7;
258#[cfg(feature = "v8")]
259mod v8;
260
261#[cfg(feature = "md5")]
262mod md5;
263#[cfg(feature = "rng")]
264mod rng;
265#[cfg(feature = "sha1")]
266mod sha1;
267
268mod external;
269
270#[macro_use]
271mod macros;
272
273#[doc(hidden)]
274#[cfg(feature = "macro-diagnostics")]
275pub extern crate uuid_macro_internal;
276
277#[doc(hidden)]
278pub mod __macro_support {
279 pub use crate::std::result::Result::{Err, Ok};
280}
281
282use crate::std::convert;
283
284pub use crate::{builder::Builder, error::Error};
285
286/// A 128-bit (16 byte) buffer containing the UUID.
287///
288/// # ABI
289///
290/// The `Bytes` type is always guaranteed to be have the same ABI as [`Uuid`].
291pub type Bytes = [u8; 16];
292
293/// The version of the UUID, denoting the generating algorithm.
294///
295/// # References
296///
297/// * [Version Field in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-4.2)
298#[derive(Clone, Copy, Debug, PartialEq)]
299#[non_exhaustive]
300#[repr(u8)]
301pub enum Version {
302 /// The "nil" (all zeros) UUID.
303 Nil = 0u8,
304 /// Version 1: Timestamp and node ID.
305 Mac = 1,
306 /// Version 2: DCE Security.
307 Dce = 2,
308 /// Version 3: MD5 hash.
309 Md5 = 3,
310 /// Version 4: Random.
311 Random = 4,
312 /// Version 5: SHA-1 hash.
313 Sha1 = 5,
314 /// Version 6: Sortable Timestamp and node ID.
315 SortMac = 6,
316 /// Version 7: Timestamp and random.
317 SortRand = 7,
318 /// Version 8: Custom.
319 Custom = 8,
320 /// The "max" (all ones) UUID.
321 Max = 0xff,
322}
323
324/// The reserved variants of UUIDs.
325///
326/// # References
327///
328/// * [Variant Field in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-4.1)
329#[derive(Clone, Copy, Debug, PartialEq)]
330#[non_exhaustive]
331#[repr(u8)]
332pub enum Variant {
333 /// Reserved by the NCS for backward compatibility.
334 NCS = 0u8,
335 /// As described in the RFC 9562 Specification (default).
336 /// (for backward compatibility it is not yet renamed)
337 RFC4122,
338 /// Reserved by Microsoft for backward compatibility.
339 Microsoft,
340 /// Reserved for future expansion.
341 Future,
342}
343
344/// A Universally Unique Identifier (UUID).
345///
346/// # Examples
347///
348/// Parse a UUID given in the simple format and print it as a urn:
349///
350/// ```
351/// # use uuid::Uuid;
352/// # fn main() -> Result<(), uuid::Error> {
353/// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
354///
355/// println!("{}", my_uuid.urn());
356/// # Ok(())
357/// # }
358/// ```
359///
360/// Create a new random (V4) UUID and print it out in hexadecimal form:
361///
362/// ```
363/// // Note that this requires the `v4` feature enabled in the uuid crate.
364/// # use uuid::Uuid;
365/// # fn main() {
366/// # #[cfg(feature = "v4")] {
367/// let my_uuid = Uuid::new_v4();
368///
369/// println!("{}", my_uuid);
370/// # }
371/// # }
372/// ```
373///
374/// # Formatting
375///
376/// A UUID can be formatted in one of a few ways:
377///
378/// * [`simple`](#method.simple): `a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8`.
379/// * [`hyphenated`](#method.hyphenated):
380/// `a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8`.
381/// * [`urn`](#method.urn): `urn:uuid:A1A2A3A4-B1B2-C1C2-D1D2-D3D4D5D6D7D8`.
382/// * [`braced`](#method.braced): `{a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8}`.
383///
384/// The default representation when formatting a UUID with `Display` is
385/// hyphenated:
386///
387/// ```
388/// # use uuid::Uuid;
389/// # fn main() -> Result<(), uuid::Error> {
390/// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
391///
392/// assert_eq!(
393/// "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
394/// my_uuid.to_string(),
395/// );
396/// # Ok(())
397/// # }
398/// ```
399///
400/// Other formats can be specified using adapter methods on the UUID:
401///
402/// ```
403/// # use uuid::Uuid;
404/// # fn main() -> Result<(), uuid::Error> {
405/// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?;
406///
407/// assert_eq!(
408/// "urn:uuid:a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8",
409/// my_uuid.urn().to_string(),
410/// );
411/// # Ok(())
412/// # }
413/// ```
414///
415/// # Endianness
416///
417/// The specification for UUIDs encodes the integer fields that make up the
418/// value in big-endian order. This crate assumes integer inputs are already in
419/// the correct order by default, regardless of the endianness of the
420/// environment. Most methods that accept integers have a `_le` variant (such as
421/// `from_fields_le`) that assumes any integer values will need to have their
422/// bytes flipped, regardless of the endianness of the environment.
423///
424/// Most users won't need to worry about endianness unless they need to operate
425/// on individual fields (such as when converting between Microsoft GUIDs). The
426/// important things to remember are:
427///
428/// - The endianness is in terms of the fields of the UUID, not the environment.
429/// - The endianness is assumed to be big-endian when there's no `_le` suffix
430/// somewhere.
431/// - Byte-flipping in `_le` methods applies to each integer.
432/// - Endianness roundtrips, so if you create a UUID with `from_fields_le`
433/// you'll get the same values back out with `to_fields_le`.
434///
435/// # ABI
436///
437/// The `Uuid` type is always guaranteed to be have the same ABI as [`Bytes`].
438#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
439#[cfg_attr(
440 all(uuid_unstable, feature = "zerocopy"),
441 derive(IntoBytes, FromBytes, KnownLayout, Immutable, Unaligned)
442)]
443#[cfg_attr(
444 feature = "borsh",
445 derive(borsh_derive::BorshDeserialize, borsh_derive::BorshSerialize)
446)]
447#[repr(transparent)]
448#[cfg_attr(
449 feature = "bytemuck",
450 derive(bytemuck::Zeroable, bytemuck::Pod, bytemuck::TransparentWrapper)
451)]
452pub struct Uuid(Bytes);
453
454impl Uuid {
455 /// UUID namespace for Domain Name System (DNS).
456 pub const NAMESPACE_DNS: Self = Uuid([
457 0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
458 0xc8,
459 ]);
460
461 /// UUID namespace for ISO Object Identifiers (OIDs).
462 pub const NAMESPACE_OID: Self = Uuid([
463 0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
464 0xc8,
465 ]);
466
467 /// UUID namespace for Uniform Resource Locators (URLs).
468 pub const NAMESPACE_URL: Self = Uuid([
469 0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
470 0xc8,
471 ]);
472
473 /// UUID namespace for X.500 Distinguished Names (DNs).
474 pub const NAMESPACE_X500: Self = Uuid([
475 0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30,
476 0xc8,
477 ]);
478
479 /// Returns the variant of the UUID structure.
480 ///
481 /// This determines the interpretation of the structure of the UUID.
482 /// This method simply reads the value of the variant byte. It doesn't
483 /// validate the rest of the UUID as conforming to that variant.
484 ///
485 /// # Examples
486 ///
487 /// Basic usage:
488 ///
489 /// ```
490 /// # use uuid::{Uuid, Variant};
491 /// # fn main() -> Result<(), uuid::Error> {
492 /// let my_uuid = Uuid::parse_str("02f09a3f-1624-3b1d-8409-44eff7708208")?;
493 ///
494 /// assert_eq!(Variant::RFC4122, my_uuid.get_variant());
495 /// # Ok(())
496 /// # }
497 /// ```
498 ///
499 /// # References
500 ///
501 /// * [Variant Field in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-4.1)
502 pub const fn get_variant(&self) -> Variant {
503 match self.as_bytes()[8] {
504 x if x & 0x80 == 0x00 => Variant::NCS,
505 x if x & 0xc0 == 0x80 => Variant::RFC4122,
506 x if x & 0xe0 == 0xc0 => Variant::Microsoft,
507 x if x & 0xe0 == 0xe0 => Variant::Future,
508 // The above match arms are actually exhaustive
509 // We just return `Future` here because we can't
510 // use `unreachable!()` in a `const fn`
511 _ => Variant::Future,
512 }
513 }
514
515 /// Returns the version number of the UUID.
516 ///
517 /// This represents the algorithm used to generate the value.
518 /// This method is the future-proof alternative to [`Uuid::get_version`].
519 ///
520 /// # Examples
521 ///
522 /// Basic usage:
523 ///
524 /// ```
525 /// # use uuid::Uuid;
526 /// # fn main() -> Result<(), uuid::Error> {
527 /// let my_uuid = Uuid::parse_str("02f09a3f-1624-3b1d-8409-44eff7708208")?;
528 ///
529 /// assert_eq!(3, my_uuid.get_version_num());
530 /// # Ok(())
531 /// # }
532 /// ```
533 ///
534 /// # References
535 ///
536 /// * [Version Field in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-4.2)
537 pub const fn get_version_num(&self) -> usize {
538 (self.as_bytes()[6] >> 4) as usize
539 }
540
541 /// Returns the version of the UUID.
542 ///
543 /// This represents the algorithm used to generate the value.
544 /// If the version field doesn't contain a recognized version then `None`
545 /// is returned. If you're trying to read the version for a future extension
546 /// you can also use [`Uuid::get_version_num`] to unconditionally return a
547 /// number. Future extensions may start to return `Some` once they're
548 /// standardized and supported.
549 ///
550 /// # Examples
551 ///
552 /// Basic usage:
553 ///
554 /// ```
555 /// # use uuid::{Uuid, Version};
556 /// # fn main() -> Result<(), uuid::Error> {
557 /// let my_uuid = Uuid::parse_str("02f09a3f-1624-3b1d-8409-44eff7708208")?;
558 ///
559 /// assert_eq!(Some(Version::Md5), my_uuid.get_version());
560 /// # Ok(())
561 /// # }
562 /// ```
563 ///
564 /// # References
565 ///
566 /// * [Version Field in RFC 9562](https://www.ietf.org/rfc/rfc9562.html#section-4.2)
567 pub const fn get_version(&self) -> Option<Version> {
568 match self.get_version_num() {
569 0 if self.is_nil() => Some(Version::Nil),
570 1 => Some(Version::Mac),
571 2 => Some(Version::Dce),
572 3 => Some(Version::Md5),
573 4 => Some(Version::Random),
574 5 => Some(Version::Sha1),
575 6 => Some(Version::SortMac),
576 7 => Some(Version::SortRand),
577 8 => Some(Version::Custom),
578 0xf => Some(Version::Max),
579 _ => None,
580 }
581 }
582
583 /// Returns the four field values of the UUID.
584 ///
585 /// These values can be passed to the [`Uuid::from_fields`] method to get
586 /// the original `Uuid` back.
587 ///
588 /// * The first field value represents the first group of (eight) hex
589 /// digits, taken as a big-endian `u32` value. For V1 UUIDs, this field
590 /// represents the low 32 bits of the timestamp.
591 /// * The second field value represents the second group of (four) hex
592 /// digits, taken as a big-endian `u16` value. For V1 UUIDs, this field
593 /// represents the middle 16 bits of the timestamp.
594 /// * The third field value represents the third group of (four) hex digits,
595 /// taken as a big-endian `u16` value. The 4 most significant bits give
596 /// the UUID version, and for V1 UUIDs, the last 12 bits represent the
597 /// high 12 bits of the timestamp.
598 /// * The last field value represents the last two groups of four and twelve
599 /// hex digits, taken in order. The first 1-3 bits of this indicate the
600 /// UUID variant, and for V1 UUIDs, the next 13-15 bits indicate the clock
601 /// sequence and the last 48 bits indicate the node ID.
602 ///
603 /// # Examples
604 ///
605 /// ```
606 /// # use uuid::Uuid;
607 /// # fn main() -> Result<(), uuid::Error> {
608 /// let uuid = Uuid::nil();
609 ///
610 /// assert_eq!(uuid.as_fields(), (0, 0, 0, &[0u8; 8]));
611 ///
612 /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
613 ///
614 /// assert_eq!(
615 /// uuid.as_fields(),
616 /// (
617 /// 0xa1a2a3a4,
618 /// 0xb1b2,
619 /// 0xc1c2,
620 /// &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8],
621 /// )
622 /// );
623 /// # Ok(())
624 /// # }
625 /// ```
626 pub fn as_fields(&self) -> (u32, u16, u16, &[u8; 8]) {
627 let bytes = self.as_bytes();
628
629 let d1 = (bytes[0] as u32) << 24
630 | (bytes[1] as u32) << 16
631 | (bytes[2] as u32) << 8
632 | (bytes[3] as u32);
633
634 let d2 = (bytes[4] as u16) << 8 | (bytes[5] as u16);
635
636 let d3 = (bytes[6] as u16) << 8 | (bytes[7] as u16);
637
638 let d4: &[u8; 8] = convert::TryInto::try_into(&bytes[8..16]).unwrap();
639 (d1, d2, d3, d4)
640 }
641
642 /// Returns the four field values of the UUID in little-endian order.
643 ///
644 /// The bytes in the returned integer fields will be converted from
645 /// big-endian order. This is based on the endianness of the UUID,
646 /// rather than the target environment so bytes will be flipped on both
647 /// big and little endian machines.
648 ///
649 /// # Examples
650 ///
651 /// ```
652 /// use uuid::Uuid;
653 ///
654 /// # fn main() -> Result<(), uuid::Error> {
655 /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
656 ///
657 /// assert_eq!(
658 /// uuid.to_fields_le(),
659 /// (
660 /// 0xa4a3a2a1,
661 /// 0xb2b1,
662 /// 0xc2c1,
663 /// &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8],
664 /// )
665 /// );
666 /// # Ok(())
667 /// # }
668 /// ```
669 pub fn to_fields_le(&self) -> (u32, u16, u16, &[u8; 8]) {
670 let d1 = (self.as_bytes()[0] as u32)
671 | (self.as_bytes()[1] as u32) << 8
672 | (self.as_bytes()[2] as u32) << 16
673 | (self.as_bytes()[3] as u32) << 24;
674
675 let d2 = (self.as_bytes()[4] as u16) | (self.as_bytes()[5] as u16) << 8;
676
677 let d3 = (self.as_bytes()[6] as u16) | (self.as_bytes()[7] as u16) << 8;
678
679 let d4: &[u8; 8] = convert::TryInto::try_into(&self.as_bytes()[8..16]).unwrap();
680 (d1, d2, d3, d4)
681 }
682
683 /// Returns a 128bit value containing the value.
684 ///
685 /// The bytes in the UUID will be packed directly into a `u128`.
686 ///
687 /// # Examples
688 ///
689 /// ```
690 /// # use uuid::Uuid;
691 /// # fn main() -> Result<(), uuid::Error> {
692 /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
693 ///
694 /// assert_eq!(
695 /// uuid.as_u128(),
696 /// 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8,
697 /// );
698 /// # Ok(())
699 /// # }
700 /// ```
701 pub const fn as_u128(&self) -> u128 {
702 u128::from_be_bytes(*self.as_bytes())
703 }
704
705 /// Returns a 128bit little-endian value containing the value.
706 ///
707 /// The bytes in the `u128` will be flipped to convert into big-endian
708 /// order. This is based on the endianness of the UUID, rather than the
709 /// target environment so bytes will be flipped on both big and little
710 /// endian machines.
711 ///
712 /// Note that this will produce a different result than
713 /// [`Uuid::to_fields_le`], because the entire UUID is reversed, rather
714 /// than reversing the individual fields in-place.
715 ///
716 /// # Examples
717 ///
718 /// ```
719 /// # use uuid::Uuid;
720 /// # fn main() -> Result<(), uuid::Error> {
721 /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
722 ///
723 /// assert_eq!(
724 /// uuid.to_u128_le(),
725 /// 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1,
726 /// );
727 /// # Ok(())
728 /// # }
729 /// ```
730 pub const fn to_u128_le(&self) -> u128 {
731 u128::from_le_bytes(*self.as_bytes())
732 }
733
734 /// Returns two 64bit values containing the value.
735 ///
736 /// The bytes in the UUID will be split into two `u64`.
737 /// The first u64 represents the 64 most significant bits,
738 /// the second one represents the 64 least significant.
739 ///
740 /// # Examples
741 ///
742 /// ```
743 /// # use uuid::Uuid;
744 /// # fn main() -> Result<(), uuid::Error> {
745 /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
746 /// assert_eq!(
747 /// uuid.as_u64_pair(),
748 /// (0xa1a2a3a4b1b2c1c2, 0xd1d2d3d4d5d6d7d8),
749 /// );
750 /// # Ok(())
751 /// # }
752 /// ```
753 pub const fn as_u64_pair(&self) -> (u64, u64) {
754 let value = self.as_u128();
755 ((value >> 64) as u64, value as u64)
756 }
757
758 /// Returns a slice of 16 octets containing the value.
759 ///
760 /// This method borrows the underlying byte value of the UUID.
761 ///
762 /// # Examples
763 ///
764 /// ```
765 /// # use uuid::Uuid;
766 /// let bytes1 = [
767 /// 0xa1, 0xa2, 0xa3, 0xa4,
768 /// 0xb1, 0xb2,
769 /// 0xc1, 0xc2,
770 /// 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
771 /// ];
772 /// let uuid1 = Uuid::from_bytes_ref(&bytes1);
773 ///
774 /// let bytes2 = uuid1.as_bytes();
775 /// let uuid2 = Uuid::from_bytes_ref(bytes2);
776 ///
777 /// assert_eq!(uuid1, uuid2);
778 ///
779 /// assert!(std::ptr::eq(
780 /// uuid2 as *const Uuid as *const u8,
781 /// &bytes1 as *const [u8; 16] as *const u8,
782 /// ));
783 /// ```
784 #[inline]
785 pub const fn as_bytes(&self) -> &Bytes {
786 &self.0
787 }
788
789 /// Consumes self and returns the underlying byte value of the UUID.
790 ///
791 /// # Examples
792 ///
793 /// ```
794 /// # use uuid::Uuid;
795 /// let bytes = [
796 /// 0xa1, 0xa2, 0xa3, 0xa4,
797 /// 0xb1, 0xb2,
798 /// 0xc1, 0xc2,
799 /// 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8,
800 /// ];
801 /// let uuid = Uuid::from_bytes(bytes);
802 /// assert_eq!(bytes, uuid.into_bytes());
803 /// ```
804 #[inline]
805 pub const fn into_bytes(self) -> Bytes {
806 self.0
807 }
808
809 /// Returns the bytes of the UUID in little-endian order.
810 ///
811 /// The bytes will be flipped to convert into little-endian order. This is
812 /// based on the endianness of the UUID, rather than the target environment
813 /// so bytes will be flipped on both big and little endian machines.
814 ///
815 /// # Examples
816 ///
817 /// ```
818 /// use uuid::Uuid;
819 ///
820 /// # fn main() -> Result<(), uuid::Error> {
821 /// let uuid = Uuid::parse_str("a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8")?;
822 ///
823 /// assert_eq!(
824 /// uuid.to_bytes_le(),
825 /// ([
826 /// 0xa4, 0xa3, 0xa2, 0xa1, 0xb2, 0xb1, 0xc2, 0xc1, 0xd1, 0xd2,
827 /// 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8
828 /// ])
829 /// );
830 /// # Ok(())
831 /// # }
832 /// ```
833 pub const fn to_bytes_le(&self) -> Bytes {
834 [
835 self.0[3], self.0[2], self.0[1], self.0[0], self.0[5], self.0[4], self.0[7], self.0[6],
836 self.0[8], self.0[9], self.0[10], self.0[11], self.0[12], self.0[13], self.0[14],
837 self.0[15],
838 ]
839 }
840
841 /// Tests if the UUID is nil (all zeros).
842 pub const fn is_nil(&self) -> bool {
843 self.as_u128() == u128::MIN
844 }
845
846 /// Tests if the UUID is max (all ones).
847 pub const fn is_max(&self) -> bool {
848 self.as_u128() == u128::MAX
849 }
850
851 /// A buffer that can be used for `encode_...` calls, that is
852 /// guaranteed to be long enough for any of the format adapters.
853 ///
854 /// # Examples
855 ///
856 /// ```
857 /// # use uuid::Uuid;
858 /// let uuid = Uuid::nil();
859 ///
860 /// assert_eq!(
861 /// uuid.simple().encode_lower(&mut Uuid::encode_buffer()),
862 /// "00000000000000000000000000000000"
863 /// );
864 ///
865 /// assert_eq!(
866 /// uuid.hyphenated()
867 /// .encode_lower(&mut Uuid::encode_buffer()),
868 /// "00000000-0000-0000-0000-000000000000"
869 /// );
870 ///
871 /// assert_eq!(
872 /// uuid.urn().encode_lower(&mut Uuid::encode_buffer()),
873 /// "urn:uuid:00000000-0000-0000-0000-000000000000"
874 /// );
875 /// ```
876 pub const fn encode_buffer() -> [u8; fmt::Urn::LENGTH] {
877 [0; fmt::Urn::LENGTH]
878 }
879
880 /// If the UUID is the correct version (v1, v6, or v7) this will return
881 /// the timestamp in a version-agnostic [`Timestamp`]. For other versions
882 /// this will return `None`.
883 ///
884 /// # Roundtripping
885 ///
886 /// This method is unlikely to roundtrip a timestamp in a UUID due to the way
887 /// UUIDs encode timestamps. The timestamp returned from this method will be truncated to
888 /// 100ns precision for version 1 and 6 UUIDs, and to millisecond precision for version 7 UUIDs.
889 pub const fn get_timestamp(&self) -> Option<Timestamp> {
890 match self.get_version() {
891 Some(Version::Mac) => {
892 let (ticks, counter) = timestamp::decode_gregorian_timestamp(self);
893
894 Some(Timestamp::from_gregorian(ticks, counter))
895 }
896 Some(Version::SortMac) => {
897 let (ticks, counter) = timestamp::decode_sorted_gregorian_timestamp(self);
898
899 Some(Timestamp::from_gregorian(ticks, counter))
900 }
901 Some(Version::SortRand) => {
902 let millis = timestamp::decode_unix_timestamp_millis(self);
903
904 let seconds = millis / 1000;
905 let nanos = ((millis % 1000) * 1_000_000) as u32;
906
907 Some(Timestamp::from_unix_time(seconds, nanos, 0, 0))
908 }
909 _ => None,
910 }
911 }
912
913 /// If the UUID is the correct version (v1, or v6) this will return the
914 /// node value as a 6-byte array. For other versions this will return `None`.
915 pub const fn get_node_id(&self) -> Option<[u8; 6]> {
916 match self.get_version() {
917 Some(Version::Mac) | Some(Version::SortMac) => {
918 let mut node_id = [0; 6];
919
920 node_id[0] = self.0[10];
921 node_id[1] = self.0[11];
922 node_id[2] = self.0[12];
923 node_id[3] = self.0[13];
924 node_id[4] = self.0[14];
925 node_id[5] = self.0[15];
926
927 Some(node_id)
928 }
929 _ => None,
930 }
931 }
932}
933
934impl Default for Uuid {
935 #[inline]
936 fn default() -> Self {
937 Uuid::nil()
938 }
939}
940
941impl AsRef<Uuid> for Uuid {
942 #[inline]
943 fn as_ref(&self) -> &Uuid {
944 self
945 }
946}
947
948impl AsRef<[u8]> for Uuid {
949 #[inline]
950 fn as_ref(&self) -> &[u8] {
951 &self.0
952 }
953}
954
955#[cfg(feature = "std")]
956impl From<Uuid> for std::vec::Vec<u8> {
957 fn from(value: Uuid) -> Self {
958 value.0.to_vec()
959 }
960}
961
962#[cfg(feature = "std")]
963impl std::convert::TryFrom<std::vec::Vec<u8>> for Uuid {
964 type Error = Error;
965
966 fn try_from(value: std::vec::Vec<u8>) -> Result<Self, Self::Error> {
967 Uuid::from_slice(&value)
968 }
969}
970
971#[cfg(feature = "serde")]
972pub mod serde {
973 //! Adapters for alternative `serde` formats.
974 //!
975 //! This module contains adapters you can use with [`#[serde(with)]`](https://serde.rs/field-attrs.html#with)
976 //! to change the way a [`Uuid`](../struct.Uuid.html) is serialized
977 //! and deserialized.
978
979 pub use crate::external::serde_support::{braced, compact, simple, urn};
980}
981
982#[cfg(test)]
983mod tests {
984 use super::*;
985
986 use crate::std::string::{String, ToString};
987
988 #[cfg(all(
989 target_arch = "wasm32",
990 target_vendor = "unknown",
991 target_os = "unknown"
992 ))]
993 use wasm_bindgen_test::*;
994
995 macro_rules! check {
996 ($buf:ident, $format:expr, $target:expr, $len:expr, $cond:expr) => {
997 $buf.clear();
998 write!($buf, $format, $target).unwrap();
999 assert!($buf.len() == $len);
1000 assert!($buf.chars().all($cond), "{}", $buf);
1001 };
1002 }
1003
1004 pub const fn new() -> Uuid {
1005 Uuid::from_bytes([
1006 0xF9, 0x16, 0x8C, 0x5E, 0xCE, 0xB2, 0x4F, 0xAA, 0xB6, 0xBF, 0x32, 0x9B, 0xF3, 0x9F,
1007 0xA1, 0xE4,
1008 ])
1009 }
1010
1011 pub const fn new2() -> Uuid {
1012 Uuid::from_bytes([
1013 0xF9, 0x16, 0x8C, 0x5E, 0xCE, 0xB2, 0x4F, 0xAB, 0xB6, 0xBF, 0x32, 0x9B, 0xF3, 0x9F,
1014 0xA1, 0xE4,
1015 ])
1016 }
1017
1018 #[test]
1019 #[cfg_attr(
1020 all(
1021 target_arch = "wasm32",
1022 target_vendor = "unknown",
1023 target_os = "unknown"
1024 ),
1025 wasm_bindgen_test
1026 )]
1027 fn test_uuid_compare() {
1028 let uuid1 = new();
1029 let uuid2 = new2();
1030
1031 assert_eq!(uuid1, uuid1);
1032 assert_eq!(uuid2, uuid2);
1033
1034 assert_ne!(uuid1, uuid2);
1035 assert_ne!(uuid2, uuid1);
1036 }
1037
1038 #[test]
1039 #[cfg_attr(
1040 all(
1041 target_arch = "wasm32",
1042 target_vendor = "unknown",
1043 target_os = "unknown"
1044 ),
1045 wasm_bindgen_test
1046 )]
1047 fn test_uuid_default() {
1048 let default_uuid = Uuid::default();
1049 let nil_uuid = Uuid::nil();
1050
1051 assert_eq!(default_uuid, nil_uuid);
1052 }
1053
1054 #[test]
1055 #[cfg_attr(
1056 all(
1057 target_arch = "wasm32",
1058 target_vendor = "unknown",
1059 target_os = "unknown"
1060 ),
1061 wasm_bindgen_test
1062 )]
1063 fn test_uuid_display() {
1064 use crate::std::fmt::Write;
1065
1066 let uuid = new();
1067 let s = uuid.to_string();
1068 let mut buffer = String::new();
1069
1070 assert_eq!(s, uuid.hyphenated().to_string());
1071
1072 check!(buffer, "{}", uuid, 36, |c| c.is_lowercase()
1073 || c.is_digit(10)
1074 || c == '-');
1075 }
1076
1077 #[test]
1078 #[cfg_attr(
1079 all(
1080 target_arch = "wasm32",
1081 target_vendor = "unknown",
1082 target_os = "unknown"
1083 ),
1084 wasm_bindgen_test
1085 )]
1086 fn test_uuid_lowerhex() {
1087 use crate::std::fmt::Write;
1088
1089 let mut buffer = String::new();
1090 let uuid = new();
1091
1092 check!(buffer, "{:x}", uuid, 36, |c| c.is_lowercase()
1093 || c.is_digit(10)
1094 || c == '-');
1095 }
1096
1097 // noinspection RsAssertEqual
1098 #[test]
1099 #[cfg_attr(
1100 all(
1101 target_arch = "wasm32",
1102 target_vendor = "unknown",
1103 target_os = "unknown"
1104 ),
1105 wasm_bindgen_test
1106 )]
1107 fn test_uuid_operator_eq() {
1108 let uuid1 = new();
1109 let uuid1_dup = uuid1.clone();
1110 let uuid2 = new2();
1111
1112 assert!(uuid1 == uuid1);
1113 assert!(uuid1 == uuid1_dup);
1114 assert!(uuid1_dup == uuid1);
1115
1116 assert!(uuid1 != uuid2);
1117 assert!(uuid2 != uuid1);
1118 assert!(uuid1_dup != uuid2);
1119 assert!(uuid2 != uuid1_dup);
1120 }
1121
1122 #[test]
1123 #[cfg_attr(
1124 all(
1125 target_arch = "wasm32",
1126 target_vendor = "unknown",
1127 target_os = "unknown"
1128 ),
1129 wasm_bindgen_test
1130 )]
1131 fn test_uuid_to_string() {
1132 use crate::std::fmt::Write;
1133
1134 let uuid = new();
1135 let s = uuid.to_string();
1136 let mut buffer = String::new();
1137
1138 assert_eq!(s.len(), 36);
1139
1140 check!(buffer, "{}", s, 36, |c| c.is_lowercase()
1141 || c.is_digit(10)
1142 || c == '-');
1143 }
1144
1145 #[test]
1146 #[cfg_attr(
1147 all(
1148 target_arch = "wasm32",
1149 target_vendor = "unknown",
1150 target_os = "unknown"
1151 ),
1152 wasm_bindgen_test
1153 )]
1154 fn test_non_conforming() {
1155 let from_bytes =
1156 Uuid::from_bytes([4, 54, 67, 12, 43, 2, 2, 76, 32, 50, 87, 5, 1, 33, 43, 87]);
1157
1158 assert_eq!(from_bytes.get_version(), None);
1159 }
1160
1161 #[test]
1162 #[cfg_attr(
1163 all(
1164 target_arch = "wasm32",
1165 target_vendor = "unknown",
1166 target_os = "unknown"
1167 ),
1168 wasm_bindgen_test
1169 )]
1170 fn test_nil() {
1171 let nil = Uuid::nil();
1172 let not_nil = new();
1173
1174 assert!(nil.is_nil());
1175 assert!(!not_nil.is_nil());
1176
1177 assert_eq!(nil.get_version(), Some(Version::Nil));
1178 assert_eq!(not_nil.get_version(), Some(Version::Random));
1179
1180 assert_eq!(
1181 nil,
1182 Builder::from_bytes([0; 16])
1183 .with_version(Version::Nil)
1184 .into_uuid()
1185 );
1186 }
1187
1188 #[test]
1189 #[cfg_attr(
1190 all(
1191 target_arch = "wasm32",
1192 target_vendor = "unknown",
1193 target_os = "unknown"
1194 ),
1195 wasm_bindgen_test
1196 )]
1197 fn test_max() {
1198 let max = Uuid::max();
1199 let not_max = new();
1200
1201 assert!(max.is_max());
1202 assert!(!not_max.is_max());
1203
1204 assert_eq!(max.get_version(), Some(Version::Max));
1205 assert_eq!(not_max.get_version(), Some(Version::Random));
1206
1207 assert_eq!(
1208 max,
1209 Builder::from_bytes([0xff; 16])
1210 .with_version(Version::Max)
1211 .into_uuid()
1212 );
1213 }
1214
1215 #[test]
1216 #[cfg_attr(
1217 all(
1218 target_arch = "wasm32",
1219 target_vendor = "unknown",
1220 target_os = "unknown"
1221 ),
1222 wasm_bindgen_test
1223 )]
1224 fn test_predefined_namespaces() {
1225 assert_eq!(
1226 Uuid::NAMESPACE_DNS.hyphenated().to_string(),
1227 "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
1228 );
1229 assert_eq!(
1230 Uuid::NAMESPACE_URL.hyphenated().to_string(),
1231 "6ba7b811-9dad-11d1-80b4-00c04fd430c8"
1232 );
1233 assert_eq!(
1234 Uuid::NAMESPACE_OID.hyphenated().to_string(),
1235 "6ba7b812-9dad-11d1-80b4-00c04fd430c8"
1236 );
1237 assert_eq!(
1238 Uuid::NAMESPACE_X500.hyphenated().to_string(),
1239 "6ba7b814-9dad-11d1-80b4-00c04fd430c8"
1240 );
1241 }
1242
1243 #[cfg(feature = "v3")]
1244 #[test]
1245 #[cfg_attr(
1246 all(
1247 target_arch = "wasm32",
1248 target_vendor = "unknown",
1249 target_os = "unknown"
1250 ),
1251 wasm_bindgen_test
1252 )]
1253 fn test_get_version_v3() {
1254 let uuid = Uuid::new_v3(&Uuid::NAMESPACE_DNS, "rust-lang.org".as_bytes());
1255
1256 assert_eq!(uuid.get_version().unwrap(), Version::Md5);
1257 assert_eq!(uuid.get_version_num(), 3);
1258 }
1259
1260 #[test]
1261 #[cfg_attr(
1262 all(
1263 target_arch = "wasm32",
1264 target_vendor = "unknown",
1265 target_os = "unknown"
1266 ),
1267 wasm_bindgen_test
1268 )]
1269 fn test_get_timestamp_unsupported_version() {
1270 let uuid = new();
1271
1272 assert_ne!(Version::Mac, uuid.get_version().unwrap());
1273 assert_ne!(Version::SortMac, uuid.get_version().unwrap());
1274 assert_ne!(Version::SortRand, uuid.get_version().unwrap());
1275
1276 assert!(uuid.get_timestamp().is_none());
1277 }
1278
1279 #[test]
1280 #[cfg_attr(
1281 all(
1282 target_arch = "wasm32",
1283 target_vendor = "unknown",
1284 target_os = "unknown"
1285 ),
1286 wasm_bindgen_test
1287 )]
1288 fn test_get_node_id_unsupported_version() {
1289 let uuid = new();
1290
1291 assert_ne!(Version::Mac, uuid.get_version().unwrap());
1292 assert_ne!(Version::SortMac, uuid.get_version().unwrap());
1293
1294 assert!(uuid.get_node_id().is_none());
1295 }
1296
1297 #[test]
1298 #[cfg_attr(
1299 all(
1300 target_arch = "wasm32",
1301 target_vendor = "unknown",
1302 target_os = "unknown"
1303 ),
1304 wasm_bindgen_test
1305 )]
1306 fn test_get_variant() {
1307 let uuid1 = new();
1308 let uuid2 = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
1309 let uuid3 = Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8").unwrap();
1310 let uuid4 = Uuid::parse_str("936DA01F9ABD4d9dC0C702AF85C822A8").unwrap();
1311 let uuid5 = Uuid::parse_str("F9168C5E-CEB2-4faa-D6BF-329BF39FA1E4").unwrap();
1312 let uuid6 = Uuid::parse_str("f81d4fae-7dec-11d0-7765-00a0c91e6bf6").unwrap();
1313
1314 assert_eq!(uuid1.get_variant(), Variant::RFC4122);
1315 assert_eq!(uuid2.get_variant(), Variant::RFC4122);
1316 assert_eq!(uuid3.get_variant(), Variant::RFC4122);
1317 assert_eq!(uuid4.get_variant(), Variant::Microsoft);
1318 assert_eq!(uuid5.get_variant(), Variant::Microsoft);
1319 assert_eq!(uuid6.get_variant(), Variant::NCS);
1320 }
1321
1322 #[test]
1323 #[cfg_attr(
1324 all(
1325 target_arch = "wasm32",
1326 target_vendor = "unknown",
1327 target_os = "unknown"
1328 ),
1329 wasm_bindgen_test
1330 )]
1331 fn test_to_simple_string() {
1332 let uuid1 = new();
1333 let s = uuid1.simple().to_string();
1334
1335 assert_eq!(s.len(), 32);
1336 assert!(s.chars().all(|c| c.is_digit(16)));
1337 }
1338
1339 #[test]
1340 #[cfg_attr(
1341 all(
1342 target_arch = "wasm32",
1343 target_vendor = "unknown",
1344 target_os = "unknown"
1345 ),
1346 wasm_bindgen_test
1347 )]
1348 fn test_hyphenated_string() {
1349 let uuid1 = new();
1350 let s = uuid1.hyphenated().to_string();
1351
1352 assert_eq!(36, s.len());
1353 assert!(s.chars().all(|c| c.is_digit(16) || c == '-'));
1354 }
1355
1356 #[test]
1357 #[cfg_attr(
1358 all(
1359 target_arch = "wasm32",
1360 target_vendor = "unknown",
1361 target_os = "unknown"
1362 ),
1363 wasm_bindgen_test
1364 )]
1365 fn test_upper_lower_hex() {
1366 use std::fmt::Write;
1367
1368 let mut buf = String::new();
1369 let u = new();
1370
1371 macro_rules! check {
1372 ($buf:ident, $format:expr, $target:expr, $len:expr, $cond:expr) => {
1373 $buf.clear();
1374 write!($buf, $format, $target).unwrap();
1375 assert_eq!($len, buf.len());
1376 assert!($buf.chars().all($cond), "{}", $buf);
1377 };
1378 }
1379
1380 check!(buf, "{:x}", u, 36, |c| c.is_lowercase()
1381 || c.is_digit(10)
1382 || c == '-');
1383 check!(buf, "{:X}", u, 36, |c| c.is_uppercase()
1384 || c.is_digit(10)
1385 || c == '-');
1386 check!(buf, "{:#x}", u, 36, |c| c.is_lowercase()
1387 || c.is_digit(10)
1388 || c == '-');
1389 check!(buf, "{:#X}", u, 36, |c| c.is_uppercase()
1390 || c.is_digit(10)
1391 || c == '-');
1392
1393 check!(buf, "{:X}", u.hyphenated(), 36, |c| c.is_uppercase()
1394 || c.is_digit(10)
1395 || c == '-');
1396 check!(buf, "{:X}", u.simple(), 32, |c| c.is_uppercase()
1397 || c.is_digit(10));
1398 check!(buf, "{:#X}", u.hyphenated(), 36, |c| c.is_uppercase()
1399 || c.is_digit(10)
1400 || c == '-');
1401 check!(buf, "{:#X}", u.simple(), 32, |c| c.is_uppercase()
1402 || c.is_digit(10));
1403
1404 check!(buf, "{:x}", u.hyphenated(), 36, |c| c.is_lowercase()
1405 || c.is_digit(10)
1406 || c == '-');
1407 check!(buf, "{:x}", u.simple(), 32, |c| c.is_lowercase()
1408 || c.is_digit(10));
1409 check!(buf, "{:#x}", u.hyphenated(), 36, |c| c.is_lowercase()
1410 || c.is_digit(10)
1411 || c == '-');
1412 check!(buf, "{:#x}", u.simple(), 32, |c| c.is_lowercase()
1413 || c.is_digit(10));
1414 }
1415
1416 #[test]
1417 #[cfg_attr(
1418 all(
1419 target_arch = "wasm32",
1420 target_vendor = "unknown",
1421 target_os = "unknown"
1422 ),
1423 wasm_bindgen_test
1424 )]
1425 fn test_to_urn_string() {
1426 let uuid1 = new();
1427 let ss = uuid1.urn().to_string();
1428 let s = &ss[9..];
1429
1430 assert!(ss.starts_with("urn:uuid:"));
1431 assert_eq!(s.len(), 36);
1432 assert!(s.chars().all(|c| c.is_digit(16) || c == '-'));
1433 }
1434
1435 #[test]
1436 #[cfg_attr(
1437 all(
1438 target_arch = "wasm32",
1439 target_vendor = "unknown",
1440 target_os = "unknown"
1441 ),
1442 wasm_bindgen_test
1443 )]
1444 fn test_to_simple_string_matching() {
1445 let uuid1 = new();
1446
1447 let hs = uuid1.hyphenated().to_string();
1448 let ss = uuid1.simple().to_string();
1449
1450 let hsn = hs.chars().filter(|&c| c != '-').collect::<String>();
1451
1452 assert_eq!(hsn, ss);
1453 }
1454
1455 #[test]
1456 #[cfg_attr(
1457 all(
1458 target_arch = "wasm32",
1459 target_vendor = "unknown",
1460 target_os = "unknown"
1461 ),
1462 wasm_bindgen_test
1463 )]
1464 fn test_string_roundtrip() {
1465 let uuid = new();
1466
1467 let hs = uuid.hyphenated().to_string();
1468 let uuid_hs = Uuid::parse_str(&hs).unwrap();
1469 assert_eq!(uuid_hs, uuid);
1470
1471 let ss = uuid.to_string();
1472 let uuid_ss = Uuid::parse_str(&ss).unwrap();
1473 assert_eq!(uuid_ss, uuid);
1474 }
1475
1476 #[test]
1477 #[cfg_attr(
1478 all(
1479 target_arch = "wasm32",
1480 target_vendor = "unknown",
1481 target_os = "unknown"
1482 ),
1483 wasm_bindgen_test
1484 )]
1485 fn test_from_fields() {
1486 let d1: u32 = 0xa1a2a3a4;
1487 let d2: u16 = 0xb1b2;
1488 let d3: u16 = 0xc1c2;
1489 let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1490
1491 let u = Uuid::from_fields(d1, d2, d3, &d4);
1492
1493 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1494 let result = u.simple().to_string();
1495 assert_eq!(result, expected);
1496 }
1497
1498 #[test]
1499 #[cfg_attr(
1500 all(
1501 target_arch = "wasm32",
1502 target_vendor = "unknown",
1503 target_os = "unknown"
1504 ),
1505 wasm_bindgen_test
1506 )]
1507 fn test_from_fields_le() {
1508 let d1: u32 = 0xa4a3a2a1;
1509 let d2: u16 = 0xb2b1;
1510 let d3: u16 = 0xc2c1;
1511 let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1512
1513 let u = Uuid::from_fields_le(d1, d2, d3, &d4);
1514
1515 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1516 let result = u.simple().to_string();
1517 assert_eq!(result, expected);
1518 }
1519
1520 #[test]
1521 #[cfg_attr(
1522 all(
1523 target_arch = "wasm32",
1524 target_vendor = "unknown",
1525 target_os = "unknown"
1526 ),
1527 wasm_bindgen_test
1528 )]
1529 fn test_as_fields() {
1530 let u = new();
1531 let (d1, d2, d3, d4) = u.as_fields();
1532
1533 assert_ne!(d1, 0);
1534 assert_ne!(d2, 0);
1535 assert_ne!(d3, 0);
1536 assert_eq!(d4.len(), 8);
1537 assert!(!d4.iter().all(|&b| b == 0));
1538 }
1539
1540 #[test]
1541 #[cfg_attr(
1542 all(
1543 target_arch = "wasm32",
1544 target_vendor = "unknown",
1545 target_os = "unknown"
1546 ),
1547 wasm_bindgen_test
1548 )]
1549 fn test_fields_roundtrip() {
1550 let d1_in: u32 = 0xa1a2a3a4;
1551 let d2_in: u16 = 0xb1b2;
1552 let d3_in: u16 = 0xc1c2;
1553 let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1554
1555 let u = Uuid::from_fields(d1_in, d2_in, d3_in, d4_in);
1556 let (d1_out, d2_out, d3_out, d4_out) = u.as_fields();
1557
1558 assert_eq!(d1_in, d1_out);
1559 assert_eq!(d2_in, d2_out);
1560 assert_eq!(d3_in, d3_out);
1561 assert_eq!(d4_in, d4_out);
1562 }
1563
1564 #[test]
1565 #[cfg_attr(
1566 all(
1567 target_arch = "wasm32",
1568 target_vendor = "unknown",
1569 target_os = "unknown"
1570 ),
1571 wasm_bindgen_test
1572 )]
1573 fn test_fields_le_roundtrip() {
1574 let d1_in: u32 = 0xa4a3a2a1;
1575 let d2_in: u16 = 0xb2b1;
1576 let d3_in: u16 = 0xc2c1;
1577 let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1578
1579 let u = Uuid::from_fields_le(d1_in, d2_in, d3_in, d4_in);
1580 let (d1_out, d2_out, d3_out, d4_out) = u.to_fields_le();
1581
1582 assert_eq!(d1_in, d1_out);
1583 assert_eq!(d2_in, d2_out);
1584 assert_eq!(d3_in, d3_out);
1585 assert_eq!(d4_in, d4_out);
1586 }
1587
1588 #[test]
1589 #[cfg_attr(
1590 all(
1591 target_arch = "wasm32",
1592 target_vendor = "unknown",
1593 target_os = "unknown"
1594 ),
1595 wasm_bindgen_test
1596 )]
1597 fn test_fields_le_are_actually_le() {
1598 let d1_in: u32 = 0xa1a2a3a4;
1599 let d2_in: u16 = 0xb1b2;
1600 let d3_in: u16 = 0xc1c2;
1601 let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
1602
1603 let u = Uuid::from_fields(d1_in, d2_in, d3_in, d4_in);
1604 let (d1_out, d2_out, d3_out, d4_out) = u.to_fields_le();
1605
1606 assert_eq!(d1_in, d1_out.swap_bytes());
1607 assert_eq!(d2_in, d2_out.swap_bytes());
1608 assert_eq!(d3_in, d3_out.swap_bytes());
1609 assert_eq!(d4_in, d4_out);
1610 }
1611
1612 #[test]
1613 #[cfg_attr(
1614 all(
1615 target_arch = "wasm32",
1616 target_vendor = "unknown",
1617 target_os = "unknown"
1618 ),
1619 wasm_bindgen_test
1620 )]
1621 fn test_from_u128() {
1622 let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
1623
1624 let u = Uuid::from_u128(v_in);
1625
1626 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1627 let result = u.simple().to_string();
1628 assert_eq!(result, expected);
1629 }
1630
1631 #[test]
1632 #[cfg_attr(
1633 all(
1634 target_arch = "wasm32",
1635 target_vendor = "unknown",
1636 target_os = "unknown"
1637 ),
1638 wasm_bindgen_test
1639 )]
1640 fn test_from_u128_le() {
1641 let v_in: u128 = 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1;
1642
1643 let u = Uuid::from_u128_le(v_in);
1644
1645 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1646 let result = u.simple().to_string();
1647 assert_eq!(result, expected);
1648 }
1649
1650 #[test]
1651 #[cfg_attr(
1652 all(
1653 target_arch = "wasm32",
1654 target_vendor = "unknown",
1655 target_os = "unknown"
1656 ),
1657 wasm_bindgen_test
1658 )]
1659 fn test_from_u64_pair() {
1660 let high_in: u64 = 0xa1a2a3a4b1b2c1c2;
1661 let low_in: u64 = 0xd1d2d3d4d5d6d7d8;
1662
1663 let u = Uuid::from_u64_pair(high_in, low_in);
1664
1665 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1666 let result = u.simple().to_string();
1667 assert_eq!(result, expected);
1668 }
1669
1670 #[test]
1671 #[cfg_attr(
1672 all(
1673 target_arch = "wasm32",
1674 target_vendor = "unknown",
1675 target_os = "unknown"
1676 ),
1677 wasm_bindgen_test
1678 )]
1679 fn test_u128_roundtrip() {
1680 let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
1681
1682 let u = Uuid::from_u128(v_in);
1683 let v_out = u.as_u128();
1684
1685 assert_eq!(v_in, v_out);
1686 }
1687
1688 #[test]
1689 #[cfg_attr(
1690 all(
1691 target_arch = "wasm32",
1692 target_vendor = "unknown",
1693 target_os = "unknown"
1694 ),
1695 wasm_bindgen_test
1696 )]
1697 fn test_u128_le_roundtrip() {
1698 let v_in: u128 = 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1;
1699
1700 let u = Uuid::from_u128_le(v_in);
1701 let v_out = u.to_u128_le();
1702
1703 assert_eq!(v_in, v_out);
1704 }
1705
1706 #[test]
1707 #[cfg_attr(
1708 all(
1709 target_arch = "wasm32",
1710 target_vendor = "unknown",
1711 target_os = "unknown"
1712 ),
1713 wasm_bindgen_test
1714 )]
1715 fn test_u64_pair_roundtrip() {
1716 let high_in: u64 = 0xa1a2a3a4b1b2c1c2;
1717 let low_in: u64 = 0xd1d2d3d4d5d6d7d8;
1718
1719 let u = Uuid::from_u64_pair(high_in, low_in);
1720 let (high_out, low_out) = u.as_u64_pair();
1721
1722 assert_eq!(high_in, high_out);
1723 assert_eq!(low_in, low_out);
1724 }
1725
1726 #[test]
1727 #[cfg_attr(
1728 all(
1729 target_arch = "wasm32",
1730 target_vendor = "unknown",
1731 target_os = "unknown"
1732 ),
1733 wasm_bindgen_test
1734 )]
1735 fn test_u128_le_is_actually_le() {
1736 let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8;
1737
1738 let u = Uuid::from_u128(v_in);
1739 let v_out = u.to_u128_le();
1740
1741 assert_eq!(v_in, v_out.swap_bytes());
1742 }
1743
1744 #[test]
1745 #[cfg_attr(
1746 all(
1747 target_arch = "wasm32",
1748 target_vendor = "unknown",
1749 target_os = "unknown"
1750 ),
1751 wasm_bindgen_test
1752 )]
1753 fn test_from_slice() {
1754 let b = [
1755 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
1756 0xd7, 0xd8,
1757 ];
1758
1759 let u = Uuid::from_slice(&b).unwrap();
1760 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1761
1762 assert_eq!(u.simple().to_string(), expected);
1763 }
1764
1765 #[test]
1766 #[cfg_attr(
1767 all(
1768 target_arch = "wasm32",
1769 target_vendor = "unknown",
1770 target_os = "unknown"
1771 ),
1772 wasm_bindgen_test
1773 )]
1774 fn test_from_bytes() {
1775 let b = [
1776 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
1777 0xd7, 0xd8,
1778 ];
1779
1780 let u = Uuid::from_bytes(b);
1781 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
1782
1783 assert_eq!(u.simple().to_string(), expected);
1784 }
1785
1786 #[test]
1787 #[cfg_attr(
1788 all(
1789 target_arch = "wasm32",
1790 target_vendor = "unknown",
1791 target_os = "unknown"
1792 ),
1793 wasm_bindgen_test
1794 )]
1795 fn test_as_bytes() {
1796 let u = new();
1797 let ub = u.as_bytes();
1798 let ur: &[u8] = u.as_ref();
1799
1800 assert_eq!(ub.len(), 16);
1801 assert_eq!(ur.len(), 16);
1802 assert!(!ub.iter().all(|&b| b == 0));
1803 assert!(!ur.iter().all(|&b| b == 0));
1804 }
1805
1806 #[test]
1807 #[cfg(feature = "std")]
1808 #[cfg_attr(
1809 all(
1810 target_arch = "wasm32",
1811 target_vendor = "unknown",
1812 target_os = "unknown"
1813 ),
1814 wasm_bindgen_test
1815 )]
1816 fn test_convert_vec() {
1817 use crate::std::{convert::TryInto, vec::Vec};
1818
1819 let u = new();
1820 let ub: &[u8] = u.as_ref();
1821
1822 let v: Vec<u8> = u.into();
1823
1824 assert_eq!(&v, ub);
1825
1826 let uv: Uuid = v.try_into().unwrap();
1827
1828 assert_eq!(uv, u);
1829 }
1830
1831 #[test]
1832 #[cfg_attr(
1833 all(
1834 target_arch = "wasm32",
1835 target_vendor = "unknown",
1836 target_os = "unknown"
1837 ),
1838 wasm_bindgen_test
1839 )]
1840 fn test_bytes_roundtrip() {
1841 let b_in: crate::Bytes = [
1842 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
1843 0xd7, 0xd8,
1844 ];
1845
1846 let u = Uuid::from_slice(&b_in).unwrap();
1847
1848 let b_out = u.as_bytes();
1849
1850 assert_eq!(&b_in, b_out);
1851 }
1852
1853 #[test]
1854 #[cfg_attr(
1855 all(
1856 target_arch = "wasm32",
1857 target_vendor = "unknown",
1858 target_os = "unknown"
1859 ),
1860 wasm_bindgen_test
1861 )]
1862 fn test_bytes_le_roundtrip() {
1863 let b = [
1864 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6,
1865 0xd7, 0xd8,
1866 ];
1867
1868 let u1 = Uuid::from_bytes(b);
1869
1870 let b_le = u1.to_bytes_le();
1871
1872 let u2 = Uuid::from_bytes_le(b_le);
1873
1874 assert_eq!(u1, u2);
1875 }
1876
1877 #[test]
1878 #[cfg_attr(
1879 all(
1880 target_arch = "wasm32",
1881 target_vendor = "unknown",
1882 target_os = "unknown"
1883 ),
1884 wasm_bindgen_test
1885 )]
1886 fn test_iterbytes_impl_for_uuid() {
1887 let mut set = std::collections::HashSet::new();
1888 let id1 = new();
1889 let id2 = new2();
1890 set.insert(id1.clone());
1891
1892 assert!(set.contains(&id1));
1893 assert!(!set.contains(&id2));
1894 }
1895}