Skip to main content

ps_uuid/methods/
from_parts_v2.rs

1use crate::UUID;
2
3impl UUID {
4    /// Build a DCE Security (v2) UUID from its individual fields.
5    #[must_use]
6    pub fn from_parts_v2(
7        domain: u8,
8        local_id: u32,
9        time_mid: u16,
10        time_hi: u16,
11        clock_seq: u16,
12        node_id: [u8; 6],
13    ) -> Self {
14        // `local_id` occupies the time-low field, so just forward it.
15        let mut uuid = Self::from_parts_v1(local_id, time_mid, time_hi, clock_seq, node_id);
16
17        uuid.bytes[9] = domain; // clock_seq_low -> Domain
18        uuid.with_version(2)
19    }
20}
21
22#[cfg(test)]
23mod tests {
24    use crate::{NodeId, UUID};
25
26    const fn variant_rfc_4122(byte: u8) -> bool {
27        (byte & 0b1100_0000) == 0b1000_0000
28    }
29
30    #[test]
31    fn from_parts_v2_encodes_every_field() {
32        let domain = 0xAC;
33        let local_id = 0x1234_5678;
34        let time_mid = 0x9ABC;
35        let time_hi = 0xDEF0;
36        let clock_seq = 0x1357;
37        let node_id = NodeId::random();
38
39        let u = UUID::from_parts_v2(domain, local_id, time_mid, time_hi, clock_seq, *node_id);
40
41        // time_low == local_id (big-endian)
42        assert_eq!(&u.bytes[0..4], &local_id.to_be_bytes());
43
44        // time_mid
45        assert_eq!(&u.bytes[4..6], &time_mid.to_be_bytes());
46
47        // time_hi_and_version (lower 12 bits from `time_hi`, upper nibble = 2)
48        let expected_hi = ((time_hi & 0x0FFF) | 0x2000).to_be_bytes();
49        assert_eq!(&u.bytes[6..8], &expected_hi);
50
51        // Variant bits = 10
52        assert!(variant_rfc_4122(u.bytes[8]));
53
54        // Domain
55        assert_eq!(u.bytes[9], domain);
56
57        // Node ID
58        assert_eq!(u.bytes[10..16], *node_id);
59
60        // Public API
61        assert_eq!(u.get_version(), Some(2));
62    }
63}