use crate::Case;
#[cfg(any(feature = "encryption", feature = "internals"))]
use crate::TnidVariant;
pub const UUID_V8_MASK: u128 = 0x00000000_0000_8000_8000_000000000000;
pub fn uuid_and_variant_mask(tnid_variant: u8) -> u128 {
debug_assert!(tnid_variant.leading_zeros() >= 6);
let variant = tnid_variant as u128;
UUID_V8_MASK | (variant << 60)
}
#[cfg(any(feature = "encryption", feature = "internals"))]
pub fn change_variant(id: u128, to_variant: TnidVariant) -> u128 {
let variant_mask = 0b11u128 << 60;
let id_without_variant = id & !variant_mask;
let new_variant = to_variant.as_u8() as u128;
id_without_variant | (new_variant << 60)
}
pub fn u128_to_uuid_string(id: u128, case: Case) -> String {
let first_section = (id >> 96) as u32;
let second_section = ((id >> 80) & 0xffff) as u16;
let third_section = ((id >> 64) & 0xffff) as u16;
let fourth_section = ((id >> 48) & 0xffff) as u16;
let fifth_section = (id & 0xffffffffffff) as u64;
match case {
Case::Upper => format!(
"{:08X}-{:04X}-{:04X}-{:04X}-{:012X}",
first_section, second_section, third_section, fourth_section, fifth_section
),
Case::Lower => format!(
"{:08x}-{:04x}-{:04x}-{:04x}-{:012x}",
first_section, second_section, third_section, fourth_section, fifth_section
),
}
}
pub fn hex_char_to_nibble(c: u8) -> Option<u8> {
match c {
b'0'..=b'9' => Some(c - b'0'),
b'a'..=b'f' => Some(c - b'a' + 10),
b'A'..=b'F' => Some(c - b'A' + 10),
_ => None,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn metadata_mask_correct_location() {
let mask = uuid_and_variant_mask(0);
assert_eq!(mask.leading_zeros(), 48);
assert_eq!(mask.trailing_zeros(), 63);
assert_eq!(mask.count_ones(), 2);
}
#[test]
#[cfg(any(feature = "encryption", feature = "internals"))]
fn change_variant_changes_only_variant_bits() {
let id: u128 = 0x0123_4567_89ab_cdef_0123_4567_89ab_cdef;
let v0 = change_variant(id, TnidVariant::V0);
let v1 = change_variant(id, TnidVariant::V1);
let mask = 0b11u128 << 60;
assert_eq!(id & !mask, v0 & !mask);
assert_eq!(id & !mask, v1 & !mask);
assert_ne!(v0 & mask, v1 & mask);
}
}