From 95ebcc24b0f7ec1ff7113fe7ba127b3401cbd7ab Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Mon, 19 Aug 2024 17:31:50 +0300 Subject: refactor(tazjin/german-string): add type for encoding storage class Adds a StorageClassPtr type that is set up to be able to steal bits from an aligned pointer to encode the storage class of a German String. Change-Id: I64591174eac1ebcb73e624a59bd107ba1e02c69d Reviewed-on: https://cl.tvl.fyi/c/depot/+/12262 Reviewed-by: tazjin Autosubmit: tazjin Tested-by: BuildkiteCI --- users/tazjin/german-string/src/lib.rs | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) (limited to 'users/tazjin') diff --git a/users/tazjin/german-string/src/lib.rs b/users/tazjin/german-string/src/lib.rs index b6e6a6057e78..d9beb7a099cb 100644 --- a/users/tazjin/german-string/src/lib.rs +++ b/users/tazjin/german-string/src/lib.rs @@ -9,12 +9,30 @@ struct GSSmall { data: [u8; 12], } +#[derive(Clone, Copy)] +#[repr(transparent)] +struct StorageClassPtr(usize); + +impl StorageClassPtr { + fn transient(ptr: *mut u8) -> Self { + debug_assert!( + (ptr as usize & 0b11) == 0, + "pointer must be at least 4-byte aligned" + ); + Self(ptr as usize) + } + + fn as_ptr(&self) -> *mut u8 { + (self.0 & !0b11) as *mut u8 + } +} + #[derive(Clone, Copy)] #[repr(C)] struct GSLarge { len: u32, prefix: [u8; 4], - data: *mut u8, + data: StorageClassPtr, } const _ASSERT_VARIANTS_SIZE: () = assert!( @@ -61,7 +79,7 @@ impl GermanString { std::alloc::handle_alloc_error(layout); } std::ptr::copy_nonoverlapping(bytes.as_ptr(), ptr, bytes.len()); - ptr + StorageClassPtr::transient(ptr) }, }; @@ -92,7 +110,7 @@ impl GermanString { let mut large = GSLarge { len: md.len() as u32, prefix: [0u8; 4], - data: md.as_mut_ptr(), + data: StorageClassPtr::transient(md.as_mut_ptr()), }; large.prefix.copy_from_slice(&md[..4]); @@ -108,7 +126,7 @@ impl GermanString { pub fn as_bytes(&self) -> &[u8] { if self.len() > 12 { - unsafe { std::slice::from_raw_parts(self.0.large.data, self.len()) } + unsafe { std::slice::from_raw_parts(self.0.large.data.as_ptr(), self.len()) } } else { unsafe { &self.0.small.data.as_ref()[..self.len()] } } @@ -124,7 +142,7 @@ impl Drop for GermanString { if self.len() > 12 { let layout = Layout::array::(self.len()).unwrap(); unsafe { - std::alloc::dealloc(self.0.large.data, layout); + std::alloc::dealloc(self.0.large.data.as_ptr(), layout); } } } @@ -140,7 +158,7 @@ impl PartialEq for GermanString { if self.len() <= 12 { return self.0.small.data[..self.len()] == other.0.small.data[..other.len()]; } - return self.0.large.data == other.0.large.data + return self.0.large.data.as_ptr() == other.0.large.data.as_ptr() || (self.0.large.prefix == other.0.large.prefix && self.as_bytes() == other.as_bytes()); } -- cgit 1.4.1