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