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 <tazjin@tvl.su> Autosubmit: tazjin <tazjin@tvl.su> Tested-by: BuildkiteCI
This commit is contained in:
parent
565c0fd24c
commit
95ebcc24b0
1 changed files with 24 additions and 6 deletions
|
@ -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::<u8>(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());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue