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