use crate::UUID;
impl UUID {
#[must_use]
pub const fn with_version(self, version: u8) -> Self {
let mut uuid = self;
uuid.bytes[6] &= 0x0F;
uuid.bytes[6] |= version << 4;
uuid.with_variant(crate::Variant::OSF)
}
}
#[cfg(test)]
mod tests {
use super::UUID;
const fn create_test_uuid(bytes: [u8; 16]) -> UUID {
UUID { bytes }
}
const fn has_osf_variant(uuid: &UUID) -> bool {
let byte8 = uuid.bytes[8];
(byte8 & 0b1100_0000) == 0b1000_0000
}
#[test]
fn test_set_valid_version() {
let original_bytes = [
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, ];
let uuid = create_test_uuid(original_bytes);
for version in 1..=5 {
let modified_uuid = uuid.with_version(version);
assert_eq!(
modified_uuid.get_version(),
Some(version),
"Version should be set to {version}"
);
assert_eq!(
modified_uuid.bytes[6],
(version << 4) | (original_bytes[6] & 0x0F),
"Byte 6 incorrect for version {version}"
);
assert!(
has_osf_variant(&modified_uuid),
"OSF variant not set for version {version}"
);
for (i, _) in original_bytes.iter().enumerate() {
if i != 6 && i != 8 {
assert_eq!(
modified_uuid.bytes[i], original_bytes[i],
"Byte {i} changed unexpectedly for version {version}"
);
}
}
}
}
#[test]
fn test_set_version_zero() {
let original_bytes = [0xFF; 16];
let uuid = create_test_uuid(original_bytes);
let modified_uuid = uuid.with_version(0);
assert_eq!(
modified_uuid.get_version(),
Some(0),
"Version should be set to 0"
);
assert_eq!(
modified_uuid.bytes[6],
original_bytes[6] & 0x0F,
"Byte 6 should preserve lower bits with version 0"
);
assert!(
has_osf_variant(&modified_uuid),
"OSF variant not set for version 0"
);
for (i, _) in original_bytes.iter().enumerate() {
if i != 6 && i != 8 {
assert_eq!(
modified_uuid.bytes[i], original_bytes[i],
"Byte {i} changed unexpectedly"
);
}
}
}
#[test]
fn test_set_max_version() {
let original_bytes = [0x00; 16];
let uuid = create_test_uuid(original_bytes);
let modified_uuid = uuid.with_version(15);
assert_eq!(
modified_uuid.get_version(),
Some(15),
"Version should be set to 15"
);
assert_eq!(
modified_uuid.bytes[6], 0xF0,
"Byte 6 should be 0xF0 for version 15"
);
assert!(
has_osf_variant(&modified_uuid),
"OSF variant not set for version 15"
);
for (i, _) in original_bytes.iter().enumerate() {
if i != 6 && i != 8 {
assert_eq!(
modified_uuid.bytes[i], original_bytes[i],
"Byte {i} changed unexpectedly"
);
}
}
}
#[test]
fn test_preserve_lower_nibble_byte6() {
let original_bytes = [
0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0x5F, 0xFF, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0, ];
let uuid = create_test_uuid(original_bytes);
let modified_uuid = uuid.with_version(3);
assert_eq!(
modified_uuid.get_version(),
Some(3),
"Version should be set to 3"
);
assert_eq!(
modified_uuid.bytes[6], 0x3F,
"Byte 6 should have version 3 (0x3) in upper nibble and preserve 0xF in lower nibble"
);
assert!(has_osf_variant(&modified_uuid), "OSF variant not set");
}
#[test]
fn test_idempotence() {
let original_bytes = [0xAA; 16];
let uuid = create_test_uuid(original_bytes);
let uuid_v1 = uuid.with_version(1);
let uuid_v1_again = uuid_v1.with_version(1);
assert_eq!(
uuid_v1.bytes, uuid_v1_again.bytes,
"Repeated calls with same version should be idempotent"
);
assert_eq!(
uuid_v1_again.get_version(),
Some(1),
"Version should remain 1"
);
let uuid_v2 = uuid_v1.with_version(2);
assert_eq!(uuid_v2.get_version(), Some(2), "Version should change to 2");
assert!(has_osf_variant(&uuid_v2), "OSF variant should persist");
}
#[test]
fn test_version_change_preserves_other_fields() {
let original_bytes = [
0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x7A, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, ];
let uuid = create_test_uuid(original_bytes);
let modified_uuid = uuid.with_version(4);
assert_eq!(
modified_uuid.get_version(),
Some(4),
"Version should be set to 4"
);
let unchanged_indices = [0, 1, 2, 3, 4, 5, 7, 9, 10, 11, 12, 13, 14, 15];
for i in &unchanged_indices {
assert_eq!(
modified_uuid.bytes[*i], original_bytes[*i],
"Byte {i} should remain unchanged"
);
}
assert_eq!(modified_uuid.bytes[6], 0x4A, "Byte 6 should be 0x4A");
assert!(has_osf_variant(&modified_uuid), "OSF variant not set");
}
#[test]
fn test_version_after_variant_change() {
let original_bytes = [0x00; 16];
let uuid = create_test_uuid(original_bytes);
let uuid_with_version = uuid.with_version(5);
let uuid_with_version_again = uuid_with_version.with_version(3);
assert_eq!(
uuid_with_version_again.get_version(),
Some(3),
"Version should be updated to 3"
);
assert!(
has_osf_variant(&uuid_with_version_again),
"OSF variant should be set"
);
assert_eq!(
uuid_with_version_again.bytes[6], 0x30,
"Byte 6 should reflect version 3 with zero lower nibble"
);
}
}