#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "https://www.rust-lang.org/favicon.ico",
html_root_url = "https://doc.rust-lang.org/uuid/")]
#![deny(warnings)]
#![no_std]
#[cfg(feature = "v4")]
extern crate rand;
#[cfg(feature = "v5")]
extern crate sha1;
use core::fmt;
use core::hash;
use core::str::FromStr;
#[cfg(any(feature = "use_std",
feature = "rustc-serialize",
feature = "serde"))]
mod std_support;
#[cfg(feature = "rustc-serialize")]
mod rustc_serialize;
#[cfg(feature = "serde")]
mod serde;
#[cfg(feature = "v4")]
use rand::Rng;
#[cfg(feature = "v5")]
use sha1::Sha1;
pub type UuidBytes = [u8; 16];
#[derive(PartialEq, Copy, Clone)]
pub enum UuidVersion {
Mac = 1,
Dce = 2,
Md5 = 3,
Random = 4,
Sha1 = 5,
}
#[derive(PartialEq, Copy, Clone)]
pub enum UuidVariant {
NCS,
RFC4122,
Microsoft,
Future,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Uuid {
bytes: UuidBytes,
}
pub struct Simple<'a> {
inner: &'a Uuid,
}
pub struct Hyphenated<'a> {
inner: &'a Uuid,
}
pub const NAMESPACE_DNS: Uuid = Uuid {
bytes: [0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1,
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8]
};
pub const NAMESPACE_URL: Uuid = Uuid {
bytes: [0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1,
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8]
};
pub const NAMESPACE_OID: Uuid = Uuid {
bytes: [0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1,
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8]
};
pub const NAMESPACE_X500: Uuid = Uuid {
bytes: [0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1,
0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8]
};
pub struct Urn<'a> {
inner: &'a Uuid,
}
#[allow(missing_docs)]
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
pub enum ParseError {
InvalidLength(usize),
InvalidCharacter(char, usize),
InvalidGroups(usize),
InvalidGroupLength(usize, usize, u8),
}
const SIMPLE_LENGTH: usize = 32;
const HYPHENATED_LENGTH: usize = 36;
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
ParseError::InvalidLength(found) => {
write!(f,
"Invalid length; expecting {} or {} chars, found {}",
SIMPLE_LENGTH, HYPHENATED_LENGTH, found)
}
ParseError::InvalidCharacter(found, pos) => {
write!(f,
"Invalid character; found `{}` (0x{:02x}) at offset {}",
found,
found as usize,
pos)
}
ParseError::InvalidGroups(found) => {
write!(f,
"Malformed; wrong number of groups: expected 1 or 5, found {}",
found)
}
ParseError::InvalidGroupLength(group, found, expecting) => {
write!(f,
"Malformed; length of group {} was {}, expecting {}",
group,
found,
expecting)
}
}
}
}
const GROUP_LENS: [u8; 5] = [8, 4, 4, 4, 12];
const ACC_GROUP_LENS: [u8; 5] = [8, 12, 16, 20, 32];
impl Uuid {
pub fn nil() -> Uuid {
Uuid { bytes: [0; 16] }
}
pub fn new(v: UuidVersion) -> Option<Uuid> {
match v {
#[cfg(feature = "v4")]
UuidVersion::Random => Some(Uuid::new_v4()),
_ => None,
}
}
#[cfg(feature = "v4")]
pub fn new_v4() -> Uuid {
rand::thread_rng().gen()
}
#[cfg(feature = "v5")]
pub fn new_v5(namespace: &Uuid, name: &str) -> Uuid {
let mut hash = Sha1::new();
hash.update(namespace.as_bytes());
hash.update(name.as_bytes());
let buffer = hash.digest().bytes();
let mut uuid = Uuid { bytes: [0; 16] };
copy_memory(&mut uuid.bytes, &buffer[..16]);
uuid.set_variant(UuidVariant::RFC4122);
uuid.set_version(UuidVersion::Sha1);
uuid
}
pub fn from_fields(d1: u32,
d2: u16,
d3: u16,
d4: &[u8]) -> Result<Uuid, ParseError> {
if d4.len() != 8 {
return Err(ParseError::InvalidLength(d4.len()))
}
Ok(Uuid {
bytes: [
(d1 >> 24) as u8,
(d1 >> 16) as u8,
(d1 >> 8) as u8,
(d1 >> 0) as u8,
(d2 >> 8) as u8,
(d2 >> 0) as u8,
(d3 >> 8) as u8,
(d3 >> 0) as u8,
d4[0], d4[1], d4[2], d4[3], d4[4], d4[5], d4[6], d4[7]
],
})
}
pub fn from_bytes(b: &[u8]) -> Result<Uuid, ParseError> {
let len = b.len();
if len != 16 {
return Err(ParseError::InvalidLength(len));
}
let mut uuid = Uuid { bytes: [0; 16] };
copy_memory(&mut uuid.bytes, b);
Ok(uuid)
}
#[allow(dead_code)]
fn set_variant(&mut self, v: UuidVariant) {
self.bytes[8] = match v {
UuidVariant::NCS => self.bytes[8] & 0x7f, UuidVariant::RFC4122 => (self.bytes[8] & 0x3f) | 0x80, UuidVariant::Microsoft => (self.bytes[8] & 0x1f) | 0xc0, UuidVariant::Future => (self.bytes[8] & 0x1f) | 0xe0, }
}
pub fn get_variant(&self) -> Option<UuidVariant> {
match self.bytes[8] {
x if x & 0x80 == 0x00 => Some(UuidVariant::NCS),
x if x & 0xc0 == 0x80 => Some(UuidVariant::RFC4122),
x if x & 0xe0 == 0xc0 => Some(UuidVariant::Microsoft),
x if x & 0xe0 == 0xe0 => Some(UuidVariant::Future),
_ => None,
}
}
#[allow(dead_code)]
fn set_version(&mut self, v: UuidVersion) {
self.bytes[6] = (self.bytes[6] & 0xF) | ((v as u8) << 4);
}
pub fn get_version_num(&self) -> usize {
(self.bytes[6] >> 4) as usize
}
pub fn get_version(&self) -> Option<UuidVersion> {
let v = self.bytes[6] >> 4;
match v {
1 => Some(UuidVersion::Mac),
2 => Some(UuidVersion::Dce),
3 => Some(UuidVersion::Md5),
4 => Some(UuidVersion::Random),
5 => Some(UuidVersion::Sha1),
_ => None,
}
}
pub fn as_bytes(&self) -> &[u8; 16] {
&self.bytes
}
pub fn simple(&self) -> Simple {
Simple { inner: self }
}
pub fn hyphenated(&self) -> Hyphenated {
Hyphenated { inner: self }
}
pub fn urn(&self) -> Urn {
Urn { inner: self }
}
pub fn parse_str(mut input: &str) -> Result<Uuid, ParseError> {
let len = input.len();
if len == (HYPHENATED_LENGTH + 9) && input.starts_with("urn:uuid:") {
input = &input[9..];
} else if len != SIMPLE_LENGTH && len != HYPHENATED_LENGTH {
return Err(ParseError::InvalidLength(len));
}
let mut digit = 0;
let mut group = 0;
let mut acc = 0;
let mut buffer = [0u8; 16];
for (i_char, chr) in input.chars().enumerate() {
if digit as usize >= SIMPLE_LENGTH && group == 0 {
return Err(ParseError::InvalidLength(len));
}
if digit % 2 == 0 {
match chr {
'0'...'9' => acc = chr as u8 - '0' as u8,
'a'...'f' => acc = chr as u8 - 'a' as u8 + 10,
'A'...'F' => acc = chr as u8 - 'A' as u8 + 10,
'-' => {
if ACC_GROUP_LENS[group] != digit {
let found = if group > 0 {
digit - ACC_GROUP_LENS[group - 1]
} else {
digit
};
return Err(ParseError::InvalidGroupLength(group,
found as usize,
GROUP_LENS[group]));
}
group += 1;
digit -= 1;
}
_ => return Err(ParseError::InvalidCharacter(chr, i_char)),
}
} else {
acc *= 16;
match chr {
'0'...'9' => acc += chr as u8 - '0' as u8,
'a'...'f' => acc += chr as u8 - 'a' as u8 + 10,
'A'...'F' => acc += chr as u8 - 'A' as u8 + 10,
'-' => {
let found = if group > 0 {
digit - ACC_GROUP_LENS[group - 1]
} else {
digit
};
return Err(ParseError::InvalidGroupLength(group,
found as usize,
GROUP_LENS[group]));
}
_ => return Err(ParseError::InvalidCharacter(chr, i_char)),
}
buffer[(digit / 2) as usize] = acc;
}
digit += 1;
}
if group != 0 && group != 4 {
return Err(ParseError::InvalidGroups(group + 1));
} else if ACC_GROUP_LENS[4] != digit {
return Err(ParseError::InvalidGroupLength(group,
(digit - ACC_GROUP_LENS[3]) as usize,
GROUP_LENS[4]));
}
Ok(Uuid::from_bytes(&mut buffer).unwrap())
}
pub fn is_nil(&self) -> bool {
self.bytes.iter().all(|&b| b == 0)
}
}
fn copy_memory(dst: &mut [u8], src: &[u8]) {
for (slot, val) in dst.iter_mut().zip(src.iter()) {
*slot = *val;
}
}
impl Default for Uuid {
fn default() -> Uuid {
Uuid::nil()
}
}
impl FromStr for Uuid {
type Err = ParseError;
fn from_str(us: &str) -> Result<Uuid, ParseError> {
Uuid::parse_str(us)
}
}
impl fmt::Debug for Uuid {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Uuid(\"{}\")", self.hyphenated())
}
}
impl fmt::Display for Uuid {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.hyphenated().fmt(f)
}
}
impl hash::Hash for Uuid {
fn hash<S: hash::Hasher>(&self, state: &mut S) {
self.bytes.hash(state)
}
}
impl<'a> fmt::Display for Simple<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for byte in self.inner.bytes.iter() {
try!(write!(f, "{:02x}", byte));
}
Ok(())
}
}
impl<'a> fmt::Display for Hyphenated<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let data1 = ((self.inner.bytes[0] as u32) << 24) |
((self.inner.bytes[1] as u32) << 16) |
((self.inner.bytes[2] as u32) << 8) |
((self.inner.bytes[3] as u32) << 0);
let data2 = ((self.inner.bytes[4] as u16) << 8) |
((self.inner.bytes[5] as u16) << 0);
let data3 = ((self.inner.bytes[6] as u16) << 8) |
((self.inner.bytes[7] as u16) << 0);
write!(f, "{:08x}-\
{:04x}-\
{:04x}-\
{:02x}{:02x}-\
{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}",
data1,
data2,
data3,
self.inner.bytes[8],
self.inner.bytes[9],
self.inner.bytes[10],
self.inner.bytes[11],
self.inner.bytes[12],
self.inner.bytes[13],
self.inner.bytes[14],
self.inner.bytes[15])
}
}
impl<'a> fmt::Display for Urn<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "urn:uuid:{}", self.inner.hyphenated())
}
}
#[cfg(feature = "v4")]
impl rand::Rand for Uuid {
fn rand<R: rand::Rng>(rng: &mut R) -> Uuid {
let mut uuid = Uuid { bytes: [0; 16] };
rng.fill_bytes(&mut uuid.bytes);
uuid.set_variant(UuidVariant::RFC4122);
uuid.set_version(UuidVersion::Random);
uuid
}
}
#[cfg(test)]
mod tests {
extern crate std;
use self::std::prelude::v1::*;
use super::{NAMESPACE_DNS, NAMESPACE_URL, NAMESPACE_OID, NAMESPACE_X500};
use super::{Uuid, UuidVariant, UuidVersion};
#[cfg(feature = "v4")]
use rand;
fn new() -> Uuid {
Uuid::parse_str("F9168C5E-CEB2-4FAA-B6BF-329BF39FA1E4").unwrap()
}
fn new2() -> Uuid {
Uuid::parse_str("F9168C5E-CEB2-4FAB-B6BF-329BF39FA1E4").unwrap()
}
#[cfg(feature = "v5")]
static FIXTURE_V5: &'static [(&'static Uuid, &'static str, &'static str)] = &[
(&NAMESPACE_DNS, "example.org", "aad03681-8b63-5304-89e0-8ca8f49461b5"),
(&NAMESPACE_DNS, "rust-lang.org", "c66bbb60-d62e-5f17-a399-3a0bd237c503"),
(&NAMESPACE_DNS, "42", "7c411b5e-9d3f-50b5-9c28-62096e41c4ed"),
(&NAMESPACE_DNS, "lorem ipsum", "97886a05-8a68-5743-ad55-56ab2d61cf7b"),
(&NAMESPACE_URL, "example.org", "54a35416-963c-5dd6-a1e2-5ab7bb5bafc7"),
(&NAMESPACE_URL, "rust-lang.org", "c48d927f-4122-5413-968c-598b1780e749"),
(&NAMESPACE_URL, "42", "5c2b23de-4bad-58ee-a4b3-f22f3b9cfd7d"),
(&NAMESPACE_URL, "lorem ipsum", "15c67689-4b85-5253-86b4-49fbb138569f"),
(&NAMESPACE_OID, "example.org", "34784df9-b065-5094-92c7-00bb3da97a30"),
(&NAMESPACE_OID, "rust-lang.org", "8ef61ecb-977a-5844-ab0f-c25ef9b8d5d6"),
(&NAMESPACE_OID, "42", "ba293c61-ad33-57b9-9671-f3319f57d789"),
(&NAMESPACE_OID, "lorem ipsum", "6485290d-f79e-5380-9e64-cb4312c7b4a6"),
(&NAMESPACE_X500, "example.org", "e3635e86-f82b-5bbc-a54a-da97923e5c76"),
(&NAMESPACE_X500, "rust-lang.org", "26c9c3e9-49b7-56da-8b9f-a0fb916a71a3"),
(&NAMESPACE_X500, "42", "e4b88014-47c6-5fe0-a195-13710e5f6e27"),
(&NAMESPACE_X500, "lorem ipsum", "b11f79a5-1e6d-57ce-a4b5-ba8531ea03d0"),
];
#[test]
fn test_nil() {
let nil = Uuid::nil();
let not_nil = new();
assert!(nil.is_nil());
assert!(!not_nil.is_nil());
}
#[test]
fn test_new() {
if cfg!(feature = "v4") {
let uuid1 = Uuid::new(UuidVersion::Random).unwrap();
let s = uuid1.simple().to_string();
assert!(s.len() == 32);
assert!(uuid1.get_version().unwrap() == UuidVersion::Random);
} else {
assert!(Uuid::new(UuidVersion::Random).is_none());
}
assert!(Uuid::new(UuidVersion::Mac) == None);
assert!(Uuid::new(UuidVersion::Dce) == None);
assert!(Uuid::new(UuidVersion::Md5) == None);
assert!(Uuid::new(UuidVersion::Sha1) == None);
}
#[test]
#[cfg(feature = "v4")]
fn test_new_v4() {
let uuid1 = Uuid::new_v4();
assert!(uuid1.get_version().unwrap() == UuidVersion::Random);
assert!(uuid1.get_variant().unwrap() == UuidVariant::RFC4122);
}
#[cfg(feature = "v5")]
#[test]
fn test_new_v5() {
for &(ref ns, ref name, _) in FIXTURE_V5 {
let uuid = Uuid::new_v5(*ns, *name);
assert!(uuid.get_version().unwrap() == UuidVersion::Sha1);
assert!(uuid.get_variant().unwrap() == UuidVariant::RFC4122);
}
}
#[test]
fn test_predefined_namespaces() {
assert_eq!(NAMESPACE_DNS.hyphenated().to_string(),
"6ba7b810-9dad-11d1-80b4-00c04fd430c8");
assert_eq!(NAMESPACE_URL.hyphenated().to_string(),
"6ba7b811-9dad-11d1-80b4-00c04fd430c8");
assert_eq!(NAMESPACE_OID.hyphenated().to_string(),
"6ba7b812-9dad-11d1-80b4-00c04fd430c8");
assert_eq!(NAMESPACE_X500.hyphenated().to_string(),
"6ba7b814-9dad-11d1-80b4-00c04fd430c8");
}
#[test]
#[cfg(feature = "v4")]
fn test_get_version_v4() {
let uuid1 = Uuid::new_v4();
assert!(uuid1.get_version().unwrap() == UuidVersion::Random);
assert_eq!(uuid1.get_version_num(), 4);
}
#[cfg(feature = "v5")]
#[test]
fn test_get_version_v5() {
let uuid2 = Uuid::new_v5(&NAMESPACE_DNS, "rust-lang.org");
assert!(uuid2.get_version().unwrap() == UuidVersion::Sha1);
assert_eq!(uuid2.get_version_num(), 5);
}
#[test]
fn test_get_variant() {
let uuid1 = new();
let uuid2 = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
let uuid3 = Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8").unwrap();
let uuid4 = Uuid::parse_str("936DA01F9ABD4d9dC0C702AF85C822A8").unwrap();
let uuid5 = Uuid::parse_str("F9168C5E-CEB2-4faa-D6BF-329BF39FA1E4").unwrap();
let uuid6 = Uuid::parse_str("f81d4fae-7dec-11d0-7765-00a0c91e6bf6").unwrap();
assert!(uuid1.get_variant().unwrap() == UuidVariant::RFC4122);
assert!(uuid2.get_variant().unwrap() == UuidVariant::RFC4122);
assert!(uuid3.get_variant().unwrap() == UuidVariant::RFC4122);
assert!(uuid4.get_variant().unwrap() == UuidVariant::Microsoft);
assert!(uuid5.get_variant().unwrap() == UuidVariant::Microsoft);
assert!(uuid6.get_variant().unwrap() == UuidVariant::NCS);
}
#[test]
fn test_parse_uuid_v4() {
use super::ParseError::*;
assert_eq!(Uuid::parse_str(""), Err(InvalidLength(0)));
assert_eq!(Uuid::parse_str("!"), Err(InvalidLength(1)));
assert_eq!(Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E45"),
Err(InvalidLength(37)));
assert_eq!(Uuid::parse_str("F9168C5E-CEB2-4faa-BBF-329BF39FA1E4"),
Err(InvalidLength(35)));
assert_eq!(Uuid::parse_str("F9168C5E-CEB2-4faa-BGBF-329BF39FA1E4"),
Err(InvalidCharacter('G', 20)));
assert_eq!(Uuid::parse_str("F9168C5E-CEB2-4faa-B6BFF329BF39FA1E4"),
Err(InvalidGroups(4)));
assert_eq!(Uuid::parse_str("F9168C5E-CEB2-4faa"),
Err(InvalidLength(18)));
assert_eq!(Uuid::parse_str("F9168C5E-CEB2-4faaXB6BFF329BF39FA1E4"),
Err(InvalidCharacter('X', 18)));
assert_eq!(Uuid::parse_str("F9168C5E-CEB-24fa-eB6BFF32-BF39FA1E4"),
Err(InvalidGroupLength(1, 3, 4)));
assert_eq!(Uuid::parse_str("01020304-1112-2122-3132-41424344"),
Err(InvalidGroupLength(4, 8, 12)));
assert_eq!(Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c"),
Err(InvalidLength(31)));
assert_eq!(Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c88"),
Err(InvalidLength(33)));
assert_eq!(Uuid::parse_str("67e5504410b1426f9247bb680e5fe0cg8"),
Err(InvalidLength(33)));
assert_eq!(Uuid::parse_str("67e5504410b1426%9247bb680e5fe0c8"),
Err(InvalidCharacter('%', 15)));
assert_eq!(Uuid::parse_str("231231212212423424324323477343246663"),
Err(InvalidLength(36)));
assert!(Uuid::parse_str("00000000000000000000000000000000").is_ok());
assert!(Uuid::parse_str("67e55044-10b1-426f-9247-bb680e5fe0c8").is_ok());
assert!(Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4").is_ok());
assert!(Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c8").is_ok());
assert!(Uuid::parse_str("01020304-1112-2122-3132-414243444546").is_ok());
assert!(Uuid::parse_str("urn:uuid:67e55044-10b1-426f-9247-bb680e5fe0c8").is_ok());
let nil = Uuid::nil();
assert!(Uuid::parse_str("00000000000000000000000000000000").unwrap() == nil);
assert!(Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap() == nil);
let uuid_orig = new();
let orig_str = uuid_orig.to_string();
let uuid_out = Uuid::parse_str(&orig_str).unwrap();
assert!(uuid_orig == uuid_out);
assert_eq!(Uuid::parse_str("67e5504410b1426f9247bb680e5fe0c"),
Err(InvalidLength(31)));
assert_eq!(Uuid::parse_str("67e550X410b1426f9247bb680e5fe0cd"),
Err(InvalidCharacter('X', 6)));
assert_eq!(Uuid::parse_str("67e550-4105b1426f9247bb680e5fe0c"),
Err(InvalidGroupLength(0, 6, 8)));
assert_eq!(Uuid::parse_str("F9168C5E-CEB2-4faa-B6BF1-02BF39FA1E4"),
Err(InvalidGroupLength(3, 5, 4)));
}
#[test]
fn test_to_simple_string() {
let uuid1 = new();
let s = uuid1.simple().to_string();
assert!(s.len() == 32);
assert!(s.chars().all(|c| c.is_digit(16)));
}
#[test]
fn test_to_string() {
let uuid1 = new();
let s = uuid1.to_string();
assert!(s.len() == 36);
assert!(s.chars().all(|c| c.is_digit(16) || c == '-'));
}
#[test]
fn test_display() {
let uuid1 = new();
let s = uuid1.to_string();
assert_eq!(s, uuid1.hyphenated().to_string());
}
#[test]
fn test_to_hyphenated_string() {
let uuid1 = new();
let s = uuid1.hyphenated().to_string();
assert!(s.len() == 36);
assert!(s.chars().all(|c| c.is_digit(16) || c == '-'));
}
#[cfg(feature = "v5")]
#[test]
fn test_v5_to_hypenated_string() {
for &(ref ns, ref name, ref expected) in FIXTURE_V5 {
let uuid = Uuid::new_v5(*ns, *name);
assert_eq!(uuid.hyphenated().to_string(), *expected);
}
}
#[test]
fn test_to_urn_string() {
let uuid1 = new();
let ss = uuid1.urn().to_string();
let s = &ss[9..];
assert!(ss.starts_with("urn:uuid:"));
assert!(s.len() == 36);
assert!(s.chars().all(|c| c.is_digit(16) || c == '-'));
}
#[test]
fn test_to_simple_string_matching() {
let uuid1 = new();
let hs = uuid1.hyphenated().to_string();
let ss = uuid1.simple().to_string();
let hsn = hs.chars().filter(|&c| c != '-').collect::<String>();
assert!(hsn == ss);
}
#[test]
fn test_string_roundtrip() {
let uuid = new();
let hs = uuid.hyphenated().to_string();
let uuid_hs = Uuid::parse_str(&hs).unwrap();
assert_eq!(uuid_hs, uuid);
let ss = uuid.to_string();
let uuid_ss = Uuid::parse_str(&ss).unwrap();
assert_eq!(uuid_ss, uuid);
}
#[test]
fn test_compare() {
let uuid1 = new();
let uuid2 = new2();
assert!(uuid1 == uuid1);
assert!(uuid2 == uuid2);
assert!(uuid1 != uuid2);
assert!(uuid2 != uuid1);
}
#[test]
fn test_from_fields() {
let d1: u32 = 0xa1a2a3a4;
let d2: u16 = 0xb1b2;
let d3: u16 = 0xc1c2;
let d4 = [0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
let u = Uuid::from_fields(d1, d2, d3, &d4).unwrap();
let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
let result = u.simple().to_string();
assert_eq!(result, expected);
}
#[test]
fn test_from_bytes() {
let b = [0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2,
0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
let u = Uuid::from_bytes(&b).unwrap();
let expected = "a1a2a3a4b1b2c1c2d1d2d3d4d5d6d7d8";
assert_eq!(u.simple().to_string(), expected);
}
#[test]
fn test_as_bytes() {
let u = new();
let ub = u.as_bytes();
assert_eq!(ub.len(), 16);
assert!(!ub.iter().all(|&b| b == 0));
}
#[test]
fn test_bytes_roundtrip() {
let b_in: [u8; 16] = [0xa1, 0xa2, 0xa3, 0xa4, 0xb1, 0xb2, 0xc1, 0xc2, 0xd1, 0xd2, 0xd3,
0xd4, 0xd5, 0xd6, 0xd7, 0xd8];
let u = Uuid::from_bytes(&b_in).unwrap();
let b_out = u.as_bytes();
assert_eq!(&b_in, b_out);
}
#[test]
fn test_operator_eq() {
let u1 = new();
let u2 = u1.clone();
let u3 = new2();
assert!(u1 == u1);
assert!(u1 == u2);
assert!(u2 == u1);
assert!(u1 != u3);
assert!(u3 != u1);
assert!(u2 != u3);
assert!(u3 != u2);
}
#[test]
#[cfg(feature = "v4")]
fn test_rand_rand() {
let mut rng = rand::thread_rng();
let u: Uuid = rand::Rand::rand(&mut rng);
let ub = u.as_bytes();
assert!(ub.len() == 16);
assert!(!ub.iter().all(|&b| b == 0));
}
#[test]
fn test_iterbytes_impl_for_uuid() {
let mut set = std::collections::HashSet::new();
let id1 = new();
let id2 = new2();
set.insert(id1.clone());
assert!(set.contains(&id1));
assert!(!set.contains(&id2));
}
}