pub mod heer {
use crate::heer::{HEER_FLIP_MASK, HeerId};
use crate::heer_desc::HeerIdDesc;
pub fn to_desc(mut v: Vec<HeerId>) -> Vec<HeerIdDesc> {
for id in v.iter_mut() {
let raw = id.as_i64() ^ HEER_FLIP_MASK;
*id = HeerId::from_i64_raw(raw);
}
let mut v = std::mem::ManuallyDrop::new(v);
let (ptr, len, cap) = (v.as_mut_ptr(), v.len(), v.capacity());
unsafe { Vec::from_raw_parts(ptr as *mut HeerIdDesc, len, cap) }
}
pub fn to_asc(mut v: Vec<HeerIdDesc>) -> Vec<HeerId> {
for id in v.iter_mut() {
let raw = id.as_i64() ^ HEER_FLIP_MASK;
*id = HeerIdDesc::from_i64(raw).expect("XOR preserves bit 63 = 0");
}
let mut v = std::mem::ManuallyDrop::new(v);
let (ptr, len, cap) = (v.as_mut_ptr(), v.len(), v.capacity());
unsafe { Vec::from_raw_parts(ptr as *mut HeerId, len, cap) }
}
}
pub mod ranj {
use crate::ranj::{RANJ_FLIP_MASK, RanjId};
use crate::ranj_desc::RanjIdDesc;
use uuid::Uuid;
pub fn to_desc(mut v: Vec<RanjId>) -> Vec<RanjIdDesc> {
for id in v.iter_mut() {
let raw = id.as_uuid().as_u128() ^ RANJ_FLIP_MASK;
*id = RanjId::from_uuid_raw(Uuid::from_u128(raw));
}
let mut v = std::mem::ManuallyDrop::new(v);
let (ptr, len, cap) = (v.as_mut_ptr(), v.len(), v.capacity());
unsafe { Vec::from_raw_parts(ptr as *mut RanjIdDesc, len, cap) }
}
pub fn to_asc(mut v: Vec<RanjIdDesc>) -> Vec<RanjId> {
for id in v.iter_mut() {
let raw = id.as_uuid().as_u128() ^ RANJ_FLIP_MASK;
*id = RanjIdDesc::from_uuid(Uuid::from_u128(raw))
.expect("XOR preserves version and variant");
}
let mut v = std::mem::ManuallyDrop::new(v);
let (ptr, len, cap) = (v.as_mut_ptr(), v.len(), v.capacity());
unsafe { Vec::from_raw_parts(ptr as *mut RanjId, len, cap) }
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::precision::RanjPrecision;
use crate::{HeerId, HeerIdDesc, RanjId};
#[test]
fn heer_to_desc_to_asc_is_identity() {
let original: Vec<HeerId> = (0..1000u64)
.map(|i| HeerId::new(i * 1000, (i as u16) % 500, (i as u16) % 8000).unwrap())
.collect();
let copy = original.clone();
let descs = heer::to_desc(copy);
assert_eq!(descs.len(), original.len());
let back = heer::to_asc(descs);
assert_eq!(back, original);
}
#[test]
fn heer_to_desc_preserves_logical_fields() {
let id = HeerId::new(1_234_567, 42, 777).unwrap();
let descs = heer::to_desc(vec![id]);
assert_eq!(descs[0].timestamp_ms(), 1_234_567);
assert_eq!(descs[0].node_id(), 42);
assert_eq!(descs[0].sequence(), 777);
}
#[test]
fn heer_bulk_sort_matches_per_element_desc_sort() {
let asc: Vec<HeerId> = (0..100u64)
.rev()
.map(|i| HeerId::new(i * 1000, 1, 0).unwrap())
.collect();
let mut bulk = heer::to_desc(asc.clone());
bulk.sort();
let mut per_elem: Vec<HeerIdDesc> = asc
.iter()
.map(|h| {
HeerIdDesc::new(
h.into_parts().timestamp_ms,
h.into_parts().node_id,
h.into_parts().sequence,
)
.unwrap()
})
.collect();
per_elem.sort();
assert_eq!(bulk, per_elem);
}
#[test]
fn ranj_to_desc_to_asc_is_identity() {
let original: Vec<RanjId> = (0..1000u128)
.map(|i| {
RanjId::new(
i * 1000,
RanjPrecision::Microseconds,
(i as u16) % 1000,
i as u16,
)
.unwrap()
})
.collect();
let copy = original.clone();
let descs = ranj::to_desc(copy);
let back = ranj::to_asc(descs);
assert_eq!(back, original);
}
#[test]
fn reuses_allocation() {
let v: Vec<HeerId> = (0..10u64).map(|i| HeerId::new(i, 0, 0).unwrap()).collect();
let cap_before = v.capacity();
let ptr_before = v.as_ptr() as usize;
let descs = heer::to_desc(v);
assert_eq!(descs.capacity(), cap_before);
assert_eq!(descs.as_ptr() as usize, ptr_before);
}
}