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