about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVincent Ambo <tazjin@tvl.su>2024-08-19T14·31+0300
committerclbot <clbot@tvl.fyi>2024-08-22T14·02+0000
commit95ebcc24b0f7ec1ff7113fe7ba127b3401cbd7ab (patch)
tree12b53dd7f7061c8b74382f8b1f3b1abe20a11f24
parent565c0fd24c616adce50e940fc33b7bf9137a21cc (diff)
refactor(tazjin/german-string): add type for encoding storage class r/8549
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
-rw-r--r--users/tazjin/german-string/src/lib.rs30
1 files changed, 24 insertions, 6 deletions
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
@@ -10,11 +10,29 @@ struct GSSmall {
 }
 
 #[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());
         }