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 UUIDs. 13 //! 14 //! Provides support for Universally Unique Identifiers (UUIDs). A UUID is a 15 //! unique 128-bit number, stored as 16 octets. UUIDs are used to assign 16 //! unique identifiers to entities without requiring a central allocating 17 //! authority. 18 //! 19 //! They are particularly useful in distributed systems, though can be used in 20 //! disparate areas, such as databases and network protocols. Typically a UUID 21 //! is displayed in a readable string form as a sequence of hexadecimal digits, 22 //! separated into groups by hyphens. 23 //! 24 //! The uniqueness property is not strictly guaranteed, however for all 25 //! practical purposes, it can be assumed that an unintentional collision would 26 //! be extremely unlikely. 27 //! 28 //! # Dependencies 29 //! 30 //! By default, this crate depends on nothing but `std` and cannot generate 31 //! UUIDs. You need to enable the following Cargo features to enable 32 //! various pieces of functionality: 33 //! 34 //! * `v1` - adds the [`Uuid::new_v1`] function and the ability to create a V1 35 //! using an implementation of [`v1::ClockSequence`] (usually 36 //! [`v1::Context`]) and a timestamp from `time::timespec`. 37 //! * `v3` - adds the [`Uuid::new_v3`] function and the ability to create a V3 38 //! UUID based on the MD5 hash of some data. 39 //! * `v4` - adds the [`Uuid::new_v4`] function and the ability to randomly 40 //! generate a UUID. 41 //! * `v5` - adds the [`Uuid::new_v5`] function and the ability to create a V5 42 //! UUID based on the SHA1 hash of some data. 43 //! * `serde` - adds the ability to serialize and deserialize a UUID using the 44 //! `serde` crate. 45 //! 46 //! For WebAssembly, enable one of the following features depending 47 //! on your JavaScript interop toolchain of choice: 48 //! 49 //! * `stdweb` - for [`stdweb`] combined with [`cargo-web`] 50 //! * `wasm-bindgen` - for [`wasm-bindgen`] 51 //! 52 //! By default, `uuid` can be depended on with: 53 //! 54 //! ```toml 55 //! [dependencies] 56 //! uuid = "0.8" 57 //! ``` 58 //! 59 //! To activate various features, use syntax like: 60 //! 61 //! ```toml 62 //! [dependencies] 63 //! uuid = { version = "0.8", features = ["serde", "v4"] } 64 //! ``` 65 //! 66 //! You can disable default features with: 67 //! 68 //! ```toml 69 //! [dependencies] 70 //! uuid = { version = "0.8", default-features = false } 71 //! ``` 72 //! 73 //! # Examples 74 //! 75 //! To parse a UUID given in the simple format and print it as a urn: 76 //! 77 //! ```rust 78 //! use uuid::Uuid; 79 //! 80 //! fn main() -> Result<(), uuid::Error> { 81 //! let my_uuid = 82 //! Uuid::parse_str("936DA01F9ABD4d9d80C702AF85C822A8")?; 83 //! println!("{}", my_uuid.to_urn()); 84 //! Ok(()) 85 //! } 86 //! ``` 87 //! 88 //! To create a new random (V4) UUID and print it out in hexadecimal form: 89 //! 90 //! ```ignore,rust 91 //! // Note that this requires the `v4` feature enabled in the uuid crate. 92 //! 93 //! use uuid::Uuid; 94 //! 95 //! fn main() -> Result<(), Box<dyn std::error::Error>> { 96 //! #[cfg(feature = "v4")] { 97 //! let my_uuid = Uuid::new_v4()?; 98 //! println!("{}", my_uuid); 99 //! } 100 //! Ok(()) 101 //! } 102 //! ``` 103 //! 104 //! # Strings 105 //! 106 //! Examples of string representations: 107 //! 108 //! * simple: `936DA01F9ABD4d9d80C702AF85C822A8` 109 //! * hyphenated: `550e8400-e29b-41d4-a716-446655440000` 110 //! * urn: `urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4` 111 //! 112 //! # References 113 //! 114 //! * [Wikipedia: Universally Unique Identifier](http://en.wikipedia.org/wiki/Universally_unique_identifier) 115 //! * [RFC4122: A Universally Unique IDentifier (UUID) URN Namespace](http://tools.ietf.org/html/rfc4122) 116 //! 117 //! [`wasm-bindgen`]: https://crates.io/crates/wasm-bindgen 118 //! [`cargo-web`]: https://crates.io/crates/cargo-web 119 //! [`stdweb`]: https://crates.io/crates/stdweb 120 //! [`Uuid`]: struct.Uuid.html 121 //! [`Uuid::new_v1`]: struct.Uuid.html#method.new_v1 122 //! [`Uuid::new_v3`]: struct.Uuid.html#method.new_v3 123 //! [`Uuid::new_v4`]: struct.Uuid.html#method.new_v4 124 //! [`Uuid::new_v5`]: struct.Uuid.html#method.new_v5 125 //! [`v1::ClockSequence`]: v1/trait.ClockSequence.html 126 //! [`v1::Context`]: v1/struct.Context.html 127 128 #![no_std] 129 #![deny(missing_debug_implementations, missing_docs)] 130 #![doc( 131 html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", 132 html_favicon_url = "https://www.rust-lang.org/favicon.ico", 133 html_root_url = "https://docs.rs/uuid/0.8.2" 134 )] 135 136 #[cfg(any(feature = "std", test))] 137 #[macro_use] 138 extern crate std; 139 140 #[cfg(all(not(feature = "std"), not(test)))] 141 #[macro_use] 142 extern crate core as std; 143 144 mod builder; 145 mod error; 146 mod parser; 147 mod prelude; 148 149 pub mod adapter; 150 #[cfg(feature = "v1")] 151 pub mod v1; 152 153 #[cfg(feature = "serde")] 154 mod serde_support; 155 #[cfg(feature = "slog")] 156 mod slog_support; 157 #[cfg(test)] 158 mod test_util; 159 #[cfg(all( 160 feature = "v3", 161 any( 162 not(target_arch = "wasm32"), 163 target_os = "wasi", 164 all( 165 target_arch = "wasm32", 166 any(feature = "stdweb", feature = "wasm-bindgen") 167 ) 168 ) 169 ))] 170 mod v3; 171 #[cfg(all( 172 feature = "v4", 173 any( 174 not(target_arch = "wasm32"), 175 target_os = "wasi", 176 all( 177 target_arch = "wasm32", 178 any(feature = "stdweb", feature = "wasm-bindgen") 179 ) 180 ) 181 ))] 182 mod v4; 183 #[cfg(all( 184 feature = "v5", 185 any( 186 not(target_arch = "wasm32"), 187 target_os = "wasi", 188 all( 189 target_arch = "wasm32", 190 any(feature = "stdweb", feature = "wasm-bindgen") 191 ) 192 ) 193 ))] 194 mod v5; 195 #[cfg(all(windows, feature = "winapi"))] 196 mod winapi_support; 197 198 use crate::std::{fmt, str}; 199 200 pub use crate::error::Error; 201 202 /// A builder struct for creating a UUID. 203 /// 204 /// # Examples 205 /// 206 /// Creating a v4 UUID from externally generated bytes: 207 /// 208 /// ``` 209 /// use uuid::{Builder, Variant, Version}; 210 /// 211 /// # let rng = || [ 212 /// # 70, 235, 208, 238, 14, 109, 67, 201, 185, 13, 204, 195, 90, 213 /// # 145, 63, 62, 214 /// # ]; 215 /// let random_bytes = rng(); 216 /// let uuid = Builder::from_bytes(random_bytes) 217 /// .set_variant(Variant::RFC4122) 218 /// .set_version(Version::Random) 219 /// .build(); 220 /// ``` 221 #[allow(missing_copy_implementations)] 222 #[derive(Debug)] 223 pub struct Builder(Bytes); 224 225 /// A 128-bit (16 byte) buffer containing the ID. 226 pub type Bytes = [u8; 16]; 227 228 /// The version of the UUID, denoting the generating algorithm. 229 #[derive(Clone, Copy, Debug, PartialEq)] 230 pub enum Version { 231 /// Special case for `nil` UUID. 232 Nil = 0, 233 /// Version 1: MAC address. 234 Mac, 235 /// Version 2: DCE Security. 236 Dce, 237 /// Version 3: MD5 hash. 238 Md5, 239 /// Version 4: Random. 240 Random, 241 /// Version 5: SHA-1 hash. 242 Sha1, 243 } 244 245 /// The reserved variants of UUIDs. 246 #[derive(Clone, Copy, Debug, PartialEq)] 247 pub enum Variant { 248 /// Reserved by the NCS for backward compatibility. 249 NCS = 0, 250 /// As described in the RFC4122 Specification (default). 251 RFC4122, 252 /// Reserved by Microsoft for backward compatibility. 253 Microsoft, 254 /// Reserved for future expansion. 255 Future, 256 } 257 258 /// A Universally Unique Identifier (UUID). 259 #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] 260 #[repr(transparent)] 261 pub struct Uuid(Bytes); 262 263 impl Uuid { 264 /// UUID namespace for Domain Name System (DNS). 265 pub const NAMESPACE_DNS: Self = Uuid([ 266 0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 267 0x4f, 0xd4, 0x30, 0xc8, 268 ]); 269 270 /// UUID namespace for ISO Object Identifiers (OIDs). 271 pub const NAMESPACE_OID: Self = Uuid([ 272 0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 273 0x4f, 0xd4, 0x30, 0xc8, 274 ]); 275 276 /// UUID namespace for Uniform Resource Locators (URLs). 277 pub const NAMESPACE_URL: Self = Uuid([ 278 0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 279 0x4f, 0xd4, 0x30, 0xc8, 280 ]); 281 282 /// UUID namespace for X.500 Distinguished Names (DNs). 283 pub const NAMESPACE_X500: Self = Uuid([ 284 0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 285 0x4f, 0xd4, 0x30, 0xc8, 286 ]); 287 288 /// Returns the variant of the UUID structure. 289 /// 290 /// This determines the interpretation of the structure of the UUID. 291 /// Currently only the RFC4122 variant is generated by this module. 292 /// 293 /// * [Variant Reference](http://tools.ietf.org/html/rfc4122#section-4.1.1) get_variant(&self) -> Option<Variant>294 pub fn get_variant(&self) -> Option<Variant> { 295 match self.as_bytes()[8] { 296 x if x & 0x80 == 0x00 => Some(Variant::NCS), 297 x if x & 0xc0 == 0x80 => Some(Variant::RFC4122), 298 x if x & 0xe0 == 0xc0 => Some(Variant::Microsoft), 299 x if x & 0xe0 == 0xe0 => Some(Variant::Future), 300 _ => None, 301 } 302 } 303 304 /// Returns the version number of the UUID. 305 /// 306 /// This represents the algorithm used to generate the contents. 307 /// 308 /// Currently only the Random (V4) algorithm is supported by this 309 /// module. There are security and privacy implications for using 310 /// older versions - see [Wikipedia: Universally Unique Identifier]( 311 /// http://en.wikipedia.org/wiki/Universally_unique_identifier) for 312 /// details. 313 /// 314 /// * [Version Reference](http://tools.ietf.org/html/rfc4122#section-4.1.3) get_version_num(&self) -> usize315 pub const fn get_version_num(&self) -> usize { 316 (self.as_bytes()[6] >> 4) as usize 317 } 318 319 /// Returns the version of the UUID. 320 /// 321 /// This represents the algorithm used to generate the contents get_version(&self) -> Option<Version>322 pub fn get_version(&self) -> Option<Version> { 323 let v = self.as_bytes()[6] >> 4; 324 match v { 325 0 if self.is_nil() => Some(Version::Nil), 326 1 => Some(Version::Mac), 327 2 => Some(Version::Dce), 328 3 => Some(Version::Md5), 329 4 => Some(Version::Random), 330 5 => Some(Version::Sha1), 331 _ => None, 332 } 333 } 334 335 /// Returns the four field values of the UUID in big-endian order. 336 /// 337 /// These values can be passed to the `from_fields()` method to get the 338 /// original `Uuid` back. 339 /// 340 /// * The first field value represents the first group of (eight) hex 341 /// digits, taken as a big-endian `u32` value. For V1 UUIDs, this field 342 /// represents the low 32 bits of the timestamp. 343 /// * The second field value represents the second group of (four) hex 344 /// digits, taken as a big-endian `u16` value. For V1 UUIDs, this field 345 /// represents the middle 16 bits of the timestamp. 346 /// * The third field value represents the third group of (four) hex digits, 347 /// taken as a big-endian `u16` value. The 4 most significant bits give 348 /// the UUID version, and for V1 UUIDs, the last 12 bits represent the 349 /// high 12 bits of the timestamp. 350 /// * The last field value represents the last two groups of four and twelve 351 /// hex digits, taken in order. The first 1-3 bits of this indicate the 352 /// UUID variant, and for V1 UUIDs, the next 13-15 bits indicate the clock 353 /// sequence and the last 48 bits indicate the node ID. 354 /// 355 /// # Examples 356 /// 357 /// ``` 358 /// use uuid::Uuid; 359 /// 360 /// fn main() -> Result<(), uuid::Error> { 361 /// let uuid = Uuid::nil(); 362 /// assert_eq!(uuid.as_fields(), (0, 0, 0, &[0u8; 8])); 363 /// 364 /// let uuid = Uuid::parse_str("936DA01F-9ABD-4D9D-80C7-02AF85C822A8")?; 365 /// assert_eq!( 366 /// uuid.as_fields(), 367 /// ( 368 /// 0x936DA01F, 369 /// 0x9ABD, 370 /// 0x4D9D, 371 /// b"\x80\xC7\x02\xAF\x85\xC8\x22\xA8" 372 /// ) 373 /// ); 374 /// 375 /// Ok(()) 376 /// } 377 /// ``` as_fields(&self) -> (u32, u16, u16, &[u8; 8])378 pub fn as_fields(&self) -> (u32, u16, u16, &[u8; 8]) { 379 let d1 = u32::from(self.as_bytes()[0]) << 24 380 | u32::from(self.as_bytes()[1]) << 16 381 | u32::from(self.as_bytes()[2]) << 8 382 | u32::from(self.as_bytes()[3]); 383 384 let d2 = 385 u16::from(self.as_bytes()[4]) << 8 | u16::from(self.as_bytes()[5]); 386 387 let d3 = 388 u16::from(self.as_bytes()[6]) << 8 | u16::from(self.as_bytes()[7]); 389 390 let d4: &[u8; 8] = 391 unsafe { &*(self.as_bytes()[8..16].as_ptr() as *const [u8; 8]) }; 392 (d1, d2, d3, d4) 393 } 394 395 /// Returns the four field values of the UUID in little-endian order. 396 /// 397 /// The bytes in the returned integer fields will 398 /// be converted from big-endian order. 399 /// 400 /// # Examples 401 /// 402 /// ``` 403 /// use uuid::Uuid; 404 /// 405 /// fn main() -> Result<(), uuid::Error> { 406 /// let uuid = Uuid::parse_str("936DA01F-9ABD-4D9D-80C7-02AF85C822A8")?; 407 /// assert_eq!( 408 /// uuid.to_fields_le(), 409 /// ( 410 /// 0x1FA06D93, 411 /// 0xBD9A, 412 /// 0x9D4D, 413 /// b"\x80\xC7\x02\xAF\x85\xC8\x22\xA8" 414 /// ) 415 /// ); 416 /// Ok(()) 417 /// } 418 /// ``` to_fields_le(&self) -> (u32, u16, u16, &[u8; 8])419 pub fn to_fields_le(&self) -> (u32, u16, u16, &[u8; 8]) { 420 let d1 = u32::from(self.as_bytes()[0]) 421 | u32::from(self.as_bytes()[1]) << 8 422 | u32::from(self.as_bytes()[2]) << 16 423 | u32::from(self.as_bytes()[3]) << 24; 424 425 let d2 = 426 u16::from(self.as_bytes()[4]) | u16::from(self.as_bytes()[5]) << 8; 427 428 let d3 = 429 u16::from(self.as_bytes()[6]) | u16::from(self.as_bytes()[7]) << 8; 430 431 let d4: &[u8; 8] = 432 unsafe { &*(self.as_bytes()[8..16].as_ptr() as *const [u8; 8]) }; 433 (d1, d2, d3, d4) 434 } 435 436 /// Returns a 128bit value containing the UUID data. 437 /// 438 /// The bytes in the UUID will be packed into a `u128`, like the 439 /// [`Uuid::as_bytes`] method. 440 /// 441 /// # Examples 442 /// 443 /// ``` 444 /// use uuid::Uuid; 445 /// 446 /// fn main() -> Result<(), uuid::Error> { 447 /// let uuid = Uuid::parse_str("936DA01F-9ABD-4D9D-80C7-02AF85C822A8")?; 448 /// assert_eq!( 449 /// uuid.as_u128(), 450 /// 0x936DA01F9ABD4D9D80C702AF85C822A8, 451 /// ); 452 /// Ok(()) 453 /// } 454 /// ``` as_u128(&self) -> u128455 pub fn as_u128(&self) -> u128 { 456 u128::from(self.as_bytes()[0]) << 120 457 | u128::from(self.as_bytes()[1]) << 112 458 | u128::from(self.as_bytes()[2]) << 104 459 | u128::from(self.as_bytes()[3]) << 96 460 | u128::from(self.as_bytes()[4]) << 88 461 | u128::from(self.as_bytes()[5]) << 80 462 | u128::from(self.as_bytes()[6]) << 72 463 | u128::from(self.as_bytes()[7]) << 64 464 | u128::from(self.as_bytes()[8]) << 56 465 | u128::from(self.as_bytes()[9]) << 48 466 | u128::from(self.as_bytes()[10]) << 40 467 | u128::from(self.as_bytes()[11]) << 32 468 | u128::from(self.as_bytes()[12]) << 24 469 | u128::from(self.as_bytes()[13]) << 16 470 | u128::from(self.as_bytes()[14]) << 8 471 | u128::from(self.as_bytes()[15]) 472 } 473 474 /// Returns a 128bit little-endian value containing the UUID data. 475 /// 476 /// The bytes in the UUID will be reversed and packed into a `u128`. 477 /// Note that this will produce a different result than 478 /// [`Uuid::to_fields_le`], because the entire UUID is reversed, rather 479 /// than reversing the individual fields in-place. 480 /// 481 /// # Examples 482 /// 483 /// ``` 484 /// use uuid::Uuid; 485 /// 486 /// fn main() -> Result<(), uuid::Error> { 487 /// let uuid = Uuid::parse_str("936DA01F-9ABD-4D9D-80C7-02AF85C822A8")?; 488 /// 489 /// assert_eq!( 490 /// uuid.to_u128_le(), 491 /// 0xA822C885AF02C7809D4DBD9A1FA06D93, 492 /// ); 493 /// Ok(()) 494 /// } 495 /// ``` to_u128_le(&self) -> u128496 pub fn to_u128_le(&self) -> u128 { 497 u128::from(self.as_bytes()[0]) 498 | u128::from(self.as_bytes()[1]) << 8 499 | u128::from(self.as_bytes()[2]) << 16 500 | u128::from(self.as_bytes()[3]) << 24 501 | u128::from(self.as_bytes()[4]) << 32 502 | u128::from(self.as_bytes()[5]) << 40 503 | u128::from(self.as_bytes()[6]) << 48 504 | u128::from(self.as_bytes()[7]) << 56 505 | u128::from(self.as_bytes()[8]) << 64 506 | u128::from(self.as_bytes()[9]) << 72 507 | u128::from(self.as_bytes()[10]) << 80 508 | u128::from(self.as_bytes()[11]) << 88 509 | u128::from(self.as_bytes()[12]) << 96 510 | u128::from(self.as_bytes()[13]) << 104 511 | u128::from(self.as_bytes()[14]) << 112 512 | u128::from(self.as_bytes()[15]) << 120 513 } 514 515 /// Returns an array of 16 octets containing the UUID data. as_bytes(&self) -> &Bytes516 pub const fn as_bytes(&self) -> &Bytes { 517 &self.0 518 } 519 520 /// Tests if the UUID is nil. is_nil(&self) -> bool521 pub fn is_nil(&self) -> bool { 522 self.as_bytes().iter().all(|&b| b == 0) 523 } 524 525 /// A buffer that can be used for `encode_...` calls, that is 526 /// guaranteed to be long enough for any of the adapters. 527 /// 528 /// # Examples 529 /// 530 /// ```rust 531 /// use uuid::Uuid; 532 /// 533 /// let uuid = Uuid::nil(); 534 /// 535 /// assert_eq!( 536 /// uuid.to_simple().encode_lower(&mut Uuid::encode_buffer()), 537 /// "00000000000000000000000000000000" 538 /// ); 539 /// 540 /// assert_eq!( 541 /// uuid.to_hyphenated() 542 /// .encode_lower(&mut Uuid::encode_buffer()), 543 /// "00000000-0000-0000-0000-000000000000" 544 /// ); 545 /// 546 /// assert_eq!( 547 /// uuid.to_urn().encode_lower(&mut Uuid::encode_buffer()), 548 /// "urn:uuid:00000000-0000-0000-0000-000000000000" 549 /// ); 550 /// ``` encode_buffer() -> [u8; adapter::Urn::LENGTH]551 pub const fn encode_buffer() -> [u8; adapter::Urn::LENGTH] { 552 [0; adapter::Urn::LENGTH] 553 } 554 } 555 556 impl fmt::Debug for Uuid { 557 #[inline] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result558 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 559 fmt::LowerHex::fmt(self, f) 560 } 561 } 562 563 impl fmt::Display for Uuid { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result564 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 565 fmt::LowerHex::fmt(self, f) 566 } 567 } 568 569 impl fmt::Display for Variant { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result570 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 571 match *self { 572 Variant::NCS => write!(f, "NCS"), 573 Variant::RFC4122 => write!(f, "RFC4122"), 574 Variant::Microsoft => write!(f, "Microsoft"), 575 Variant::Future => write!(f, "Future"), 576 } 577 } 578 } 579 580 impl fmt::LowerHex for Uuid { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result581 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 582 fmt::LowerHex::fmt(&self.to_hyphenated_ref(), f) 583 } 584 } 585 586 impl fmt::UpperHex for Uuid { 587 #[inline] fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result588 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 589 fmt::UpperHex::fmt(&self.to_hyphenated_ref(), f) 590 } 591 } 592 593 impl str::FromStr for Uuid { 594 type Err = Error; 595 from_str(uuid_str: &str) -> Result<Self, Self::Err>596 fn from_str(uuid_str: &str) -> Result<Self, Self::Err> { 597 Uuid::parse_str(uuid_str) 598 } 599 } 600 601 impl Default for Uuid { 602 #[inline] default() -> Self603 fn default() -> Self { 604 Uuid::nil() 605 } 606 } 607 608 #[cfg(test)] 609 mod tests { 610 use crate::{ 611 prelude::*, 612 std::string::{String, ToString}, 613 test_util, 614 }; 615 616 macro_rules! check { 617 ($buf:ident, $format:expr, $target:expr, $len:expr, $cond:expr) => { 618 $buf.clear(); 619 write!($buf, $format, $target).unwrap(); 620 assert!($buf.len() == $len); 621 assert!($buf.chars().all($cond), "{}", $buf); 622 }; 623 } 624 625 #[test] test_uuid_compare()626 fn test_uuid_compare() { 627 let uuid1 = test_util::new(); 628 let uuid2 = test_util::new2(); 629 630 assert_eq!(uuid1, uuid1); 631 assert_eq!(uuid2, uuid2); 632 633 assert_ne!(uuid1, uuid2); 634 assert_ne!(uuid2, uuid1); 635 } 636 637 #[test] test_uuid_default()638 fn test_uuid_default() { 639 let default_uuid = Uuid::default(); 640 let nil_uuid = Uuid::nil(); 641 642 assert_eq!(default_uuid, nil_uuid); 643 } 644 645 #[test] test_uuid_display()646 fn test_uuid_display() { 647 use super::fmt::Write; 648 649 let uuid = test_util::new(); 650 let s = uuid.to_string(); 651 let mut buffer = String::new(); 652 653 assert_eq!(s, uuid.to_hyphenated().to_string()); 654 655 check!(buffer, "{}", uuid, 36, |c| c.is_lowercase() 656 || c.is_digit(10) 657 || c == '-'); 658 } 659 660 #[test] test_uuid_lowerhex()661 fn test_uuid_lowerhex() { 662 use super::fmt::Write; 663 664 let mut buffer = String::new(); 665 let uuid = test_util::new(); 666 667 check!(buffer, "{:x}", uuid, 36, |c| c.is_lowercase() 668 || c.is_digit(10) 669 || c == '-'); 670 } 671 672 // noinspection RsAssertEqual 673 #[test] test_uuid_operator_eq()674 fn test_uuid_operator_eq() { 675 let uuid1 = test_util::new(); 676 let uuid1_dup = uuid1.clone(); 677 let uuid2 = test_util::new2(); 678 679 assert!(uuid1 == uuid1); 680 assert!(uuid1 == uuid1_dup); 681 assert!(uuid1_dup == uuid1); 682 683 assert!(uuid1 != uuid2); 684 assert!(uuid2 != uuid1); 685 assert!(uuid1_dup != uuid2); 686 assert!(uuid2 != uuid1_dup); 687 } 688 689 #[test] test_uuid_to_string()690 fn test_uuid_to_string() { 691 use super::fmt::Write; 692 693 let uuid = test_util::new(); 694 let s = uuid.to_string(); 695 let mut buffer = String::new(); 696 697 assert_eq!(s.len(), 36); 698 699 check!(buffer, "{}", s, 36, |c| c.is_lowercase() 700 || c.is_digit(10) 701 || c == '-'); 702 } 703 704 #[test] test_uuid_upperhex()705 fn test_uuid_upperhex() { 706 use super::fmt::Write; 707 708 let mut buffer = String::new(); 709 let uuid = test_util::new(); 710 711 check!(buffer, "{:X}", uuid, 36, |c| c.is_uppercase() 712 || c.is_digit(10) 713 || c == '-'); 714 } 715 716 #[test] test_nil()717 fn test_nil() { 718 let nil = Uuid::nil(); 719 let not_nil = test_util::new(); 720 let from_bytes = Uuid::from_bytes([ 721 4, 54, 67, 12, 43, 2, 2, 76, 32, 50, 87, 5, 1, 33, 43, 87, 722 ]); 723 724 assert_eq!(from_bytes.get_version(), None); 725 726 assert!(nil.is_nil()); 727 assert!(!not_nil.is_nil()); 728 729 assert_eq!(nil.get_version(), Some(Version::Nil)); 730 assert_eq!(not_nil.get_version(), Some(Version::Random)) 731 } 732 733 #[test] test_predefined_namespaces()734 fn test_predefined_namespaces() { 735 assert_eq!( 736 Uuid::NAMESPACE_DNS.to_hyphenated().to_string(), 737 "6ba7b810-9dad-11d1-80b4-00c04fd430c8" 738 ); 739 assert_eq!( 740 Uuid::NAMESPACE_URL.to_hyphenated().to_string(), 741 "6ba7b811-9dad-11d1-80b4-00c04fd430c8" 742 ); 743 assert_eq!( 744 Uuid::NAMESPACE_OID.to_hyphenated().to_string(), 745 "6ba7b812-9dad-11d1-80b4-00c04fd430c8" 746 ); 747 assert_eq!( 748 Uuid::NAMESPACE_X500.to_hyphenated().to_string(), 749 "6ba7b814-9dad-11d1-80b4-00c04fd430c8" 750 ); 751 } 752 753 #[cfg(feature = "v3")] 754 #[test] test_get_version_v3()755 fn test_get_version_v3() { 756 let uuid = 757 Uuid::new_v3(&Uuid::NAMESPACE_DNS, "rust-lang.org".as_bytes()); 758 759 assert_eq!(uuid.get_version().unwrap(), Version::Md5); 760 assert_eq!(uuid.get_version_num(), 3); 761 } 762 763 #[test] test_get_variant()764 fn test_get_variant() { 765 let uuid1 = test_util::new(); 766 let uuid2 = 767 Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap(); 768 let uuid3 = 769 Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8").unwrap(); 770 let uuid4 = 771 Uuid::parse_str("936DA01F9ABD4d9dC0C702AF85C822A8").unwrap(); 772 let uuid5 = 773 Uuid::parse_str("F9168C5E-CEB2-4faa-D6BF-329BF39FA1E4").unwrap(); 774 let uuid6 = 775 Uuid::parse_str("f81d4fae-7dec-11d0-7765-00a0c91e6bf6").unwrap(); 776 777 assert_eq!(uuid1.get_variant().unwrap(), Variant::RFC4122); 778 assert_eq!(uuid2.get_variant().unwrap(), Variant::RFC4122); 779 assert_eq!(uuid3.get_variant().unwrap(), Variant::RFC4122); 780 assert_eq!(uuid4.get_variant().unwrap(), Variant::Microsoft); 781 assert_eq!(uuid5.get_variant().unwrap(), Variant::Microsoft); 782 assert_eq!(uuid6.get_variant().unwrap(), Variant::NCS); 783 } 784 785 #[test] test_to_simple_string()786 fn test_to_simple_string() { 787 let uuid1 = test_util::new(); 788 let s = uuid1.to_simple().to_string(); 789 790 assert_eq!(s.len(), 32); 791 assert!(s.chars().all(|c| c.is_digit(16))); 792 } 793 794 #[test] test_to_hyphenated_string()795 fn test_to_hyphenated_string() { 796 let uuid1 = test_util::new(); 797 let s = uuid1.to_hyphenated().to_string(); 798 799 assert!(s.len() == 36); 800 assert!(s.chars().all(|c| c.is_digit(16) || c == '-')); 801 } 802 803 #[test] test_upper_lower_hex()804 fn test_upper_lower_hex() { 805 use std::fmt::Write; 806 807 let mut buf = String::new(); 808 let u = test_util::new(); 809 810 macro_rules! check { 811 ($buf:ident, $format:expr, $target:expr, $len:expr, $cond:expr) => { 812 $buf.clear(); 813 write!($buf, $format, $target).unwrap(); 814 assert!(buf.len() == $len); 815 assert!($buf.chars().all($cond), "{}", $buf); 816 }; 817 } 818 819 check!(buf, "{:X}", u, 36, |c| c.is_uppercase() 820 || c.is_digit(10) 821 || c == '-'); 822 check!(buf, "{:X}", u.to_hyphenated(), 36, |c| c.is_uppercase() 823 || c.is_digit(10) 824 || c == '-'); 825 check!(buf, "{:X}", u.to_simple(), 32, |c| c.is_uppercase() 826 || c.is_digit(10)); 827 828 check!(buf, "{:x}", u.to_hyphenated(), 36, |c| c.is_lowercase() 829 || c.is_digit(10) 830 || c == '-'); 831 check!(buf, "{:x}", u.to_simple(), 32, |c| c.is_lowercase() 832 || c.is_digit(10)); 833 } 834 835 #[test] test_to_urn_string()836 fn test_to_urn_string() { 837 let uuid1 = test_util::new(); 838 let ss = uuid1.to_urn().to_string(); 839 let s = &ss[9..]; 840 841 assert!(ss.starts_with("urn:uuid:")); 842 assert_eq!(s.len(), 36); 843 assert!(s.chars().all(|c| c.is_digit(16) || c == '-')); 844 } 845 846 #[test] test_to_simple_string_matching()847 fn test_to_simple_string_matching() { 848 let uuid1 = test_util::new(); 849 850 let hs = uuid1.to_hyphenated().to_string(); 851 let ss = uuid1.to_simple().to_string(); 852 853 let hsn = hs.chars().filter(|&c| c != '-').collect::<String>(); 854 855 assert_eq!(hsn, ss); 856 } 857 858 #[test] test_string_roundtrip()859 fn test_string_roundtrip() { 860 let uuid = test_util::new(); 861 862 let hs = uuid.to_hyphenated().to_string(); 863 let uuid_hs = Uuid::parse_str(&hs).unwrap(); 864 assert_eq!(uuid_hs, uuid); 865 866 let ss = uuid.to_string(); 867 let uuid_ss = Uuid::parse_str(&ss).unwrap(); 868 assert_eq!(uuid_ss, uuid); 869 } 870 871 #[test] test_from_fields()872 fn test_from_fields() { 873 let d1: u32 = 0xa1a2a3a4; 874 let d2: u16 = 0xb1b2; 875 let d3: u16 = 0xc1c2; 876 let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8]; 877 878 let u = Uuid::from_fields(d1, d2, d3, &d4).unwrap(); 879 880 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"; 881 let result = u.to_simple().to_string(); 882 assert_eq!(result, expected); 883 } 884 885 #[test] test_from_fields_le()886 fn test_from_fields_le() { 887 let d1: u32 = 0xa4a3a2a1; 888 let d2: u16 = 0xb2b1; 889 let d3: u16 = 0xc2c1; 890 let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8]; 891 892 let u = Uuid::from_fields_le(d1, d2, d3, &d4).unwrap(); 893 894 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"; 895 let result = u.to_simple().to_string(); 896 assert_eq!(result, expected); 897 } 898 899 #[test] test_as_fields()900 fn test_as_fields() { 901 let u = test_util::new(); 902 let (d1, d2, d3, d4) = u.as_fields(); 903 904 assert_ne!(d1, 0); 905 assert_ne!(d2, 0); 906 assert_ne!(d3, 0); 907 assert_eq!(d4.len(), 8); 908 assert!(!d4.iter().all(|&b| b == 0)); 909 } 910 911 #[test] test_fields_roundtrip()912 fn test_fields_roundtrip() { 913 let d1_in: u32 = 0xa1a2a3a4; 914 let d2_in: u16 = 0xb1b2; 915 let d3_in: u16 = 0xc1c2; 916 let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8]; 917 918 let u = Uuid::from_fields(d1_in, d2_in, d3_in, d4_in).unwrap(); 919 let (d1_out, d2_out, d3_out, d4_out) = u.as_fields(); 920 921 assert_eq!(d1_in, d1_out); 922 assert_eq!(d2_in, d2_out); 923 assert_eq!(d3_in, d3_out); 924 assert_eq!(d4_in, d4_out); 925 } 926 927 #[test] test_fields_le_roundtrip()928 fn test_fields_le_roundtrip() { 929 let d1_in: u32 = 0xa4a3a2a1; 930 let d2_in: u16 = 0xb2b1; 931 let d3_in: u16 = 0xc2c1; 932 let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8]; 933 934 let u = Uuid::from_fields_le(d1_in, d2_in, d3_in, d4_in).unwrap(); 935 let (d1_out, d2_out, d3_out, d4_out) = u.to_fields_le(); 936 937 assert_eq!(d1_in, d1_out); 938 assert_eq!(d2_in, d2_out); 939 assert_eq!(d3_in, d3_out); 940 assert_eq!(d4_in, d4_out); 941 } 942 943 #[test] test_fields_le_are_actually_le()944 fn test_fields_le_are_actually_le() { 945 let d1_in: u32 = 0xa1a2a3a4; 946 let d2_in: u16 = 0xb1b2; 947 let d3_in: u16 = 0xc1c2; 948 let d4_in = &[0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8]; 949 950 let u = Uuid::from_fields(d1_in, d2_in, d3_in, d4_in).unwrap(); 951 let (d1_out, d2_out, d3_out, d4_out) = u.to_fields_le(); 952 953 assert_eq!(d1_in, d1_out.swap_bytes()); 954 assert_eq!(d2_in, d2_out.swap_bytes()); 955 assert_eq!(d3_in, d3_out.swap_bytes()); 956 assert_eq!(d4_in, d4_out); 957 } 958 959 #[test] test_from_u128()960 fn test_from_u128() { 961 let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8; 962 963 let u = Uuid::from_u128(v_in); 964 965 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"; 966 let result = u.to_simple().to_string(); 967 assert_eq!(result, expected); 968 } 969 970 #[test] test_from_u128_le()971 fn test_from_u128_le() { 972 let v_in: u128 = 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1; 973 974 let u = Uuid::from_u128_le(v_in); 975 976 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"; 977 let result = u.to_simple().to_string(); 978 assert_eq!(result, expected); 979 } 980 981 #[test] test_u128_roundtrip()982 fn test_u128_roundtrip() { 983 let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8; 984 985 let u = Uuid::from_u128(v_in); 986 let v_out = u.as_u128(); 987 988 assert_eq!(v_in, v_out); 989 } 990 991 #[test] test_u128_le_roundtrip()992 fn test_u128_le_roundtrip() { 993 let v_in: u128 = 0xd8d7d6d5d4d3d2d1c2c1b2b1a4a3a2a1; 994 995 let u = Uuid::from_u128_le(v_in); 996 let v_out = u.to_u128_le(); 997 998 assert_eq!(v_in, v_out); 999 } 1000 1001 #[test] test_u128_le_is_actually_le()1002 fn test_u128_le_is_actually_le() { 1003 let v_in: u128 = 0xa1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8; 1004 1005 let u = Uuid::from_u128(v_in); 1006 let v_out = u.to_u128_le(); 1007 1008 assert_eq!(v_in, v_out.swap_bytes()); 1009 } 1010 1011 #[test] test_from_slice()1012 fn test_from_slice() { 1013 let b = [ 1014 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 1015 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 1016 ]; 1017 1018 let u = Uuid::from_slice(&b).unwrap(); 1019 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"; 1020 1021 assert_eq!(u.to_simple().to_string(), expected); 1022 } 1023 1024 #[test] test_from_bytes()1025 fn test_from_bytes() { 1026 let b = [ 1027 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 1028 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 1029 ]; 1030 1031 let u = Uuid::from_bytes(b); 1032 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8"; 1033 1034 assert_eq!(u.to_simple().to_string(), expected); 1035 } 1036 1037 #[test] test_as_bytes()1038 fn test_as_bytes() { 1039 let u = test_util::new(); 1040 let ub = u.as_bytes(); 1041 1042 assert_eq!(ub.len(), 16); 1043 assert!(!ub.iter().all(|&b| b == 0)); 1044 } 1045 1046 #[test] test_bytes_roundtrip()1047 fn test_bytes_roundtrip() { 1048 let b_in: crate::Bytes = [ 1049 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3, 1050 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 1051 ]; 1052 1053 let u = Uuid::from_slice(&b_in).unwrap(); 1054 1055 let b_out = u.as_bytes(); 1056 1057 assert_eq!(&b_in, b_out); 1058 } 1059 1060 #[test] test_iterbytes_impl_for_uuid()1061 fn test_iterbytes_impl_for_uuid() { 1062 let mut set = std::collections::HashSet::new(); 1063 let id1 = test_util::new(); 1064 let id2 = test_util::new2(); 1065 set.insert(id1.clone()); 1066 1067 assert!(set.contains(&id1)); 1068 assert!(!set.contains(&id2)); 1069 } 1070 } 1071