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.10-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 // NOTE remove the following two attributes after the next snapshot.
68 #[allow(unrecognized_lint)];
69 #[allow(default_type_param_usage)];
71 // test harness access
76 extern crate serialize;
78 use std::cast::{transmute,transmute_copy};
80 use std::default::Default;
82 use std::from_str::FromStr;
84 use std::num::FromStrRadix;
90 use serialize::{Encoder, Encodable, Decoder, Decodable};
92 /// A 128-bit (16 byte) buffer containing the ID
93 pub type UuidBytes = [u8, ..16];
95 /// The version of the UUID, denoting the generating algorithm
97 pub enum UuidVersion {
98 /// Version 1: MAC address
100 /// Version 2: DCE Security
102 /// Version 3: MD5 hash
104 /// Version 4: Random
106 /// Version 5: SHA-1 hash
110 /// The reserved variants of UUIDs
112 pub enum UuidVariant {
113 /// Reserved by the NCS for backward compatibility
115 /// As described in the RFC4122 Specification (default)
117 /// Reserved by Microsoft for backward compatibility
119 /// Reserved for future expansion
123 /// A Universally Unique Identifier (UUID)
125 /// The 128-bit number stored in 16 bytes
129 impl<S: Writer> Hash<S> for Uuid {
130 fn hash(&self, state: &mut S) {
131 self.bytes.hash(state)
135 /// A UUID stored as fields (identical to UUID, used only for conversions)
137 /// First field, 32-bit word
139 /// Second field, 16-bit short
141 /// Third field, 16-bit short
143 /// Fourth field, 8 bytes
147 /// Error details for string parsing failures
148 #[allow(missing_doc)]
149 pub enum ParseError {
150 ErrorInvalidLength(uint),
151 ErrorInvalidCharacter(char, uint),
152 ErrorInvalidGroups(uint),
153 ErrorInvalidGroupLength(uint, uint, uint),
156 /// Converts a ParseError to a string
157 impl fmt::Show for ParseError {
158 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
160 ErrorInvalidLength(found) =>
161 write!(f.buf, "Invalid length; expecting 32, 36 or 45 chars, \
163 ErrorInvalidCharacter(found, pos) =>
164 write!(f.buf, "Invalid character; found `{}` (0x{:02x}) at \
165 offset {}", found, found as uint, pos),
166 ErrorInvalidGroups(found) =>
167 write!(f.buf, "Malformed; wrong number of groups: expected 1 \
168 or 5, found {}", found),
169 ErrorInvalidGroupLength(group, found, expecting) =>
170 write!(f.buf, "Malformed; length of group {} was {}, \
171 expecting {}", group, found, expecting),
176 // Length of each hyphenated group in hex digits
177 static UuidGroupLens: [uint, ..5] = [8u, 4u, 4u, 4u, 12u];
181 /// Returns a nil or empty UUID (containing all zeroes)
182 pub fn nil() -> Uuid {
183 let uuid = Uuid{ bytes: [0, .. 16] };
187 /// Create a new UUID of the specified version
188 pub fn new(v: UuidVersion) -> Option<Uuid> {
190 Version4Random => Some(Uuid::new_v4()),
195 /// Creates a new random UUID
197 /// Uses the `rand` module's default RNG task as the source
198 /// of random numbers. Use the rand::Rand trait to supply
199 /// a custom generator if required.
200 pub fn new_v4() -> Uuid {
201 let ub = rand::task_rng().gen_vec(16);
202 let mut uuid = Uuid{ bytes: [0, .. 16] };
203 slice::bytes::copy_memory(uuid.bytes, ub);
204 uuid.set_variant(VariantRFC4122);
205 uuid.set_version(Version4Random);
209 /// Creates a UUID using the supplied field values
212 /// * `d1` A 32-bit word
213 /// * `d2` A 16-bit word
214 /// * `d3` A 16-bit word
215 /// * `d4` Array of 8 octets
216 pub fn from_fields(d1: u32, d2: u16, d3: u16, d4: &[u8]) -> Uuid {
217 use std::mem::{to_be16, to_be32};
219 // First construct a temporary field-based struct
220 let mut fields = UuidFields {
227 fields.data1 = to_be32(d1 as i32) as u32;
228 fields.data2 = to_be16(d2 as i16) as u16;
229 fields.data3 = to_be16(d3 as i16) as u16;
230 slice::bytes::copy_memory(fields.data4, d4);
237 /// Creates a UUID using the supplied bytes
240 /// * `b` An array or slice of 16 bytes
241 pub fn from_bytes(b: &[u8]) -> Option<Uuid> {
246 let mut uuid = Uuid{ bytes: [0, .. 16] };
247 slice::bytes::copy_memory(uuid.bytes, b);
251 /// Specifies the variant of the UUID structure
252 fn set_variant(&mut self, v: UuidVariant) {
253 // Octet 8 contains the variant in the most significant 3 bits
255 VariantNCS => // b0xx...
256 self.bytes[8] = self.bytes[8] & 0x7f,
257 VariantRFC4122 => // b10x...
258 self.bytes[8] = (self.bytes[8] & 0x3f) | 0x80,
259 VariantMicrosoft => // b110...
260 self.bytes[8] = (self.bytes[8] & 0x1f) | 0xc0,
261 VariantFuture => // b111...
262 self.bytes[8] = (self.bytes[8] & 0x1f) | 0xe0,
266 /// Returns the variant of the UUID structure
268 /// This determines the interpretation of the structure of the UUID.
269 /// Currently only the RFC4122 variant is generated by this module.
271 /// * [Variant Reference](http://tools.ietf.org/html/rfc4122#section-4.1.1)
272 pub fn get_variant(&self) -> Option<UuidVariant> {
273 if self.bytes[8] & 0x80 == 0x00 {
275 } else if self.bytes[8] & 0xc0 == 0x80 {
277 } else if self.bytes[8] & 0xe0 == 0xc0 {
278 Some(VariantMicrosoft)
279 } else if self.bytes[8] & 0xe0 == 0xe0 {
286 /// Specifies the version number of the UUID
287 fn set_version(&mut self, v: UuidVersion) {
288 self.bytes[6] = (self.bytes[6] & 0xF) | ((v as u8) << 4);
291 /// Returns the version number of the UUID
293 /// This represents the algorithm used to generate the contents.
295 /// Currently only the Random (V4) algorithm is supported by this
296 /// module. There are security and privacy implications for using
297 /// older versions - see [Wikipedia: Universally Unique Identifier](
298 /// http://en.wikipedia.org/wiki/Universally_unique_identifier) for
301 /// * [Version Reference](http://tools.ietf.org/html/rfc4122#section-4.1.3)
302 pub fn get_version_num(&self) -> uint {
303 (self.bytes[6] >> 4) as uint
306 /// Returns the version of the UUID
308 /// This represents the algorithm used to generate the contents
309 pub fn get_version(&self) -> Option<UuidVersion> {
310 let v = self.bytes[6] >> 4;
312 1 => Some(Version1Mac),
313 2 => Some(Version2Dce),
314 3 => Some(Version3Md5),
315 4 => Some(Version4Random),
316 5 => Some(Version5Sha1),
321 /// Return an array of 16 octets containing the UUID data
322 pub fn as_bytes<'a>(&'a self) -> &'a [u8] {
323 self.bytes.as_slice()
326 /// Returns the UUID as a string of 16 hexadecimal digits
328 /// Example: `936DA01F9ABD4d9d80C702AF85C822A8`
329 pub fn to_simple_str(&self) -> ~str {
330 let mut s: Vec<u8> = Vec::from_elem(32, 0u8);
331 for i in range(0u, 16u) {
332 let digit = format!("{:02x}", self.bytes[i] as uint);
333 *s.get_mut(i*2+0) = digit[0];
334 *s.get_mut(i*2+1) = digit[1];
336 str::from_utf8(s.as_slice()).unwrap().to_str()
339 /// Returns a string of hexadecimal digits, separated into groups with a hyphen.
341 /// Example: `550e8400-e29b-41d4-a716-446655440000`
342 pub fn to_hyphenated_str(&self) -> ~str {
343 use std::mem::{to_be16, to_be32};
344 // Convert to field-based struct as it matches groups in output.
345 // Ensure fields are in network byte order, as per RFC.
346 let mut uf: UuidFields;
348 uf = transmute_copy(&self.bytes);
350 uf.data1 = to_be32(uf.data1 as i32) as u32;
351 uf.data2 = to_be16(uf.data2 as i16) as u16;
352 uf.data3 = to_be16(uf.data3 as i16) as u16;
353 let s = format!("{:08x}-{:04x}-{:04x}-{:02x}{:02x}-\
354 {:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
357 uf.data4[0], uf.data4[1],
358 uf.data4[2], uf.data4[3], uf.data4[4],
359 uf.data4[5], uf.data4[6], uf.data4[7]);
363 /// Returns the UUID formatted as a full URN string
365 /// This is the same as the hyphenated format, but with the "urn:uuid:" prefix.
367 /// Example: `urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4`
368 pub fn to_urn_str(&self) -> ~str {
369 "urn:uuid:" + self.to_hyphenated_str()
372 /// Parses a UUID from a string of hexadecimal digits with optional hyphens
374 /// Any of the formats generated by this module (simple, hyphenated, urn) are
375 /// supported by this parsing function.
376 pub fn parse_string(us: &str) -> Result<Uuid, ParseError> {
378 let mut us = us.clone();
379 let orig_len = us.len();
381 // Ensure length is valid for any of the supported formats
382 if orig_len != 32 && orig_len != 36 && orig_len != 45 {
383 return Err(ErrorInvalidLength(orig_len));
386 // Strip off URN prefix if present
387 if us.starts_with("urn:uuid:") {
388 us = us.slice(9, orig_len);
391 // Make sure all chars are either hex digits or hyphen
392 for (i, c) in us.chars().enumerate() {
394 '0'..'9' | 'A'..'F' | 'a'..'f' | '-' => {},
395 _ => return Err(ErrorInvalidCharacter(c, i)),
399 // Split string up by hyphens into groups
400 let hex_groups: Vec<&str> = us.split_str("-").collect();
402 // Get the length of each group
403 let group_lens: Vec<uint> = hex_groups.iter().map(|&v| v.len()).collect();
405 // Ensure the group lengths are valid
406 match group_lens.len() {
407 // Single group, no hyphens
409 if *group_lens.get(0) != 32 {
410 return Err(ErrorInvalidLength(*group_lens.get(0)));
413 // Five groups, hyphens in between each
415 // Ensure each group length matches the expected
416 for (i, (&gl, &expected)) in
417 group_lens.iter().zip(UuidGroupLens.iter()).enumerate() {
419 return Err(ErrorInvalidGroupLength(i, gl, expected))
424 return Err(ErrorInvalidGroups(group_lens.len()));
428 // Normalise into one long hex string
429 let vs = hex_groups.concat();
431 // At this point, we know we have a valid hex string, without hyphens
432 assert!(vs.len() == 32);
433 assert!(vs.chars().all(|c| c.is_digit_radix(16)));
435 // Allocate output UUID buffer
436 let mut ub = [0u8, ..16];
438 // Extract each hex digit from the string
439 for i in range(0u, 16u) {
440 ub[i] = FromStrRadix::from_str_radix(vs.slice(i*2, (i+1)*2), 16).unwrap();
443 Ok(Uuid::from_bytes(ub).unwrap())
446 /// Tests if the UUID is nil
447 pub fn is_nil(&self) -> bool {
448 return self.bytes.iter().all(|&b| b == 0);
452 impl Default for Uuid {
453 /// Returns the nil UUID, which is all zeroes
454 fn default() -> Uuid {
459 impl Clone for Uuid {
460 /// Returns a copy of the UUID
461 fn clone(&self) -> Uuid { *self }
464 impl FromStr for Uuid {
465 /// Parse a hex string and interpret as a UUID
467 /// Accepted formats are a sequence of 32 hexadecimal characters,
468 /// with or without hypens (grouped as 8, 4, 4, 4, 12).
469 fn from_str(us: &str) -> Option<Uuid> {
470 let result = Uuid::parse_string(us);
478 /// Convert the UUID to a hexadecimal-based string representation
479 impl fmt::Show for Uuid {
480 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
481 write!(f.buf, "{}", self.to_simple_str())
485 /// Test two UUIDs for equality
487 /// UUIDs are equal only when they are byte-for-byte identical
489 fn eq(&self, other: &Uuid) -> bool {
490 self.bytes == other.bytes
494 /// Test two UUIDs for equality
496 /// UUIDs are equal only when they are byte-for-byte identical
497 impl TotalEq for Uuid {
498 fn equals(&self, other: &Uuid) -> bool {
499 self.bytes == other.bytes
503 // FIXME #9845: Test these more thoroughly
504 impl<T: Encoder> Encodable<T> for Uuid {
505 /// Encode a UUID as a hypenated string
506 fn encode(&self, e: &mut T) {
507 e.emit_str(self.to_hyphenated_str());
511 impl<T: Decoder> Decodable<T> for Uuid {
512 /// Decode a UUID from a string
513 fn decode(d: &mut T) -> Uuid {
514 from_str(d.read_str()).unwrap()
518 /// Generates a random instance of UUID (V4 conformant)
519 impl rand::Rand for Uuid {
521 fn rand<R: rand::Rng>(rng: &mut R) -> Uuid {
522 let ub = rng.gen_vec(16);
523 let mut uuid = Uuid{ bytes: [0, .. 16] };
524 slice::bytes::copy_memory(uuid.bytes, ub);
525 uuid.set_variant(VariantRFC4122);
526 uuid.set_version(Version4Random);
533 extern crate collections;
536 use super::{Uuid, VariantMicrosoft, VariantNCS, VariantRFC4122,
537 Version1Mac, Version2Dce, Version3Md5, Version4Random,
540 use std::io::MemWriter;
544 let nil = Uuid::nil();
545 let not_nil = Uuid::new_v4();
547 assert!(nil.is_nil());
548 assert!(!not_nil.is_nil());
554 let uuid1 = Uuid::new(Version4Random).unwrap();
555 let s = uuid1.to_simple_str();
557 assert!(s.len() == 32);
558 assert!(uuid1.get_version().unwrap() == Version4Random);
560 // Test unsupported versions
561 assert!(Uuid::new(Version1Mac) == None);
562 assert!(Uuid::new(Version2Dce) == None);
563 assert!(Uuid::new(Version3Md5) == None);
564 assert!(Uuid::new(Version5Sha1) == None);
569 let uuid1 = Uuid::new_v4();
571 assert!(uuid1.get_version().unwrap() == Version4Random);
572 assert!(uuid1.get_variant().unwrap() == VariantRFC4122);
576 fn test_get_version() {
577 let uuid1 = Uuid::new_v4();
579 assert!(uuid1.get_version().unwrap() == Version4Random);
580 assert!(uuid1.get_version_num() == 4);
584 fn test_get_variant() {
585 let uuid1 = Uuid::new_v4();
586 let uuid2 = Uuid::parse_string("550e8400-e29b-41d4-a716-446655440000").unwrap();
587 let uuid3 = Uuid::parse_string("67e55044-10b1-426f-9247-bb680e5fe0c8").unwrap();
588 let uuid4 = Uuid::parse_string("936DA01F9ABD4d9dC0C702AF85C822A8").unwrap();
589 let uuid5 = Uuid::parse_string("F9168C5E-CEB2-4faa-D6BF-329BF39FA1E4").unwrap();
590 let uuid6 = Uuid::parse_string("f81d4fae-7dec-11d0-7765-00a0c91e6bf6").unwrap();
592 assert!(uuid1.get_variant().unwrap() == VariantRFC4122);
593 assert!(uuid2.get_variant().unwrap() == VariantRFC4122);
594 assert!(uuid3.get_variant().unwrap() == VariantRFC4122);
595 assert!(uuid4.get_variant().unwrap() == VariantMicrosoft);
596 assert!(uuid5.get_variant().unwrap() == VariantMicrosoft);
597 assert!(uuid6.get_variant().unwrap() == VariantNCS);
601 fn test_parse_uuid_v4() {
602 use super::{ErrorInvalidCharacter, ErrorInvalidGroups,
603 ErrorInvalidGroupLength, ErrorInvalidLength};
606 assert!(Uuid::parse_string("").is_err());
607 assert!(Uuid::parse_string("!").is_err());
608 assert!(Uuid::parse_string("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E45").is_err());
609 assert!(Uuid::parse_string("F9168C5E-CEB2-4faa-BBF-329BF39FA1E4").is_err());
610 assert!(Uuid::parse_string("F9168C5E-CEB2-4faa-BGBF-329BF39FA1E4").is_err());
611 assert!(Uuid::parse_string("F9168C5E-CEB2-4faa-B6BFF329BF39FA1E4").is_err());
612 assert!(Uuid::parse_string("F9168C5E-CEB2-4faa").is_err());
613 assert!(Uuid::parse_string("F9168C5E-CEB2-4faaXB6BFF329BF39FA1E4").is_err());
614 assert!(Uuid::parse_string("F9168C5E-CEB-24fa-eB6BFF32-BF39FA1E4").is_err());
615 assert!(Uuid::parse_string("01020304-1112-2122-3132-41424344").is_err());
616 assert!(Uuid::parse_string("67e5504410b1426f9247bb680e5fe0c").is_err());
617 assert!(Uuid::parse_string("67e5504410b1426f9247bb680e5fe0c88").is_err());
618 assert!(Uuid::parse_string("67e5504410b1426f9247bb680e5fe0cg8").is_err());
619 assert!(Uuid::parse_string("67e5504410b1426%9247bb680e5fe0c8").is_err());
622 assert!(Uuid::parse_string("00000000000000000000000000000000").is_ok());
623 assert!(Uuid::parse_string("67e55044-10b1-426f-9247-bb680e5fe0c8").is_ok());
624 assert!(Uuid::parse_string("67e55044-10b1-426f-9247-bb680e5fe0c8").is_ok());
625 assert!(Uuid::parse_string("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4").is_ok());
626 assert!(Uuid::parse_string("67e5504410b1426f9247bb680e5fe0c8").is_ok());
627 assert!(Uuid::parse_string("01020304-1112-2122-3132-414243444546").is_ok());
628 assert!(Uuid::parse_string("urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8").is_ok());
631 let nil = Uuid::nil();
632 assert!(Uuid::parse_string("00000000000000000000000000000000").unwrap() == nil);
633 assert!(Uuid::parse_string("00000000-0000-0000-0000-000000000000").unwrap() == nil);
636 let uuid_orig = Uuid::new_v4();
637 let orig_str = uuid_orig.to_str();
638 let uuid_out = Uuid::parse_string(orig_str).unwrap();
639 assert!(uuid_orig == uuid_out);
641 // Test error reporting
642 let e = Uuid::parse_string("67e5504410b1426f9247bb680e5fe0c").unwrap_err();
643 assert!(match e { ErrorInvalidLength(n) => n==31, _ => false });
645 let e = Uuid::parse_string("67e550X410b1426f9247bb680e5fe0cd").unwrap_err();
646 assert!(match e { ErrorInvalidCharacter(c, n) => c=='X' && n==6, _ => false });
648 let e = Uuid::parse_string("67e550-4105b1426f9247bb680e5fe0c").unwrap_err();
649 assert!(match e { ErrorInvalidGroups(n) => n==2, _ => false });
651 let e = Uuid::parse_string("F9168C5E-CEB2-4faa-B6BF1-02BF39FA1E4").unwrap_err();
652 assert!(match e { ErrorInvalidGroupLength(g, n, e) => g==3 && n==5 && e==4, _ => false });
656 fn test_to_simple_str() {
657 let uuid1 = Uuid::new_v4();
658 let s = uuid1.to_simple_str();
660 assert!(s.len() == 32);
661 assert!(s.chars().all(|c| c.is_digit_radix(16)));
666 let uuid1 = Uuid::new_v4();
667 let s = uuid1.to_str();
669 assert!(s.len() == 32);
670 assert!(s.chars().all(|c| c.is_digit_radix(16)));
674 fn test_to_hyphenated_str() {
675 let uuid1 = Uuid::new_v4();
676 let s = uuid1.to_hyphenated_str();
678 assert!(s.len() == 36);
679 assert!(s.chars().all(|c| c.is_digit_radix(16) || c == '-'));
683 fn test_to_urn_str() {
684 let uuid1 = Uuid::new_v4();
685 let ss = uuid1.to_urn_str();
686 let s = ss.slice(9, ss.len());
688 assert!(ss.starts_with("urn:uuid:"));
689 assert!(s.len() == 36);
690 assert!(s.chars().all(|c| c.is_digit_radix(16) || c == '-'));
694 fn test_to_str_matching() {
695 let uuid1 = Uuid::new_v4();
697 let hs = uuid1.to_hyphenated_str();
698 let ss = uuid1.to_str();
700 let hsn = str::from_chars(hs.chars()
701 .filter(|&c| c != '-')
702 .collect::<Vec<char>>()
709 fn test_string_roundtrip() {
710 let uuid = Uuid::new_v4();
712 let hs = uuid.to_hyphenated_str();
713 let uuid_hs = Uuid::parse_string(hs).unwrap();
714 assert!(uuid_hs == uuid);
716 let ss = uuid.to_str();
717 let uuid_ss = Uuid::parse_string(ss).unwrap();
718 assert!(uuid_ss == uuid);
723 let uuid1 = Uuid::new_v4();
724 let uuid2 = Uuid::new_v4();
726 assert!(uuid1 == uuid1);
727 assert!(uuid2 == uuid2);
728 assert!(uuid1 != uuid2);
729 assert!(uuid2 != uuid1);
733 fn test_from_fields() {
734 let d1: u32 = 0xa1a2a3a4;
735 let d2: u16 = 0xb1b2;
736 let d3: u16 = 0xc1c2;
737 let d4: Vec<u8> = vec!(0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8);
739 let u = Uuid::from_fields(d1, d2, d3, d4.as_slice());
741 let expected = ~"a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
742 let result = u.to_simple_str();
743 assert!(result == expected);
747 fn test_from_bytes() {
748 let b = vec!( 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2,
749 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8 );
751 let u = Uuid::from_bytes(b.as_slice()).unwrap();
752 let expected = ~"a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
754 assert!(u.to_simple_str() == expected);
759 let u = Uuid::new_v4();
760 let ub = u.as_bytes();
762 assert!(ub.len() == 16);
763 assert!(! ub.iter().all(|&b| b == 0));
767 fn test_bytes_roundtrip() {
768 let b_in: [u8, ..16] = [ 0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2,
769 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8 ];
771 let u = Uuid::from_bytes(b_in.clone()).unwrap();
773 let b_out = u.as_bytes();
775 assert!(b_in == b_out);
779 fn test_operator_eq() {
780 let u1 = Uuid::new_v4();
782 let u3 = Uuid::new_v4();
795 fn test_rand_rand() {
796 let mut rng = rand::task_rng();
797 let u: ~Uuid = rand::Rand::rand(&mut rng);
798 let ub = u.as_bytes();
800 assert!(ub.len() == 16);
801 assert!(! ub.iter().all(|&b| b == 0));
805 fn test_serialize_round_trip() {
807 use serialize::{Encodable, Decodable};
809 let u = Uuid::new_v4();
810 let mut wr = MemWriter::new();
811 u.encode(&mut ebml::writer::Encoder(&mut wr));
812 let doc = ebml::reader::Doc(wr.get_ref());
813 let u2 = Decodable::decode(&mut ebml::reader::Decoder(doc));
818 fn test_iterbytes_impl_for_uuid() {
819 use self::collections::HashSet;
820 let mut set = HashSet::new();
821 let id1 = Uuid::new_v4();
822 let id2 = Uuid::new_v4();
824 assert!(set.contains(&id1));
825 assert!(!set.contains(&id2));
832 use self::test::BenchHarness;
836 pub fn create_uuids(bh: &mut BenchHarness) {
843 pub fn uuid_to_str(bh: &mut BenchHarness) {
844 let u = Uuid::new_v4();
851 pub fn parse_str(bh: &mut BenchHarness) {
852 let s = "urn:uuid:F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4";
854 Uuid::parse_string(s).unwrap();