1 // Copyright 2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
12 Generate and parse UUIDs
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 unique
16 identifiers to entities without requiring a central allocating authority.
18 They are particularly useful in distributed systems, though can be used in
19 disparate areas, such as databases and network protocols. Typically a UUID is
20 displayed in a readable string form as a sequence of hexadecimal digits,
21 separated into groups by hyphens.
23 The uniqueness property is not strictly guaranteed, however for all practical
24 purposes, it can be assumed that an unintentional collision would be extremely
29 To create a new random (V4) UUID and print it out in hexadecimal form:
35 let uuid1 = Uuid::new_v4();
36 println!("{}", uuid1.to_str());
42 Examples of string representations:
44 * simple: `936DA01F9ABD4d9d80C702AF85C822A8`
45 * hyphenated: `550e8400-e29b-41d4-a716-446655440000`
46 * urn: `urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4`
50 * [Wikipedia: Universally Unique Identifier](
51 http://en.wikipedia.org/wiki/Universally_unique_identifier)
52 * [RFC4122: A Universally Unique IDentifier (UUID) URN Namespace](
53 http://tools.ietf.org/html/rfc4122)
57 #![crate_id = "uuid#0.11-pre"]
58 #![crate_type = "rlib"]
59 #![crate_type = "dylib"]
60 #![license = "MIT/ASL2"]
61 #![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
62 html_favicon_url = "http://www.rust-lang.org/favicon.ico",
63 html_root_url = "http://static.rust-lang.org/doc/master")]
65 #![feature(default_type_params)]
67 // test harness access
72 extern crate serialize;
74 use std::cast::{transmute,transmute_copy};
76 use std::default::Default;
78 use std::from_str::FromStr;
80 use std::num::FromStrRadix;
86 use serialize::{Encoder, Encodable, Decoder, Decodable};
88 /// A 128-bit (16 byte) buffer containing the ID
89 pub type UuidBytes = [u8, ..16];
91 /// The version of the UUID, denoting the generating algorithm
93 pub enum UuidVersion {
94 /// Version 1: MAC address
96 /// Version 2: DCE Security
98 /// Version 3: MD5 hash
100 /// Version 4: Random
102 /// Version 5: SHA-1 hash
106 /// The reserved variants of UUIDs
108 pub enum UuidVariant {
109 /// Reserved by the NCS for backward compatibility
111 /// As described in the RFC4122 Specification (default)
113 /// Reserved by Microsoft for backward compatibility
115 /// Reserved for future expansion
119 /// A Universally Unique Identifier (UUID)
121 /// The 128-bit number stored in 16 bytes
125 impl<S: Writer> Hash<S> for Uuid {
126 fn hash(&self, state: &mut S) {
127 self.bytes.hash(state)
131 /// A UUID stored as fields (identical to UUID, used only for conversions)
133 /// First field, 32-bit word
135 /// Second field, 16-bit short
137 /// Third field, 16-bit short
139 /// Fourth field, 8 bytes
143 /// Error details for string parsing failures
144 #[allow(missing_doc)]
145 pub enum ParseError {
146 ErrorInvalidLength(uint),
147 ErrorInvalidCharacter(char, uint),
148 ErrorInvalidGroups(uint),
149 ErrorInvalidGroupLength(uint, uint, uint),
152 /// Converts a ParseError to a string
153 impl fmt::Show for ParseError {
154 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
156 ErrorInvalidLength(found) =>
157 write!(f.buf, "Invalid length; expecting 32, 36 or 45 chars, \
159 ErrorInvalidCharacter(found, pos) =>
160 write!(f.buf, "Invalid character; found `{}` (0x{:02x}) at \
161 offset {}", found, found as uint, pos),
162 ErrorInvalidGroups(found) =>
163 write!(f.buf, "Malformed; wrong number of groups: expected 1 \
164 or 5, found {}", found),
165 ErrorInvalidGroupLength(group, found, expecting) =>
166 write!(f.buf, "Malformed; length of group {} was {}, \
167 expecting {}", group, found, expecting),
172 // Length of each hyphenated group in hex digits
173 static UuidGroupLens: [uint, ..5] = [8u, 4u, 4u, 4u, 12u];
177 /// Returns a nil or empty UUID (containing all zeroes)
178 pub fn nil() -> Uuid {
179 let uuid = Uuid{ bytes: [0, .. 16] };
183 /// Create a new UUID of the specified version
184 pub fn new(v: UuidVersion) -> Option<Uuid> {
186 Version4Random => Some(Uuid::new_v4()),
191 /// Creates a new random UUID
193 /// Uses the `rand` module's default RNG task as the source
194 /// of random numbers. Use the rand::Rand trait to supply
195 /// a custom generator if required.
196 pub fn new_v4() -> Uuid {
197 let ub = rand::task_rng().gen_vec(16);
198 let mut uuid = Uuid{ bytes: [0, .. 16] };
199 slice::bytes::copy_memory(uuid.bytes, ub.as_slice());
200 uuid.set_variant(VariantRFC4122);
201 uuid.set_version(Version4Random);
205 /// Creates a UUID using the supplied field values
208 /// * `d1` A 32-bit word
209 /// * `d2` A 16-bit word
210 /// * `d3` A 16-bit word
211 /// * `d4` Array of 8 octets
212 pub fn from_fields(d1: u32, d2: u16, d3: u16, d4: &[u8]) -> Uuid {
213 use std::mem::{to_be16, to_be32};
215 // First construct a temporary field-based struct
216 let mut fields = UuidFields {
223 fields.data1 = to_be32(d1);
224 fields.data2 = to_be16(d2);
225 fields.data3 = to_be16(d3);
226 slice::bytes::copy_memory(fields.data4, d4);
233 /// Creates a UUID using the supplied bytes
236 /// * `b` An array or slice of 16 bytes
237 pub fn from_bytes(b: &[u8]) -> Option<Uuid> {
242 let mut uuid = Uuid{ bytes: [0, .. 16] };
243 slice::bytes::copy_memory(uuid.bytes, b);
247 /// Specifies the variant of the UUID structure
248 fn set_variant(&mut self, v: UuidVariant) {
249 // Octet 8 contains the variant in the most significant 3 bits
251 VariantNCS => // b0xx...
252 self.bytes[8] = self.bytes[8] & 0x7f,
253 VariantRFC4122 => // b10x...
254 self.bytes[8] = (self.bytes[8] & 0x3f) | 0x80,
255 VariantMicrosoft => // b110...
256 self.bytes[8] = (self.bytes[8] & 0x1f) | 0xc0,
257 VariantFuture => // b111...
258 self.bytes[8] = (self.bytes[8] & 0x1f) | 0xe0,
262 /// Returns the variant of the UUID structure
264 /// This determines the interpretation of the structure of the UUID.
265 /// Currently only the RFC4122 variant is generated by this module.
267 /// * [Variant Reference](http://tools.ietf.org/html/rfc4122#section-4.1.1)
268 pub fn get_variant(&self) -> Option<UuidVariant> {
269 if self.bytes[8] & 0x80 == 0x00 {
271 } else if self.bytes[8] & 0xc0 == 0x80 {
273 } else if self.bytes[8] & 0xe0 == 0xc0 {
274 Some(VariantMicrosoft)
275 } else if self.bytes[8] & 0xe0 == 0xe0 {
282 /// Specifies the version number of the UUID
283 fn set_version(&mut self, v: UuidVersion) {
284 self.bytes[6] = (self.bytes[6] & 0xF) | ((v as u8) << 4);
287 /// Returns the version number of the UUID
289 /// This represents the algorithm used to generate the contents.
291 /// Currently only the Random (V4) algorithm is supported by this
292 /// module. There are security and privacy implications for using
293 /// older versions - see [Wikipedia: Universally Unique Identifier](
294 /// http://en.wikipedia.org/wiki/Universally_unique_identifier) for
297 /// * [Version Reference](http://tools.ietf.org/html/rfc4122#section-4.1.3)
298 pub fn get_version_num(&self) -> uint {
299 (self.bytes[6] >> 4) as uint
302 /// Returns the version of the UUID
304 /// This represents the algorithm used to generate the contents
305 pub fn get_version(&self) -> Option<UuidVersion> {
306 let v = self.bytes[6] >> 4;
308 1 => Some(Version1Mac),
309 2 => Some(Version2Dce),
310 3 => Some(Version3Md5),
311 4 => Some(Version4Random),
312 5 => Some(Version5Sha1),
317 /// Return an array of 16 octets containing the UUID data
318 pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
319 self.bytes.as_slice()
322 /// Returns the UUID as a string of 16 hexadecimal digits
324 /// Example: `936DA01F9ABD4d9d80C702AF85C822A8`
325 pub fn to_simple_str(&self) -> ~str {
326 let mut s: Vec<u8> = Vec::from_elem(32, 0u8);
327 for i in range(0u, 16u) {
328 let digit = format!("{:02x}", self.bytes[i] as uint);
329 *s.get_mut(i*2+0) = digit[0];
330 *s.get_mut(i*2+1) = digit[1];
332 str::from_utf8(s.as_slice()).unwrap().to_str()
335 /// Returns a string of hexadecimal digits, separated into groups with a hyphen.
337 /// Example: `550e8400-e29b-41d4-a716-446655440000`
338 pub fn to_hyphenated_str(&self) -> ~str {
339 use std::mem::{to_be16, to_be32};
340 // Convert to field-based struct as it matches groups in output.
341 // Ensure fields are in network byte order, as per RFC.
342 let mut uf: UuidFields;
344 uf = transmute_copy(&self.bytes);
346 uf.data1 = to_be32(uf.data1);
347 uf.data2 = to_be16(uf.data2);
348 uf.data3 = to_be16(uf.data3);
349 let s = format!("{:08x}-{:04x}-{:04x}-{:02x}{:02x}-\
350 {:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
353 uf.data4[0], uf.data4[1],
354 uf.data4[2], uf.data4[3], uf.data4[4],
355 uf.data4[5], uf.data4[6], uf.data4[7]);
359 /// Returns the UUID formatted as a full URN string
361 /// This is the same as the hyphenated format, but with the "urn:uuid:" prefix.
363 /// Example: `urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4`
364 pub fn to_urn_str(&self) -> ~str {
365 "urn:uuid:" + self.to_hyphenated_str()
368 /// Parses a UUID from a string of hexadecimal digits with optional hyphens
370 /// Any of the formats generated by this module (simple, hyphenated, urn) are
371 /// supported by this parsing function.
372 pub fn parse_string(us: &str) -> Result<Uuid, ParseError> {
374 let mut us = us.clone();
375 let orig_len = us.len();
377 // Ensure length is valid for any of the supported formats
378 if orig_len != 32 && orig_len != 36 && orig_len != 45 {
379 return Err(ErrorInvalidLength(orig_len));
382 // Strip off URN prefix if present
383 if us.starts_with("urn:uuid:") {
384 us = us.slice(9, orig_len);
387 // Make sure all chars are either hex digits or hyphen
388 for (i, c) in us.chars().enumerate() {
390 '0'..'9' | 'A'..'F' | 'a'..'f' | '-' => {},
391 _ => return Err(ErrorInvalidCharacter(c, i)),
395 // Split string up by hyphens into groups
396 let hex_groups: Vec<&str> = us.split_str("-").collect();
398 // Get the length of each group
399 let group_lens: Vec<uint> = hex_groups.iter().map(|&v| v.len()).collect();
401 // Ensure the group lengths are valid
402 match group_lens.len() {
403 // Single group, no hyphens
405 if *group_lens.get(0) != 32 {
406 return Err(ErrorInvalidLength(*group_lens.get(0)));
409 // Five groups, hyphens in between each
411 // Ensure each group length matches the expected
412 for (i, (&gl, &expected)) in
413 group_lens.iter().zip(UuidGroupLens.iter()).enumerate() {
415 return Err(ErrorInvalidGroupLength(i, gl, expected))
420 return Err(ErrorInvalidGroups(group_lens.len()));
424 // Normalise into one long hex string
425 let vs = hex_groups.concat();
427 // At this point, we know we have a valid hex string, without hyphens
428 assert!(vs.len() == 32);
429 assert!(vs.chars().all(|c| c.is_digit_radix(16)));
431 // Allocate output UUID buffer
432 let mut ub = [0u8, ..16];
434 // Extract each hex digit from the string
435 for i in range(0u, 16u) {
436 ub[i] = FromStrRadix::from_str_radix(vs.slice(i*2, (i+1)*2), 16).unwrap();
439 Ok(Uuid::from_bytes(ub).unwrap())
442 /// Tests if the UUID is nil
443 pub fn is_nil(&self) -> bool {
444 return self.bytes.iter().all(|&b| b == 0);
448 impl Default for Uuid {
449 /// Returns the nil UUID, which is all zeroes
450 fn default() -> Uuid {
455 impl Clone for Uuid {
456 /// Returns a copy of the UUID
457 fn clone(&self) -> Uuid { *self }
460 impl FromStr for Uuid {
461 /// Parse a hex string and interpret as a UUID
463 /// Accepted formats are a sequence of 32 hexadecimal characters,
464 /// with or without hypens (grouped as 8, 4, 4, 4, 12).
465 fn from_str(us: &str) -> Option<Uuid> {
466 let result = Uuid::parse_string(us);
474 /// Convert the UUID to a hexadecimal-based string representation
475 impl fmt::Show for Uuid {
476 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
477 write!(f.buf, "{}", self.to_simple_str())
481 /// Test two UUIDs for equality
483 /// UUIDs are equal only when they are byte-for-byte identical
485 fn eq(&self, other: &Uuid) -> bool {
486 self.bytes == other.bytes
490 impl TotalEq for Uuid {}
492 // FIXME #9845: Test these more thoroughly
493 impl<T: Encoder<E>, E> Encodable<T, E> for Uuid {
494 /// Encode a UUID as a hypenated string
495 fn encode(&self, e: &mut T) -> Result<(), E> {
496 e.emit_str(self.to_hyphenated_str())
500 impl<T: Decoder<E>, E> Decodable<T, E> for Uuid {
501 /// Decode a UUID from a string
502 fn decode(d: &mut T) -> Result<Uuid, E> {
503 Ok(from_str(try!(d.read_str())).unwrap())
507 /// Generates a random instance of UUID (V4 conformant)
508 impl rand::Rand for Uuid {
510 fn rand<R: rand::Rng>(rng: &mut R) -> Uuid {
511 let ub = rng.gen_vec(16);
512 let mut uuid = Uuid{ bytes: [0, .. 16] };
513 slice::bytes::copy_memory(uuid.bytes, ub.as_slice());
514 uuid.set_variant(VariantRFC4122);
515 uuid.set_version(Version4Random);
522 extern crate collections;
525 use super::{Uuid, VariantMicrosoft, VariantNCS, VariantRFC4122,
526 Version1Mac, Version2Dce, Version3Md5, Version4Random,
529 use std::io::MemWriter;
533 let nil = Uuid::nil();
534 let not_nil = Uuid::new_v4();
536 assert!(nil.is_nil());
537 assert!(!not_nil.is_nil());
543 let uuid1 = Uuid::new(Version4Random).unwrap();
544 let s = uuid1.to_simple_str();
546 assert!(s.len() == 32);
547 assert!(uuid1.get_version().unwrap() == Version4Random);
549 // Test unsupported versions
550 assert!(Uuid::new(Version1Mac) == None);
551 assert!(Uuid::new(Version2Dce) == None);
552 assert!(Uuid::new(Version3Md5) == None);
553 assert!(Uuid::new(Version5Sha1) == None);
558 let uuid1 = Uuid::new_v4();
560 assert!(uuid1.get_version().unwrap() == Version4Random);
561 assert!(uuid1.get_variant().unwrap() == VariantRFC4122);
565 fn test_get_version() {
566 let uuid1 = Uuid::new_v4();
568 assert!(uuid1.get_version().unwrap() == Version4Random);
569 assert!(uuid1.get_version_num() == 4);
573 fn test_get_variant() {
574 let uuid1 = Uuid::new_v4();
575 let uuid2 = Uuid::parse_string("550e8400-e29b-41d4-a716-446655440000").unwrap();
576 let uuid3 = Uuid::parse_string("67e55044-10b1-426f-9247-bb680e5fe0c8").unwrap();
577 let uuid4 = Uuid::parse_string("936DA01F9ABD4d9dC0C702AF85C822A8").unwrap();
578 let uuid5 = Uuid::parse_string("F9168C5E-CEB2-4faa-D6BF-329BF39FA1E4").unwrap();
579 let uuid6 = Uuid::parse_string("f81d4fae-7dec-11d0-7765-00a0c91e6bf6").unwrap();
581 assert!(uuid1.get_variant().unwrap() == VariantRFC4122);
582 assert!(uuid2.get_variant().unwrap() == VariantRFC4122);
583 assert!(uuid3.get_variant().unwrap() == VariantRFC4122);
584 assert!(uuid4.get_variant().unwrap() == VariantMicrosoft);
585 assert!(uuid5.get_variant().unwrap() == VariantMicrosoft);
586 assert!(uuid6.get_variant().unwrap() == VariantNCS);
590 fn test_parse_uuid_v4() {
591 use super::{ErrorInvalidCharacter, ErrorInvalidGroups,
592 ErrorInvalidGroupLength, ErrorInvalidLength};
595 assert!(Uuid::parse_string("").is_err());
596 assert!(Uuid::parse_string("!").is_err());
597 assert!(Uuid::parse_string("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E45").is_err());
598 assert!(Uuid::parse_string("F9168C5E-CEB2-4faa-BBF-329BF39FA1E4").is_err());
599 assert!(Uuid::parse_string("F9168C5E-CEB2-4faa-BGBF-329BF39FA1E4").is_err());
600 assert!(Uuid::parse_string("F9168C5E-CEB2-4faa-B6BFF329BF39FA1E4").is_err());
601 assert!(Uuid::parse_string("F9168C5E-CEB2-4faa").is_err());
602 assert!(Uuid::parse_string("F9168C5E-CEB2-4faaXB6BFF329BF39FA1E4").is_err());
603 assert!(Uuid::parse_string("F9168C5E-CEB-24fa-eB6BFF32-BF39FA1E4").is_err());
604 assert!(Uuid::parse_string("01020304-1112-2122-3132-41424344").is_err());
605 assert!(Uuid::parse_string("67e5504410b1426f9247bb680e5fe0c").is_err());
606 assert!(Uuid::parse_string("67e5504410b1426f9247bb680e5fe0c88").is_err());
607 assert!(Uuid::parse_string("67e5504410b1426f9247bb680e5fe0cg8").is_err());
608 assert!(Uuid::parse_string("67e5504410b1426%9247bb680e5fe0c8").is_err());
611 assert!(Uuid::parse_string("00000000000000000000000000000000").is_ok());
612 assert!(Uuid::parse_string("67e55044-10b1-426f-9247-bb680e5fe0c8").is_ok());
613 assert!(Uuid::parse_string("67e55044-10b1-426f-9247-bb680e5fe0c8").is_ok());
614 assert!(Uuid::parse_string("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4").is_ok());
615 assert!(Uuid::parse_string("67e5504410b1426f9247bb680e5fe0c8").is_ok());
616 assert!(Uuid::parse_string("01020304-1112-2122-3132-414243444546").is_ok());
617 assert!(Uuid::parse_string("urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8").is_ok());
620 let nil = Uuid::nil();
621 assert!(Uuid::parse_string("00000000000000000000000000000000").unwrap() == nil);
622 assert!(Uuid::parse_string("00000000-0000-0000-0000-000000000000").unwrap() == nil);
625 let uuid_orig = Uuid::new_v4();
626 let orig_str = uuid_orig.to_str();
627 let uuid_out = Uuid::parse_string(orig_str).unwrap();
628 assert!(uuid_orig == uuid_out);
630 // Test error reporting
631 let e = Uuid::parse_string("67e5504410b1426f9247bb680e5fe0c").unwrap_err();
632 assert!(match e { ErrorInvalidLength(n) => n==31, _ => false });
634 let e = Uuid::parse_string("67e550X410b1426f9247bb680e5fe0cd").unwrap_err();
635 assert!(match e { ErrorInvalidCharacter(c, n) => c=='X' && n==6, _ => false });
637 let e = Uuid::parse_string("67e550-4105b1426f9247bb680e5fe0c").unwrap_err();
638 assert!(match e { ErrorInvalidGroups(n) => n==2, _ => false });
640 let e = Uuid::parse_string("F9168C5E-CEB2-4faa-B6BF1-02BF39FA1E4").unwrap_err();
641 assert!(match e { ErrorInvalidGroupLength(g, n, e) => g==3 && n==5 && e==4, _ => false });
645 fn test_to_simple_str() {
646 let uuid1 = Uuid::new_v4();
647 let s = uuid1.to_simple_str();
649 assert!(s.len() == 32);
650 assert!(s.chars().all(|c| c.is_digit_radix(16)));
655 let uuid1 = Uuid::new_v4();
656 let s = uuid1.to_str();
658 assert!(s.len() == 32);
659 assert!(s.chars().all(|c| c.is_digit_radix(16)));
663 fn test_to_hyphenated_str() {
664 let uuid1 = Uuid::new_v4();
665 let s = uuid1.to_hyphenated_str();
667 assert!(s.len() == 36);
668 assert!(s.chars().all(|c| c.is_digit_radix(16) || c == '-'));
672 fn test_to_urn_str() {
673 let uuid1 = Uuid::new_v4();
674 let ss = uuid1.to_urn_str();
675 let s = ss.slice(9, ss.len());
677 assert!(ss.starts_with("urn:uuid:"));
678 assert!(s.len() == 36);
679 assert!(s.chars().all(|c| c.is_digit_radix(16) || c == '-'));
683 fn test_to_str_matching() {
684 let uuid1 = Uuid::new_v4();
686 let hs = uuid1.to_hyphenated_str();
687 let ss = uuid1.to_str();
689 let hsn = str::from_chars(hs.chars()
690 .filter(|&c| c != '-')
691 .collect::<Vec<char>>()
698 fn test_string_roundtrip() {
699 let uuid = Uuid::new_v4();
701 let hs = uuid.to_hyphenated_str();
702 let uuid_hs = Uuid::parse_string(hs).unwrap();
703 assert!(uuid_hs == uuid);
705 let ss = uuid.to_str();
706 let uuid_ss = Uuid::parse_string(ss).unwrap();
707 assert!(uuid_ss == uuid);
712 let uuid1 = Uuid::new_v4();
713 let uuid2 = Uuid::new_v4();
715 assert!(uuid1 == uuid1);
716 assert!(uuid2 == uuid2);
717 assert!(uuid1 != uuid2);
718 assert!(uuid2 != uuid1);
722 fn test_from_fields() {
723 let d1: u32 = 0xa1a2a3a4;
724 let d2: u16 = 0xb1b2;
725 let d3: u16 = 0xc1c2;
726 let d4: Vec<u8> = vec!(0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8);
728 let u = Uuid::from_fields(d1, d2, d3, d4.as_slice());
730 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8".to_owned();
731 let result = u.to_simple_str();
732 assert!(result == expected);
736 fn test_from_bytes() {
737 let b = vec!( 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2,
738 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8 );
740 let u = Uuid::from_bytes(b.as_slice()).unwrap();
741 let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8".to_owned();
743 assert!(u.to_simple_str() == expected);
748 let u = Uuid::new_v4();
749 let ub = u.as_bytes();
751 assert!(ub.len() == 16);
752 assert!(! ub.iter().all(|&b| b == 0));
756 fn test_bytes_roundtrip() {
757 let b_in: [u8, ..16] = [ 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2,
758 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8 ];
760 let u = Uuid::from_bytes(b_in.clone()).unwrap();
762 let b_out = u.as_bytes();
764 assert!(b_in == b_out);
768 fn test_operator_eq() {
769 let u1 = Uuid::new_v4();
771 let u3 = Uuid::new_v4();
784 fn test_rand_rand() {
785 let mut rng = rand::task_rng();
786 let u: ~Uuid = rand::Rand::rand(&mut rng);
787 let ub = u.as_bytes();
789 assert!(ub.len() == 16);
790 assert!(! ub.iter().all(|&b| b == 0));
794 fn test_serialize_round_trip() {
796 use serialize::{Encodable, Decodable};
798 let u = Uuid::new_v4();
799 let mut wr = MemWriter::new();
800 let _ = u.encode(&mut ebml::writer::Encoder(&mut wr));
801 let doc = ebml::reader::Doc(wr.get_ref());
802 let u2 = Decodable::decode(&mut ebml::reader::Decoder(doc)).unwrap();
807 fn test_iterbytes_impl_for_uuid() {
808 use self::collections::HashSet;
809 let mut set = HashSet::new();
810 let id1 = Uuid::new_v4();
811 let id2 = Uuid::new_v4();
813 assert!(set.contains(&id1));
814 assert!(!set.contains(&id2));
821 use self::test::Bencher;
825 pub fn create_uuids(b: &mut Bencher) {
832 pub fn uuid_to_str(b: &mut Bencher) {
833 let u = Uuid::new_v4();
840 pub fn parse_str(b: &mut Bencher) {
841 let s = "urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4";
843 Uuid::parse_string(s).unwrap();