use crate::error::{Error, ErrorKind}; // UUID (RFC 4122) v4 implementation // Heavily based on the 'uuid' crate: https://docs.rs/uuid/latest/uuid/ mod error; mod parse; mod rng; pub mod fmt; pub mod serde; pub mod v4; pub type Bytes = [u8; 16]; #[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)] #[repr(transparent)] pub struct Uuid(Bytes); #[derive(Clone, Copy, Debug, PartialEq)] #[repr(u8)] pub enum Variant { NCS = 0u8, Default = 0x80, Microsoft = 0xc0, Future = 0xe0, } #[derive(Clone, Copy, Debug, PartialEq)] #[non_exhaustive] #[repr(u8)] pub enum Version { Nil = 0, Time = 1, DCE = 2, MD5 = 3, Random = 4, SHA1 = 5, Unknown = u8::MAX, } impl Uuid { pub fn new_nil() -> Self { Uuid(Uuid::nil_bytes()) } pub fn from_bytes(bytes: Bytes) -> Self { Uuid(bytes) } pub fn from_slice(b: &[u8]) -> Result { if b.len() != 16 { return Err(Error(ErrorKind::ByteLength { len: b.len() })); } let mut bytes: Bytes = Uuid::nil_bytes(); bytes.copy_from_slice(b); Ok(Uuid::from_bytes(bytes)) } pub const fn get_variant(&self) -> Variant { match self.as_bytes()[8] { x if x & 0x80 == 0 => Variant::NCS, x if x & 0x40 == 0 => Variant::Default, x if x & 0x20 == 0 => Variant::Microsoft, _ => Variant::Future } } pub const fn get_version_num(&self) -> u8 { self.as_bytes()[6] >> 4 } pub const fn get_version(&self) -> Version { match self.get_version_num() { 0 => Version::Nil, 1 => Version::Time, 2 => Version::DCE, 3 => Version::MD5, 4 => Version::Random, 5 => Version::SHA1, _ => Version::Unknown } } pub const fn as_u128(&self) -> u128 { u128::from_be_bytes(*self.as_bytes()) } #[inline] pub const fn as_bytes(&self) -> &Bytes { &self.0 } #[inline] pub const fn into_bytes(self) -> Bytes { self.0 } pub const fn is_nil(&self) -> bool { self.as_u128() == u128::MIN } pub const fn encode_buffer() -> [u8; fmt::UUID_STR_LEN] { [0; fmt::UUID_STR_LEN] } #[inline] const fn nil_bytes() -> Bytes { [0u8; 16] } #[inline] fn set_variant(bytes: &mut Bytes, variant: Variant) { let variant = variant as u8; let byte = bytes[8] & 0xf; bytes[8] = variant | byte; } #[inline] fn set_version(bytes: &mut Bytes, version: Version) { let version = (version as u8) << 4; let byte = bytes[6] & 0xf; bytes[6] = version | byte; } } impl Default for Uuid { fn default() -> Self { Uuid::new_nil() } } impl AsRef<[u8]> for Uuid { #[inline] fn as_ref(&self) -> &[u8] { &self.0 } } impl ToString for Uuid { fn to_string(&self) -> String { format!("{:02x}", self) } }