ps_uuid/methods/
gen_v2.rs1use crate::{UuidConstructionError, UUID};
2
3impl UUID {
4 pub fn gen_v2(domain: u8, local_id: u32) -> Result<Self, UuidConstructionError> {
10 let mut uuid = Self::gen_v1()?;
11
12 uuid.bytes[0..4].copy_from_slice(&local_id.to_be_bytes());
14 uuid.bytes[9] = domain;
15
16 Ok(uuid.with_version(2))
17 }
18}
19
20#[cfg(test)]
21mod tests {
22 #![allow(clippy::expect_used)]
23 use super::*;
24
25 fn v2(domain: u8, local_id: u32) -> UUID {
31 UUID::gen_v2(domain, local_id).expect("failed to build v2 UUID")
32 }
33
34 fn local_id(u: &UUID) -> u32 {
37 u32::from_be_bytes(
38 u.bytes[0..4]
39 .try_into()
40 .expect("UUID timestamp slice should be exactly 4 bytes"),
41 )
42 }
43
44 const fn is_rfc4122_variant(u: &UUID) -> bool {
46 (u.bytes[8] & 0b1100_0000) == 0b1000_0000
47 }
48
49 #[test]
54 fn version_is_always_2() {
55 for &domain in &[0, 1, 2, 42] {
56 let u = v2(domain, 0xDEAD_BEEF);
57 assert_eq!(u.get_version(), Some(2));
58 }
59 }
60
61 #[test]
62 fn variant_bits_remain_rfc4122() {
63 let u = v2(1, 123);
64 assert!(is_rfc4122_variant(&u));
65 }
66
67 #[test]
68 fn local_id_is_encoded_big_endian() {
69 for &id in &[0, 1, 0x1234_5678, u32::MAX] {
70 let u = v2(2, id);
71 assert_eq!(local_id(&u), id);
72 }
73 }
74
75 #[test]
76 fn domain_is_written_to_clock_seq_low() {
77 for domain in 0u8..=10 {
78 let u = v2(domain, 7);
79 assert_eq!(u.bytes[9], domain);
80 }
81 }
82
83 #[test]
84 fn different_local_ids_produce_distinct_uuids() {
85 let u1 = v2(1, 0xAAAA_BBBB);
86 let u2 = v2(1, 0xCCCC_DDDD);
87 assert_ne!(
88 u1.bytes, u2.bytes,
89 "UUIDs must differ when the Local-ID field changes"
90 );
91 }
92
93 #[test]
94 fn different_domains_produce_distinct_uuids() {
95 let u1 = v2(0, 42);
96 let u2 = v2(7, 42);
97 assert_ne!(
98 u1.bytes, u2.bytes,
99 "UUIDs must differ when the Domain field changes"
100 );
101 }
102}