uuid-rs/src/lib.rs

148 lines
3.0 KiB
Rust
Raw Permalink Normal View History

2023-09-08 15:51:26 -04:00
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;
2023-09-04 22:00:00 -04:00
mod rng;
2023-09-08 15:51:26 -04:00
pub mod fmt;
pub mod serde;
pub mod v4;
pub type Bytes = [u8; 16];
2023-09-04 22:00:00 -04:00
2023-09-08 15:51:26 -04:00
#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[repr(transparent)]
2023-09-04 22:00:00 -04:00
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)]
2023-09-08 15:51:26 -04:00
#[non_exhaustive]
2023-09-04 22:00:00 -04:00
#[repr(u8)]
pub enum Version {
Nil = 0,
Time = 1,
DCE = 2,
MD5 = 3,
Random = 4,
SHA1 = 5,
2023-09-08 15:51:26 -04:00
Unknown = u8::MAX,
2023-09-04 22:00:00 -04:00
}
impl Uuid {
pub fn new_nil() -> Self {
Uuid(Uuid::nil_bytes())
}
2023-09-08 15:51:26 -04:00
pub fn from_bytes(bytes: Bytes) -> Self {
Uuid(bytes)
}
pub fn from_slice(b: &[u8]) -> Result<Uuid, Error> {
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))
2023-09-04 22:00:00 -04:00
}
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
}
}
2023-09-08 15:51:26 -04:00
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]
}
2023-09-04 22:00:00 -04:00
#[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;
2023-09-08 15:51:26 -04:00
bytes[8] = variant | byte;
2023-09-04 22:00:00 -04:00
}
#[inline]
fn set_version(bytes: &mut Bytes, version: Version) {
2023-09-08 15:51:26 -04:00
let version = (version as u8) << 4;
let byte = bytes[6] & 0xf;
bytes[6] = version | byte;
2023-09-04 22:00:00 -04:00
}
}
impl Default for Uuid {
fn default() -> Self {
Uuid::new_nil()
}
}
2023-09-08 15:51:26 -04:00
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)
}
}