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.7.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 //! * `v6` - Version 6 UUIDs using a timestamp and monotonic counter. 84 //! * `v7` - Version 7 UUIDs using a Unix timestamp. 85 //! * `v8` - Version 8 UUIDs using user-defined data. 86 //! 87 //! Versions that are in draft are also supported. See the _unstable features_ section for details. 88 //! 89 //! This library also includes a [`Builder`] type that can be used to help construct UUIDs of any 90 //! version without any additional dependencies or features. It's a lower-level API than [`Uuid`] 91 //! that can be used when you need control over implicit requirements on things like a source 92 //! of randomness. 93 //! 94 //! ## Which UUID version should I use? 95 //! 96 //! If you just want to generate unique identifiers then consider version 4 (`v4`) UUIDs. If you want 97 //! to use UUIDs as database keys or need to sort them then consider version 7 (`v7`) UUIDs. 98 //! Other versions should generally be avoided unless there's an existing need for them. 99 //! 100 //! Some UUID versions supersede others. Prefer version 6 over version 1 and version 5 over version 3. 101 //! 102 //! # Other features 103 //! 104 //! Other crate features can also be useful beyond the version support: 105 //! 106 //! * `macro-diagnostics` - enhances the diagnostics of `uuid!` macro. 107 //! * `serde` - adds the ability to serialize and deserialize a UUID using 108 //! `serde`. 109 //! * `borsh` - adds the ability to serialize and deserialize a UUID using 110 //! `borsh`. 111 //! * `arbitrary` - adds an `Arbitrary` trait implementation to `Uuid` for 112 //! fuzzing. 113 //! * `fast-rng` - uses a faster algorithm for generating random UUIDs. 114 //! This feature requires more dependencies to compile, but is just as suitable for 115 //! UUIDs as the default algorithm. 116 //! * `bytemuck` - adds a `Pod` trait implementation to `Uuid` for byte manipulation 117 //! 118 //! # Unstable features 119 //! 120 //! Some features are unstable. They may be incomplete or depend on other 121 //! unstable libraries. These include: 122 //! 123 //! * `zerocopy` - adds support for zero-copy deserialization using the 124 //! `zerocopy` library. 125 //! 126 //! Unstable features may break between minor releases. 127 //! 128 //! To allow unstable features, you'll need to enable the Cargo feature as 129 //! normal, but also pass an additional flag through your environment to opt-in 130 //! to unstable `uuid` features: 131 //! 132 //! ```text 133 //! RUSTFLAGS="--cfg uuid_unstable" 134 //! ``` 135 //! 136 //! # Building for other targets 137 //! 138 //! ## WebAssembly 139 //! 140 //! For WebAssembly, enable the `js` feature: 141 //! 142 //! ```toml 143 //! [dependencies.uuid] 144 //! version = "1.7.0" 145 //! features = [ 146 //! "v4", 147 //! "v7", 148 //! "js", 149 //! ] 150 //! ``` 151 //! 152 //! ## Embedded 153 //! 154 //! For embedded targets without the standard library, you'll need to 155 //! disable default features when building `uuid`: 156 //! 157 //! ```toml 158 //! [dependencies.uuid] 159 //! version = "1.7.0" 160 //! default-features = false 161 //! ``` 162 //! 163 //! Some additional features are supported in no-std environments: 164 //! 165 //! * `v1`, `v3`, `v5`, `v6`, and `v8`. 166 //! * `serde`. 167 //! 168 //! If you need to use `v4` or `v7` in a no-std environment, you'll need to 169 //! follow [`getrandom`'s docs] on configuring a source of randomness 170 //! on currently unsupported targets. Alternatively, you can produce 171 //! random bytes yourself and then pass them to [`Builder::from_random_bytes`] 172 //! without enabling the `v4` or `v7` features. 173 //! 174 //! # Examples 175 //! 176 //! Parse a UUID given in the simple format and print it as a URN: 177 //! 178 //! ``` 179 //! # use uuid::Uuid; 180 //! # fn main() -> Result<(), uuid::Error> { 181 //! let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?; 182 //! 183 //! println!("{}", my_uuid.urn()); 184 //! # Ok(()) 185 //! # } 186 //! ``` 187 //! 188 //! Generate a random UUID and print it out in hexadecimal form: 189 //! 190 //! ``` 191 //! // Note that this requires the `v4` feature to be enabled. 192 //! # use uuid::Uuid; 193 //! # fn main() { 194 //! # #[cfg(feature = "v4")] { 195 //! let my_uuid = Uuid::new_v4(); 196 //! 197 //! println!("{}", my_uuid); 198 //! # } 199 //! # } 200 //! ``` 201 //! 202 //! # References 203 //! 204 //! * [Wikipedia: Universally Unique Identifier](http://en.wikipedia.org/wiki/Universally_unique_identifier) 205 //! * [RFC4122: A Universally Unique Identifier (UUID) URN Namespace](http://tools.ietf.org/html/rfc4122) 206 //! * [Draft RFC: New UUID Formats, Version 4](https://datatracker.ietf.org/doc/html/draft-peabody-dispatch-new-uuid-format-04) 207 //! 208 //! [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen 209 //! [`cargo-web`]: https://crates.io/crates/cargo-web 210 //! [`getrandom`'s docs]: https://docs.rs/getrandom 211 212 #![no_std] 213 #![deny(missing_debug_implementations, missing_docs)] 214 #![doc( 215 html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", 216 html_favicon_url = "https://www.rust-lang.org/favicon.ico", 217 html_root_url = "https://docs.rs/uuid/1.7.0" 218 )] 219 220 #[cfg(any(feature = "std", test))] 221 #[macro_use] 222 extern crate std; 223 224 #[cfg(all(not(feature = "std"), not(test)))] 225 #[macro_use] 226 extern crate core as std; 227 228 #[cfg(all(uuid_unstable, feature = "zerocopy"))] 229 use zerocopy::{AsBytes, FromBytes, Unaligned}; 230 231 mod builder; 232 mod error; 233 mod parser; 234 235 pub mod fmt; 236 pub mod timestamp; 237 238 pub use timestamp::{context::NoContext, ClockSequence, Timestamp}; 239 240 #[cfg(any(feature = "v1", feature = "v6"))] 241 pub use timestamp::context::Context; 242 243 #[cfg(feature = "v1")] 244 #[doc(hidden)] 245 // Soft-deprecated (Rust doesn't support deprecating re-exports) 246 // Use `Context` from the crate root instead 247 pub mod v1; 248 #[cfg(feature = "v3")] 249 mod v3; 250 #[cfg(feature = "v4")] 251 mod v4; 252 #[cfg(feature = "v5")] 253 mod v5; 254 #[cfg(feature = "v6")] 255 mod v6; 256 #[cfg(feature = "v7")] 257 mod v7; 258 #[cfg(feature = "v8")] 259 mod v8; 260 261 #[cfg(feature = "md5")] 262 mod md5; 263 #[cfg(feature = "rng")] 264 mod rng; 265 #[cfg(feature = "sha1")] 266 mod sha1; 267 268 mod external; 269 270 #[macro_use] 271 mod macros; 272 273 #[doc(hidden)] 274 #[cfg(feature = "macro-diagnostics")] 275 pub extern crate uuid_macro_internal; 276 277 #[doc(hidden)] 278 pub mod __macro_support { 279 pub use crate::std::result::Result::{Err, Ok}; 280 } 281 282 use crate::std::convert; 283 284 pub use crate::{builder::Builder, error::Error}; 285 286 /// A 128-bit (16 byte) buffer containing the UUID. 287 /// 288 /// # ABI 289 /// 290 /// The `Bytes` type is always guaranteed to be have the same ABI as [`Uuid`]. 291 pub type Bytes = [u8; 16]; 292 293 /// The version of the UUID, denoting the generating algorithm. 294 /// 295 /// # References 296 /// 297 /// * [Version in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.3) 298 #[derive(Clone, Copy, Debug, PartialEq)] 299 #[non_exhaustive] 300 #[repr(u8)] 301 pub enum Version { 302 /// The "nil" (all zeros) UUID. 303 Nil = 0u8, 304 /// Version 1: Timestamp and node ID. 305 Mac = 1, 306 /// Version 2: DCE Security. 307 Dce = 2, 308 /// Version 3: MD5 hash. 309 Md5 = 3, 310 /// Version 4: Random. 311 Random = 4, 312 /// Version 5: SHA-1 hash. 313 Sha1 = 5, 314 /// Version 6: Sortable Timestamp and node ID. 315 SortMac = 6, 316 /// Version 7: Timestamp and random. 317 SortRand = 7, 318 /// Version 8: Custom. 319 Custom = 8, 320 /// The "max" (all ones) UUID. 321 Max = 0xff, 322 } 323 324 /// The reserved variants of UUIDs. 325 /// 326 /// # References 327 /// 328 /// * [Variant in RFC4122](http://tools.ietf.org/html/rfc4122#section-4.1.1) 329 #[derive(Clone, Copy, Debug, PartialEq)] 330 #[non_exhaustive] 331 #[repr(u8)] 332 pub enum Variant { 333 /// Reserved by the NCS for backward compatibility. 334 NCS = 0u8, 335 /// As described in the RFC4122 Specification (default). 336 RFC4122, 337 /// Reserved by Microsoft for backward compatibility. 338 Microsoft, 339 /// Reserved for future expansion. 340 Future, 341 } 342 343 /// A Universally Unique Identifier (UUID). 344 /// 345 /// # Examples 346 /// 347 /// Parse a UUID given in the simple format and print it as a urn: 348 /// 349 /// ``` 350 /// # use uuid::Uuid; 351 /// # fn main() -> Result<(), uuid::Error> { 352 /// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?; 353 /// 354 /// println!("{}", my_uuid.urn()); 355 /// # Ok(()) 356 /// # } 357 /// ``` 358 /// 359 /// Create a new random (V4) UUID and print it out in hexadecimal form: 360 /// 361 /// ``` 362 /// // Note that this requires the `v4` feature enabled in the uuid crate. 363 /// # use uuid::Uuid; 364 /// # fn main() { 365 /// # #[cfg(feature = "v4")] { 366 /// let my_uuid = Uuid::new_v4(); 367 /// 368 /// println!("{}", my_uuid); 369 /// # } 370 /// # } 371 /// ``` 372 /// 373 /// # Formatting 374 /// 375 /// A UUID can be formatted in one of a few ways: 376 /// 377 /// * [`simple`](#method.simple): `a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8`. 378 /// * [`hyphenated`](#method.hyphenated): 379 /// `a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8`. 380 /// * [`urn`](#method.urn): `urn:uuid:A1A2A3A4-B1B2-C1C2-D1D2-D3D4D5D6D7D8`. 381 /// * [`braced`](#method.braced): `{a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8}`. 382 /// 383 /// The default representation when formatting a UUID with `Display` is 384 /// hyphenated: 385 /// 386 /// ``` 387 /// # use uuid::Uuid; 388 /// # fn main() -> Result<(), uuid::Error> { 389 /// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?; 390 /// 391 /// assert_eq!( 392 /// "a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8", 393 /// my_uuid.to_string(), 394 /// ); 395 /// # Ok(()) 396 /// # } 397 /// ``` 398 /// 399 /// Other formats can be specified using adapter methods on the UUID: 400 /// 401 /// ``` 402 /// # use uuid::Uuid; 403 /// # fn main() -> Result<(), uuid::Error> { 404 /// let my_uuid = Uuid::parse_str("a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8")?; 405 /// 406 /// assert_eq!( 407 /// "urn:uuid:a1a2a3a4-b1b2-c1c2-d1d2-d3d4d5d6d7d8", 408 /// my_uuid.urn().to_string(), 409 /// ); 410 /// # Ok(()) 411 /// # } 412 /// ``` 413 /// 414 /// # Endianness 415 /// 416 /// The specification for UUIDs encodes the integer fields that make up the 417 /// value in big-endian order. This crate assumes integer inputs are already in 418 /// the correct order by default, regardless of the endianness of the 419 /// environment. Most methods that accept integers have a `_le` variant (such as 420 /// `from_fields_le`) that assumes any integer values will need to have their 421 /// bytes flipped, regardless of the endianness of the environment. 422 /// 423 /// Most users won't need to worry about endianness unless they need to operate 424 /// on individual fields (such as when converting between Microsoft GUIDs). The 425 /// important things to remember are: 426 /// 427 /// - The endianness is in terms of the fields of the UUID, not the environment. 428 /// - The endianness is assumed to be big-endian when there's no `_le` suffix 429 /// somewhere. 430 /// - Byte-flipping in `_le` methods applies to each integer. 431 /// - Endianness roundtrips, so if you create a UUID with `from_fields_le` 432 /// you'll get the same values back out with `to_fields_le`. 433 /// 434 /// # ABI 435 /// 436 /// The `Uuid` type is always guaranteed to be have the same ABI as [`Bytes`]. 437 #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 438 #[cfg_attr( 439 all(uuid_unstable, feature = "zerocopy"), 440 derive(AsBytes, FromBytes, Unaligned) 441 )] 442 #[cfg_attr( 443 feature = "borsh", 444 derive(borsh_derive::BorshDeserialize, borsh_derive::BorshSerialize) 445 )] 446 #[repr(transparent)] 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 in RFC4122](http://tools.ietf.org/html/rfc4122#section-4.1.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 in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.3) 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 in RFC4122](https://datatracker.ietf.org/doc/html/rfc4122#section-4.1.3) 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 and counter portion parsed from a V1 UUID. 881 /// 882 /// Returns `None` if the supplied UUID is not V1. 883 /// 884 /// The V1 timestamp format defined in RFC4122 specifies a 60-bit 885 /// integer representing the number of 100-nanosecond intervals 886 /// since 00:00:00.00, 15 Oct 1582. 887 /// 888 /// [`Timestamp`] offers several options for converting the raw RFC4122 889 /// value into more commonly-used formats, such as a unix timestamp. 890 /// 891 /// # Roundtripping 892 /// 893 /// This method is unlikely to roundtrip a timestamp in a UUID due to the way 894 /// UUIDs encode timestamps. The timestamp returned from this method will be truncated to 895 /// 100ns precision for version 1 and 6 UUIDs, and to millisecond precision for version 7 UUIDs. 896 /// 897 /// [`Timestamp`]: v1/struct.Timestamp.html get_timestamp(&self) -> Option<Timestamp>898 pub const fn get_timestamp(&self) -> Option<Timestamp> { 899 match self.get_version() { 900 Some(Version::Mac) => { 901 let (ticks, counter) = timestamp::decode_rfc4122_timestamp(self); 902 903 Some(Timestamp::from_rfc4122(ticks, counter)) 904 } 905 Some(Version::SortMac) => { 906 let (ticks, counter) = timestamp::decode_sorted_rfc4122_timestamp(self); 907 908 Some(Timestamp::from_rfc4122(ticks, counter)) 909 } 910 Some(Version::SortRand) => { 911 let millis = timestamp::decode_unix_timestamp_millis(self); 912 913 let seconds = millis / 1000; 914 let nanos = ((millis % 1000) * 1_000_000) as u32; 915 916 Some(Timestamp { 917 seconds, 918 nanos, 919 #[cfg(any(feature = "v1", feature = "v6"))] 920 counter: 0, 921 }) 922 } 923 _ => None, 924 } 925 } 926 } 927 928 impl Default for Uuid { 929 #[inline] default() -> Self930 fn default() -> Self { 931 Uuid::nil() 932 } 933 } 934 935 impl AsRef<[u8]> for Uuid { 936 #[inline] as_ref(&self) -> &[u8]937 fn as_ref(&self) -> &[u8] { 938 &self.0 939 } 940 } 941 942 #[cfg(feature = "std")] 943 impl From<Uuid> for std::vec::Vec<u8> { from(value: Uuid) -> Self944 fn from(value: Uuid) -> Self { 945 value.0.to_vec() 946 } 947 } 948 949 #[cfg(feature = "std")] 950 impl std::convert::TryFrom<std::vec::Vec<u8>> for Uuid { 951 type Error = Error; 952 try_from(value: std::vec::Vec<u8>) -> Result<Self, Self::Error>953 fn try_from(value: std::vec::Vec<u8>) -> Result<Self, Self::Error> { 954 Uuid::from_slice(&value) 955 } 956 } 957 958 #[cfg(feature = "serde")] 959 pub mod serde { 960 //! Adapters for alternative `serde` formats. 961 //! 962 //! This module contains adapters you can use with [`#[serde(with)]`](https://serde.rs/field-attrs.html#with) 963 //! to change the way a [`Uuid`](../struct.Uuid.html) is serialized 964 //! and deserialized. 965 966 pub use crate::external::serde_support::compact; 967 } 968 969 #[cfg(test)] 970 mod tests { 971 use super::*; 972 973 use crate::std::string::{String, ToString}; 974 975 #[cfg(all( 976 target_arch = "wasm32", 977 target_vendor = "unknown", 978 target_os = "unknown" 979 ))] 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( 1007 all( 1008 target_arch = "wasm32", 1009 target_vendor = "unknown", 1010 target_os = "unknown" 1011 ), 1012 wasm_bindgen_test 1013 )] test_uuid_compare()1014 fn test_uuid_compare() { 1015 let uuid1 = new(); 1016 let uuid2 = new2(); 1017 1018 assert_eq!(uuid1, uuid1); 1019 assert_eq!(uuid2, uuid2); 1020 1021 assert_ne!(uuid1, uuid2); 1022 assert_ne!(uuid2, uuid1); 1023 } 1024 1025 #[test] 1026 #[cfg_attr( 1027 all( 1028 target_arch = "wasm32", 1029 target_vendor = "unknown", 1030 target_os = "unknown" 1031 ), 1032 wasm_bindgen_test 1033 )] test_uuid_default()1034 fn test_uuid_default() { 1035 let default_uuid = Uuid::default(); 1036 let nil_uuid = Uuid::nil(); 1037 1038 assert_eq!(default_uuid, nil_uuid); 1039 } 1040 1041 #[test] 1042 #[cfg_attr( 1043 all( 1044 target_arch = "wasm32", 1045 target_vendor = "unknown", 1046 target_os = "unknown" 1047 ), 1048 wasm_bindgen_test 1049 )] test_uuid_display()1050 fn test_uuid_display() { 1051 use crate::std::fmt::Write; 1052 1053 let uuid = new(); 1054 let s = uuid.to_string(); 1055 let mut buffer = String::new(); 1056 1057 assert_eq!(s, uuid.hyphenated().to_string()); 1058 1059 check!(buffer, "{}", uuid, 36, |c| c.is_lowercase() 1060 || c.is_digit(10) 1061 || c == '-'); 1062 } 1063 1064 #[test] 1065 #[cfg_attr( 1066 all( 1067 target_arch = "wasm32", 1068 target_vendor = "unknown", 1069 target_os = "unknown" 1070 ), 1071 wasm_bindgen_test 1072 )] test_uuid_lowerhex()1073 fn test_uuid_lowerhex() { 1074 use crate::std::fmt::Write; 1075 1076 let mut buffer = String::new(); 1077 let uuid = new(); 1078 1079 check!(buffer, "{:x}", uuid, 36, |c| c.is_lowercase() 1080 || c.is_digit(10) 1081 || c == '-'); 1082 } 1083 1084 // noinspection RsAssertEqual 1085 #[test] 1086 #[cfg_attr( 1087 all( 1088 target_arch = "wasm32", 1089 target_vendor = "unknown", 1090 target_os = "unknown" 1091 ), 1092 wasm_bindgen_test 1093 )] test_uuid_operator_eq()1094 fn test_uuid_operator_eq() { 1095 let uuid1 = new(); 1096 let uuid1_dup = uuid1.clone(); 1097 let uuid2 = new2(); 1098 1099 assert!(uuid1 == uuid1); 1100 assert!(uuid1 == uuid1_dup); 1101 assert!(uuid1_dup == uuid1); 1102 1103 assert!(uuid1 != uuid2); 1104 assert!(uuid2 != uuid1); 1105 assert!(uuid1_dup != uuid2); 1106 assert!(uuid2 != uuid1_dup); 1107 } 1108 1109 #[test] 1110 #[cfg_attr( 1111 all( 1112 target_arch = "wasm32", 1113 target_vendor = "unknown", 1114 target_os = "unknown" 1115 ), 1116 wasm_bindgen_test 1117 )] test_uuid_to_string()1118 fn test_uuid_to_string() { 1119 use crate::std::fmt::Write; 1120 1121 let uuid = new(); 1122 let s = uuid.to_string(); 1123 let mut buffer = String::new(); 1124 1125 assert_eq!(s.len(), 36); 1126 1127 check!(buffer, "{}", s, 36, |c| c.is_lowercase() 1128 || c.is_digit(10) 1129 || c == '-'); 1130 } 1131 1132 #[test] 1133 #[cfg_attr( 1134 all( 1135 target_arch = "wasm32", 1136 target_vendor = "unknown", 1137 target_os = "unknown" 1138 ), 1139 wasm_bindgen_test 1140 )] test_non_conforming()1141 fn test_non_conforming() { 1142 let from_bytes = 1143 Uuid::from_bytes([4, 54, 67, 12, 43, 2, 2, 76, 32, 50, 87, 5, 1, 33, 43, 87]); 1144 1145 assert_eq!(from_bytes.get_version(), None); 1146 } 1147 1148 #[test] 1149 #[cfg_attr( 1150 all( 1151 target_arch = "wasm32", 1152 target_vendor = "unknown", 1153 target_os = "unknown" 1154 ), 1155 wasm_bindgen_test 1156 )] test_nil()1157 fn test_nil() { 1158 let nil = Uuid::nil(); 1159 let not_nil = new(); 1160 1161 assert!(nil.is_nil()); 1162 assert!(!not_nil.is_nil()); 1163 1164 assert_eq!(nil.get_version(), Some(Version::Nil)); 1165 assert_eq!(not_nil.get_version(), Some(Version::Random)); 1166 1167 assert_eq!( 1168 nil, 1169 Builder::from_bytes([0; 16]) 1170 .with_version(Version::Nil) 1171 .into_uuid() 1172 ); 1173 } 1174 1175 #[test] 1176 #[cfg_attr( 1177 all( 1178 target_arch = "wasm32", 1179 target_vendor = "unknown", 1180 target_os = "unknown" 1181 ), 1182 wasm_bindgen_test 1183 )] test_max()1184 fn test_max() { 1185 let max = Uuid::max(); 1186 let not_max = new(); 1187 1188 assert!(max.is_max()); 1189 assert!(!not_max.is_max()); 1190 1191 assert_eq!(max.get_version(), Some(Version::Max)); 1192 assert_eq!(not_max.get_version(), Some(Version::Random)); 1193 1194 assert_eq!( 1195 max, 1196 Builder::from_bytes([0xff; 16]) 1197 .with_version(Version::Max) 1198 .into_uuid() 1199 ); 1200 } 1201 1202 #[test] 1203 #[cfg_attr( 1204 all( 1205 target_arch = "wasm32", 1206 target_vendor = "unknown", 1207 target_os = "unknown" 1208 ), 1209 wasm_bindgen_test 1210 )] test_predefined_namespaces()1211 fn test_predefined_namespaces() { 1212 assert_eq!( 1213 Uuid::NAMESPACE_DNS.hyphenated().to_string(), 1214 "6ba7b810-9dad-11d1-80b4-00c04fd430c8" 1215 ); 1216 assert_eq!( 1217 Uuid::NAMESPACE_URL.hyphenated().to_string(), 1218 "6ba7b811-9dad-11d1-80b4-00c04fd430c8" 1219 ); 1220 assert_eq!( 1221 Uuid::NAMESPACE_OID.hyphenated().to_string(), 1222 "6ba7b812-9dad-11d1-80b4-00c04fd430c8" 1223 ); 1224 assert_eq!( 1225 Uuid::NAMESPACE_X500.hyphenated().to_string(), 1226 "6ba7b814-9dad-11d1-80b4-00c04fd430c8" 1227 ); 1228 } 1229 1230 #[cfg(feature = "v3")] 1231 #[test] 1232 #[cfg_attr( 1233 all( 1234 target_arch = "wasm32", 1235 target_vendor = "unknown", 1236 target_os = "unknown" 1237 ), 1238 wasm_bindgen_test 1239 )] test_get_version_v3()1240 fn test_get_version_v3() { 1241 let uuid = Uuid::new_v3(&Uuid::NAMESPACE_DNS, "rust-lang.org".as_bytes()); 1242 1243 assert_eq!(uuid.get_version().unwrap(), Version::Md5); 1244 assert_eq!(uuid.get_version_num(), 3); 1245 } 1246 1247 #[test] 1248 #[cfg_attr( 1249 all( 1250 target_arch = "wasm32", 1251 target_vendor = "unknown", 1252 target_os = "unknown" 1253 ), 1254 wasm_bindgen_test 1255 )] test_get_variant()1256 fn test_get_variant() { 1257 let uuid1 = new(); 1258 let uuid2 = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(); 1259 let uuid3 = Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8").unwrap(); 1260 let uuid4 = Uuid::parse_str("936DA01F9ABD4d9dC0C702AF85C822A8").unwrap(); 1261 let uuid5 = Uuid::parse_str("F9168C5E-CEB2-4faa-D6BF-329BF39FA1E4").unwrap(); 1262 let uuid6 = Uuid::parse_str("f81d4fae-7dec-11d0-7765-00a0c91e6bf6").unwrap(); 1263 1264 assert_eq!(uuid1.get_variant(), Variant::RFC4122); 1265 assert_eq!(uuid2.get_variant(), Variant::RFC4122); 1266 assert_eq!(uuid3.get_variant(), Variant::RFC4122); 1267 assert_eq!(uuid4.get_variant(), Variant::Microsoft); 1268 assert_eq!(uuid5.get_variant(), Variant::Microsoft); 1269 assert_eq!(uuid6.get_variant(), Variant::NCS); 1270 } 1271 1272 #[test] 1273 #[cfg_attr( 1274 all( 1275 target_arch = "wasm32", 1276 target_vendor = "unknown", 1277 target_os = "unknown" 1278 ), 1279 wasm_bindgen_test 1280 )] test_to_simple_string()1281 fn test_to_simple_string() { 1282 let uuid1 = new(); 1283 let s = uuid1.simple().to_string(); 1284 1285 assert_eq!(s.len(), 32); 1286 assert!(s.chars().all(|c| c.is_digit(16))); 1287 } 1288 1289 #[test] 1290 #[cfg_attr( 1291 all( 1292 target_arch = "wasm32", 1293 target_vendor = "unknown", 1294 target_os = "unknown" 1295 ), 1296 wasm_bindgen_test 1297 )] test_hyphenated_string()1298 fn test_hyphenated_string() { 1299 let uuid1 = new(); 1300 let s = uuid1.hyphenated().to_string(); 1301 1302 assert_eq!(36, s.len()); 1303 assert!(s.chars().all(|c| c.is_digit(16) || c == '-')); 1304 } 1305 1306 #[test] 1307 #[cfg_attr( 1308 all( 1309 target_arch = "wasm32", 1310 target_vendor = "unknown", 1311 target_os = "unknown" 1312 ), 1313 wasm_bindgen_test 1314 )] test_upper_lower_hex()1315 fn test_upper_lower_hex() { 1316 use std::fmt::Write; 1317 1318 let mut buf = String::new(); 1319 let u = new(); 1320 1321 macro_rules! check { 1322 ($buf:ident, $format:expr, $target:expr, $len:expr, $cond:expr) => { 1323 $buf.clear(); 1324 write!($buf, $format, $target).unwrap(); 1325 assert_eq!($len, buf.len()); 1326 assert!($buf.chars().all($cond), "{}", $buf); 1327 }; 1328 } 1329 1330 check!(buf, "{:x}", u, 36, |c| c.is_lowercase() 1331 || c.is_digit(10) 1332 || c == '-'); 1333 check!(buf, "{:X}", u, 36, |c| c.is_uppercase() 1334 || c.is_digit(10) 1335 || c == '-'); 1336 check!(buf, "{:#x}", u, 36, |c| c.is_lowercase() 1337 || c.is_digit(10) 1338 || c == '-'); 1339 check!(buf, "{:#X}", u, 36, |c| c.is_uppercase() 1340 || c.is_digit(10) 1341 || c == '-'); 1342 1343 check!(buf, "{:X}", u.hyphenated(), 36, |c| c.is_uppercase() 1344 || c.is_digit(10) 1345 || c == '-'); 1346 check!(buf, "{:X}", u.simple(), 32, |c| c.is_uppercase() 1347 || c.is_digit(10)); 1348 check!(buf, "{:#X}", u.hyphenated(), 36, |c| c.is_uppercase() 1349 || c.is_digit(10) 1350 || c == '-'); 1351 check!(buf, "{:#X}", u.simple(), 32, |c| c.is_uppercase() 1352 || c.is_digit(10)); 1353 1354 check!(buf, "{:x}", u.hyphenated(), 36, |c| c.is_lowercase() 1355 || c.is_digit(10) 1356 || c == '-'); 1357 check!(buf, "{:x}", u.simple(), 32, |c| c.is_lowercase() 1358 || c.is_digit(10)); 1359 check!(buf, "{:#x}", u.hyphenated(), 36, |c| c.is_lowercase() 1360 || c.is_digit(10) 1361 || c == '-'); 1362 check!(buf, "{:#x}", u.simple(), 32, |c| c.is_lowercase() 1363 || c.is_digit(10)); 1364 } 1365 1366 #[test] 1367 #[cfg_attr( 1368 all( 1369 target_arch = "wasm32", 1370 target_vendor = "unknown", 1371 target_os = "unknown" 1372 ), 1373 wasm_bindgen_test 1374 )] test_to_urn_string()1375 fn test_to_urn_string() { 1376 let uuid1 = new(); 1377 let ss = uuid1.urn().to_string(); 1378 let s = &ss[9..]; 1379 1380 assert!(ss.starts_with("urn:uuid:")); 1381 assert_eq!(s.len(), 36); 1382 assert!(s.chars().all(|c| c.is_digit(16) || c == '-')); 1383 } 1384 1385 #[test] 1386 #[cfg_attr( 1387 all( 1388 target_arch = "wasm32", 1389 target_vendor = "unknown", 1390 target_os = "unknown" 1391 ), 1392 wasm_bindgen_test 1393 )] test_to_simple_string_matching()1394 fn test_to_simple_string_matching() { 1395 let uuid1 = new(); 1396 1397 let hs = uuid1.hyphenated().to_string(); 1398 let ss = uuid1.simple().to_string(); 1399 1400 let hsn = hs.chars().filter(|&c| c != '-').collect::<String>(); 1401 1402 assert_eq!(hsn, ss); 1403 } 1404 1405 #[test] 1406 #[cfg_attr( 1407 all( 1408 target_arch = "wasm32", 1409 target_vendor = "unknown", 1410 target_os = "unknown" 1411 ), 1412 wasm_bindgen_test 1413 )] test_string_roundtrip()1414 fn test_string_roundtrip() { 1415 let uuid = new(); 1416 1417 let hs = uuid.hyphenated().to_string(); 1418 let uuid_hs = Uuid::parse_str(&hs).unwrap(); 1419 assert_eq!(uuid_hs, uuid); 1420 1421 let ss = uuid.to_string(); 1422 let uuid_ss = Uuid::parse_str(&ss).unwrap(); 1423 assert_eq!(uuid_ss, uuid); 1424 } 1425 1426 #[test] 1427 #[cfg_attr( 1428 all( 1429 target_arch = "wasm32", 1430 target_vendor = "unknown", 1431 target_os = "unknown" 1432 ), 1433 wasm_bindgen_test 1434 )] test_from_fields()1435 fn test_from_fields() { 1436 let d1: u32 = 0xa1a2a3a4; 1437 let d2: u16 = 0xb1b2; 1438 let d3: u16 = 0xc1c2; 1439 let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8]; 1440 1441 let u = Uuid::from_fields(d1, d2, d3, &d4); 1442 1443 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"; 1444 let result = u.simple().to_string(); 1445 assert_eq!(result, expected); 1446 } 1447 1448 #[test] 1449 #[cfg_attr( 1450 all( 1451 target_arch = "wasm32", 1452 target_vendor = "unknown", 1453 target_os = "unknown" 1454 ), 1455 wasm_bindgen_test 1456 )] test_from_fields_le()1457 fn test_from_fields_le() { 1458 let d1: u32 = 0xa4a3a2a1; 1459 let d2: u16 = 0xb2b1; 1460 let d3: u16 = 0xc2c1; 1461 let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8]; 1462 1463 let u = Uuid::from_fields_le(d1, d2, d3, &d4); 1464 1465 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"; 1466 let result = u.simple().to_string(); 1467 assert_eq!(result, expected); 1468 } 1469 1470 #[test] 1471 #[cfg_attr( 1472 all( 1473 target_arch = "wasm32", 1474 target_vendor = "unknown", 1475 target_os = "unknown" 1476 ), 1477 wasm_bindgen_test 1478 )] test_as_fields()1479 fn test_as_fields() { 1480 let u = new(); 1481 let (d1, d2, d3, d4) = u.as_fields(); 1482 1483 assert_ne!(d1, 0); 1484 assert_ne!(d2, 0); 1485 assert_ne!(d3, 0); 1486 assert_eq!(d4.len(), 8); 1487 assert!(!d4.iter().all(|&b| b == 0)); 1488 } 1489 1490 #[test] 1491 #[cfg_attr( 1492 all( 1493 target_arch = "wasm32", 1494 target_vendor = "unknown", 1495 target_os = "unknown" 1496 ), 1497 wasm_bindgen_test 1498 )] test_fields_roundtrip()1499 fn test_fields_roundtrip() { 1500 let d1_in: u32 = 0xa1a2a3a4; 1501 let d2_in: u16 = 0xb1b2; 1502 let d3_in: u16 = 0xc1c2; 1503 let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8]; 1504 1505 let u = Uuid::from_fields(d1_in, d2_in, d3_in, d4_in); 1506 let (d1_out, d2_out, d3_out, d4_out) = u.as_fields(); 1507 1508 assert_eq!(d1_in, d1_out); 1509 assert_eq!(d2_in, d2_out); 1510 assert_eq!(d3_in, d3_out); 1511 assert_eq!(d4_in, d4_out); 1512 } 1513 1514 #[test] 1515 #[cfg_attr( 1516 all( 1517 target_arch = "wasm32", 1518 target_vendor = "unknown", 1519 target_os = "unknown" 1520 ), 1521 wasm_bindgen_test 1522 )] test_fields_le_roundtrip()1523 fn test_fields_le_roundtrip() { 1524 let d1_in: u32 = 0xa4a3a2a1; 1525 let d2_in: u16 = 0xb2b1; 1526 let d3_in: u16 = 0xc2c1; 1527 let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8]; 1528 1529 let u = Uuid::from_fields_le(d1_in, d2_in, d3_in, d4_in); 1530 let (d1_out, d2_out, d3_out, d4_out) = u.to_fields_le(); 1531 1532 assert_eq!(d1_in, d1_out); 1533 assert_eq!(d2_in, d2_out); 1534 assert_eq!(d3_in, d3_out); 1535 assert_eq!(d4_in, d4_out); 1536 } 1537 1538 #[test] 1539 #[cfg_attr( 1540 all( 1541 target_arch = "wasm32", 1542 target_vendor = "unknown", 1543 target_os = "unknown" 1544 ), 1545 wasm_bindgen_test 1546 )] test_fields_le_are_actually_le()1547 fn test_fields_le_are_actually_le() { 1548 let d1_in: u32 = 0xa1a2a3a4; 1549 let d2_in: u16 = 0xb1b2; 1550 let d3_in: u16 = 0xc1c2; 1551 let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8]; 1552 1553 let u = Uuid::from_fields(d1_in, d2_in, d3_in, d4_in); 1554 let (d1_out, d2_out, d3_out, d4_out) = u.to_fields_le(); 1555 1556 assert_eq!(d1_in, d1_out.swap_bytes()); 1557 assert_eq!(d2_in, d2_out.swap_bytes()); 1558 assert_eq!(d3_in, d3_out.swap_bytes()); 1559 assert_eq!(d4_in, d4_out); 1560 } 1561 1562 #[test] 1563 #[cfg_attr( 1564 all( 1565 target_arch = "wasm32", 1566 target_vendor = "unknown", 1567 target_os = "unknown" 1568 ), 1569 wasm_bindgen_test 1570 )] test_from_u128()1571 fn test_from_u128() { 1572 let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8; 1573 1574 let u = Uuid::from_u128(v_in); 1575 1576 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"; 1577 let result = u.simple().to_string(); 1578 assert_eq!(result, expected); 1579 } 1580 1581 #[test] 1582 #[cfg_attr( 1583 all( 1584 target_arch = "wasm32", 1585 target_vendor = "unknown", 1586 target_os = "unknown" 1587 ), 1588 wasm_bindgen_test 1589 )] test_from_u128_le()1590 fn test_from_u128_le() { 1591 let v_in: u128 = 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1; 1592 1593 let u = Uuid::from_u128_le(v_in); 1594 1595 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"; 1596 let result = u.simple().to_string(); 1597 assert_eq!(result, expected); 1598 } 1599 1600 #[test] 1601 #[cfg_attr( 1602 all( 1603 target_arch = "wasm32", 1604 target_vendor = "unknown", 1605 target_os = "unknown" 1606 ), 1607 wasm_bindgen_test 1608 )] test_from_u64_pair()1609 fn test_from_u64_pair() { 1610 let high_in: u64 = 0xa1a2a3a4b1b2c1c2; 1611 let low_in: u64 = 0xd1d2d3d4d5d6d7d8; 1612 1613 let u = Uuid::from_u64_pair(high_in, low_in); 1614 1615 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"; 1616 let result = u.simple().to_string(); 1617 assert_eq!(result, expected); 1618 } 1619 1620 #[test] 1621 #[cfg_attr( 1622 all( 1623 target_arch = "wasm32", 1624 target_vendor = "unknown", 1625 target_os = "unknown" 1626 ), 1627 wasm_bindgen_test 1628 )] test_u128_roundtrip()1629 fn test_u128_roundtrip() { 1630 let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8; 1631 1632 let u = Uuid::from_u128(v_in); 1633 let v_out = u.as_u128(); 1634 1635 assert_eq!(v_in, v_out); 1636 } 1637 1638 #[test] 1639 #[cfg_attr( 1640 all( 1641 target_arch = "wasm32", 1642 target_vendor = "unknown", 1643 target_os = "unknown" 1644 ), 1645 wasm_bindgen_test 1646 )] test_u128_le_roundtrip()1647 fn test_u128_le_roundtrip() { 1648 let v_in: u128 = 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1; 1649 1650 let u = Uuid::from_u128_le(v_in); 1651 let v_out = u.to_u128_le(); 1652 1653 assert_eq!(v_in, v_out); 1654 } 1655 1656 #[test] 1657 #[cfg_attr( 1658 all( 1659 target_arch = "wasm32", 1660 target_vendor = "unknown", 1661 target_os = "unknown" 1662 ), 1663 wasm_bindgen_test 1664 )] test_u64_pair_roundtrip()1665 fn test_u64_pair_roundtrip() { 1666 let high_in: u64 = 0xa1a2a3a4b1b2c1c2; 1667 let low_in: u64 = 0xd1d2d3d4d5d6d7d8; 1668 1669 let u = Uuid::from_u64_pair(high_in, low_in); 1670 let (high_out, low_out) = u.as_u64_pair(); 1671 1672 assert_eq!(high_in, high_out); 1673 assert_eq!(low_in, low_out); 1674 } 1675 1676 #[test] 1677 #[cfg_attr( 1678 all( 1679 target_arch = "wasm32", 1680 target_vendor = "unknown", 1681 target_os = "unknown" 1682 ), 1683 wasm_bindgen_test 1684 )] test_u128_le_is_actually_le()1685 fn test_u128_le_is_actually_le() { 1686 let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8; 1687 1688 let u = Uuid::from_u128(v_in); 1689 let v_out = u.to_u128_le(); 1690 1691 assert_eq!(v_in, v_out.swap_bytes()); 1692 } 1693 1694 #[test] 1695 #[cfg_attr( 1696 all( 1697 target_arch = "wasm32", 1698 target_vendor = "unknown", 1699 target_os = "unknown" 1700 ), 1701 wasm_bindgen_test 1702 )] test_from_slice()1703 fn test_from_slice() { 1704 let b = [ 1705 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 1706 0xd7, 0xd8, 1707 ]; 1708 1709 let u = Uuid::from_slice(&b).unwrap(); 1710 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"; 1711 1712 assert_eq!(u.simple().to_string(), expected); 1713 } 1714 1715 #[test] 1716 #[cfg_attr( 1717 all( 1718 target_arch = "wasm32", 1719 target_vendor = "unknown", 1720 target_os = "unknown" 1721 ), 1722 wasm_bindgen_test 1723 )] test_from_bytes()1724 fn test_from_bytes() { 1725 let b = [ 1726 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 1727 0xd7, 0xd8, 1728 ]; 1729 1730 let u = Uuid::from_bytes(b); 1731 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"; 1732 1733 assert_eq!(u.simple().to_string(), expected); 1734 } 1735 1736 #[test] 1737 #[cfg_attr( 1738 all( 1739 target_arch = "wasm32", 1740 target_vendor = "unknown", 1741 target_os = "unknown" 1742 ), 1743 wasm_bindgen_test 1744 )] test_as_bytes()1745 fn test_as_bytes() { 1746 let u = new(); 1747 let ub = u.as_bytes(); 1748 let ur = u.as_ref(); 1749 1750 assert_eq!(ub.len(), 16); 1751 assert_eq!(ur.len(), 16); 1752 assert!(!ub.iter().all(|&b| b == 0)); 1753 assert!(!ur.iter().all(|&b| b == 0)); 1754 } 1755 1756 #[test] 1757 #[cfg(feature = "std")] 1758 #[cfg_attr( 1759 all( 1760 target_arch = "wasm32", 1761 target_vendor = "unknown", 1762 target_os = "unknown" 1763 ), 1764 wasm_bindgen_test 1765 )] test_convert_vec()1766 fn test_convert_vec() { 1767 use crate::std::{convert::TryInto, vec::Vec}; 1768 1769 let u = new(); 1770 let ub = u.as_ref(); 1771 1772 let v: Vec<u8> = u.into(); 1773 1774 assert_eq!(&v, ub); 1775 1776 let uv: Uuid = v.try_into().unwrap(); 1777 1778 assert_eq!(uv, u); 1779 } 1780 1781 #[test] 1782 #[cfg_attr( 1783 all( 1784 target_arch = "wasm32", 1785 target_vendor = "unknown", 1786 target_os = "unknown" 1787 ), 1788 wasm_bindgen_test 1789 )] test_bytes_roundtrip()1790 fn test_bytes_roundtrip() { 1791 let b_in: crate::Bytes = [ 1792 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 1793 0xd7, 0xd8, 1794 ]; 1795 1796 let u = Uuid::from_slice(&b_in).unwrap(); 1797 1798 let b_out = u.as_bytes(); 1799 1800 assert_eq!(&b_in, b_out); 1801 } 1802 1803 #[test] 1804 #[cfg_attr( 1805 all( 1806 target_arch = "wasm32", 1807 target_vendor = "unknown", 1808 target_os = "unknown" 1809 ), 1810 wasm_bindgen_test 1811 )] test_bytes_le_roundtrip()1812 fn test_bytes_le_roundtrip() { 1813 let b = [ 1814 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 1815 0xd7, 0xd8, 1816 ]; 1817 1818 let u1 = Uuid::from_bytes(b); 1819 1820 let b_le = u1.to_bytes_le(); 1821 1822 let u2 = Uuid::from_bytes_le(b_le); 1823 1824 assert_eq!(u1, u2); 1825 } 1826 1827 #[test] 1828 #[cfg_attr( 1829 all( 1830 target_arch = "wasm32", 1831 target_vendor = "unknown", 1832 target_os = "unknown" 1833 ), 1834 wasm_bindgen_test 1835 )] test_iterbytes_impl_for_uuid()1836 fn test_iterbytes_impl_for_uuid() { 1837 let mut set = std::collections::HashSet::new(); 1838 let id1 = new(); 1839 let id2 = new2(); 1840 set.insert(id1.clone()); 1841 1842 assert!(set.contains(&id1)); 1843 assert!(!set.contains(&id2)); 1844 } 1845 } 1846