1use crate::UUID;
2
3impl UUID {
4 #[must_use]
5 pub const fn with_version(self, version: u8) -> Self {
6 let mut uuid = self;
7
8 uuid.bytes[6] &= 0x0F;
9 uuid.bytes[6] |= version << 4;
10
11 uuid.with_variant(crate::Variant::OSF)
12 }
13}
14
15#[cfg(test)]
16mod tests {
17 use super::UUID;
18
19 const fn create_test_uuid(bytes: [u8; 16]) -> UUID {
21 UUID { bytes }
22 }
23
24 const fn has_osf_variant(uuid: &UUID) -> bool {
26 let byte8 = uuid.bytes[8];
27 (byte8 & 0b1100_0000) == 0b1000_0000
28 }
29
30 #[test]
31 fn test_set_valid_version() {
32 let original_bytes = [
34 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, ];
39 let uuid = create_test_uuid(original_bytes);
40
41 for version in 1..=5 {
42 let modified_uuid = uuid.with_version(version);
43 assert_eq!(
45 modified_uuid.get_version(),
46 Some(version),
47 "Version should be set to {version}"
48 );
49 assert_eq!(
51 modified_uuid.bytes[6],
52 (version << 4) | (original_bytes[6] & 0x0F),
53 "Byte 6 incorrect for version {version}"
54 );
55 assert!(
57 has_osf_variant(&modified_uuid),
58 "OSF variant not set for version {version}"
59 );
60 for (i, _) in original_bytes.iter().enumerate() {
62 if i != 6 && i != 8 {
63 assert_eq!(
64 modified_uuid.bytes[i], original_bytes[i],
65 "Byte {i} changed unexpectedly for version {version}"
66 );
67 }
68 }
69 }
70 }
71
72 #[test]
73 fn test_set_version_zero() {
74 let original_bytes = [0xFF; 16];
76 let uuid = create_test_uuid(original_bytes);
77
78 let modified_uuid = uuid.with_version(0);
79 assert_eq!(
80 modified_uuid.get_version(),
81 Some(0),
82 "Version should be set to 0"
83 );
84 assert_eq!(
85 modified_uuid.bytes[6],
86 original_bytes[6] & 0x0F,
87 "Byte 6 should preserve lower bits with version 0"
88 );
89 assert!(
90 has_osf_variant(&modified_uuid),
91 "OSF variant not set for version 0"
92 );
93 for (i, _) in original_bytes.iter().enumerate() {
95 if i != 6 && i != 8 {
96 assert_eq!(
97 modified_uuid.bytes[i], original_bytes[i],
98 "Byte {i} changed unexpectedly"
99 );
100 }
101 }
102 }
103
104 #[test]
105 fn test_set_max_version() {
106 let original_bytes = [0x00; 16];
108 let uuid = create_test_uuid(original_bytes);
109
110 let modified_uuid = uuid.with_version(15);
111 assert_eq!(
112 modified_uuid.get_version(),
113 Some(15),
114 "Version should be set to 15"
115 );
116 assert_eq!(
117 modified_uuid.bytes[6], 0xF0,
118 "Byte 6 should be 0xF0 for version 15"
119 );
120 assert!(
121 has_osf_variant(&modified_uuid),
122 "OSF variant not set for version 15"
123 );
124 for (i, _) in original_bytes.iter().enumerate() {
126 if i != 6 && i != 8 {
127 assert_eq!(
128 modified_uuid.bytes[i], original_bytes[i],
129 "Byte {i} changed unexpectedly"
130 );
131 }
132 }
133 }
134
135 #[test]
136 fn test_preserve_lower_nibble_byte6() {
137 let original_bytes = [
139 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0x5F, 0xFF, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, ];
144 let uuid = create_test_uuid(original_bytes);
145
146 let modified_uuid = uuid.with_version(3);
147 assert_eq!(
148 modified_uuid.get_version(),
149 Some(3),
150 "Version should be set to 3"
151 );
152 assert_eq!(
153 modified_uuid.bytes[6], 0x3F,
154 "Byte 6 should have version 3 (0x3) in upper nibble and preserve 0xF in lower nibble"
155 );
156 assert!(has_osf_variant(&modified_uuid), "OSF variant not set");
157 }
158
159 #[test]
160 fn test_idempotence() {
161 let original_bytes = [0xAA; 16];
163 let uuid = create_test_uuid(original_bytes);
164
165 let uuid_v1 = uuid.with_version(1);
166 let uuid_v1_again = uuid_v1.with_version(1);
167 assert_eq!(
168 uuid_v1.bytes, uuid_v1_again.bytes,
169 "Repeated calls with same version should be idempotent"
170 );
171 assert_eq!(
172 uuid_v1_again.get_version(),
173 Some(1),
174 "Version should remain 1"
175 );
176
177 let uuid_v2 = uuid_v1.with_version(2);
178 assert_eq!(uuid_v2.get_version(), Some(2), "Version should change to 2");
179 assert!(has_osf_variant(&uuid_v2), "OSF variant should persist");
180 }
181
182 #[test]
183 fn test_version_change_preserves_other_fields() {
184 let original_bytes = [
186 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x7A, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, ];
191 let uuid = create_test_uuid(original_bytes);
192
193 let modified_uuid = uuid.with_version(4);
194 assert_eq!(
195 modified_uuid.get_version(),
196 Some(4),
197 "Version should be set to 4"
198 );
199 let unchanged_indices = [0, 1, 2, 3, 4, 5, 7, 9, 10, 11, 12, 13, 14, 15];
201 for i in &unchanged_indices {
202 assert_eq!(
203 modified_uuid.bytes[*i], original_bytes[*i],
204 "Byte {i} should remain unchanged"
205 );
206 }
207 assert_eq!(modified_uuid.bytes[6], 0x4A, "Byte 6 should be 0x4A");
209 assert!(has_osf_variant(&modified_uuid), "OSF variant not set");
210 }
211
212 #[test]
213 fn test_version_after_variant_change() {
214 let original_bytes = [0x00; 16];
216 let uuid = create_test_uuid(original_bytes);
217
218 let uuid_with_version = uuid.with_version(5);
219 let uuid_with_version_again = uuid_with_version.with_version(3);
220 assert_eq!(
221 uuid_with_version_again.get_version(),
222 Some(3),
223 "Version should be updated to 3"
224 );
225 assert!(
226 has_osf_variant(&uuid_with_version_again),
227 "OSF variant should be set"
228 );
229 assert_eq!(
230 uuid_with_version_again.bytes[6], 0x30,
231 "Byte 6 should reflect version 3 with zero lower nibble"
232 );
233 }
234}