Skip to main content

ps_uuid/methods/
new_v8.rs

1use crate::UUID;
2
3impl UUID {
4    /// Build an RFC-4122 **Version 8** (custom) UUID from any value convertible to `u128`.
5    ///
6    /// The caller supplies the complete 128-bit payload (in host order).
7    /// This function:
8    /// - Converts the value to a `u128`
9    /// - Serializes it to big-endian (network order)
10    /// - Overwrites the version nibble (bits 48‥=51) with `0b1000`
11    /// - Overwrites the variant bits (bits 64‥=65) with `0b10`
12    /// - Leaves all other bits untouched
13    ///
14    /// # Example
15    /// ```
16    /// use ps_uuid::UUID;
17    ///
18    /// let payload: u128 = 0xDEAD_BEEF_DEAD_BEEF_DEAD_BEEF_DEAD_BEEF;
19    /// let uuid = UUID::new_v8(payload);
20    ///
21    /// assert_eq!(uuid.get_version(), Some(8));
22    /// ```
23    #[must_use]
24    pub fn new_v8<V: Into<u128>>(value: V) -> Self {
25        Self::from_parts_v8(value.into().to_be_bytes())
26    }
27}
28
29#[cfg(test)]
30mod tests {
31    #![allow(clippy::expect_used)]
32    use super::*;
33    use crate::Variant;
34
35    const fn ver(b: &[u8; 16]) -> u8 {
36        b[6] >> 4
37    }
38    const fn var(b: &[u8; 16]) -> u8 {
39        b[8] >> 6
40    }
41
42    #[test]
43    fn version_and_variant_bits_are_fixed() {
44        for payload in &[0u128, u128::MAX] {
45            let uuid = UUID::new_v8(*payload);
46            let b = uuid.as_bytes();
47            assert_eq!(ver(b), 0b1000, "version must be 8");
48            assert_eq!(var(b), 0b10, "variant must be RFC-4122");
49        }
50    }
51
52    #[test]
53    fn non_reserved_bits_are_preserved() {
54        let mut bytes = [0u8; 16];
55        for (i, item) in bytes.iter_mut().enumerate() {
56            *item = u8::try_from(i).expect("loop index should fit into u8");
57        }
58        let payload = u128::from_be_bytes(bytes);
59
60        let uuid = UUID::new_v8(payload);
61        let out = uuid.as_bytes();
62
63        for i in 0..16 {
64            match i {
65                6 => {
66                    assert_eq!(out[6] & 0x0F, bytes[6] & 0x0F);
67                    assert_eq!(out[6] >> 4, 0x8);
68                }
69                8 => {
70                    assert_eq!(out[8] & 0x3F, bytes[8] & 0x3F);
71                    assert_eq!(out[8] >> 6, 0b10);
72                }
73                _ => assert_eq!(out[i], bytes[i], "byte {i} changed"),
74            }
75        }
76    }
77
78    #[test]
79    fn version_and_variant_helpers_report_correctly() {
80        let uuid = UUID::new_v8(0u128);
81        assert_eq!(uuid.get_version(), Some(8));
82        assert_eq!(uuid.get_variant(), Variant::OSF);
83    }
84}