1 use alloc::boxed::Box; 2 use core::marker::PhantomData; 3 use core::mem::ManuallyDrop; 4 use core::ops::{Deref, DerefMut}; 5 use core::ptr::NonNull; 6 /// This is equivalent to &[T], except it has a stable repr(C) layout 7 #[repr(C)] 8 pub struct DiplomatSlice<'a, T> { 9 // Invariant: ptr is a valid ptr to the beginning of an &[T] allocation. It may be null if len is null 10 ptr: *const T, 11 // Invariant: the allocation contains at least `len` elements 12 len: usize, 13 phantom: PhantomData<&'a [T]>, 14 } 15 16 impl<T> Clone for DiplomatSlice<'_, T> { clone(&self) -> Self17 fn clone(&self) -> Self { 18 *self 19 } 20 } 21 impl<T> Copy for DiplomatSlice<'_, T> {} 22 23 impl<'a, T> From<&'a [T]> for DiplomatSlice<'a, T> { from(x: &'a [T]) -> Self24 fn from(x: &'a [T]) -> Self { 25 // Safe to construct since we're constructing it from a slice 26 DiplomatSlice { 27 ptr: x.as_ptr(), 28 len: x.len(), 29 phantom: PhantomData, 30 } 31 } 32 } 33 34 impl<'a, T> From<DiplomatSlice<'a, T>> for &'a [T] { from(x: DiplomatSlice<'a, T>) -> Self35 fn from(x: DiplomatSlice<'a, T>) -> Self { 36 unsafe { 37 // It's common in C-land to represent empty slices with NULL, which is not the case in Rust 38 // We normalize this 39 if x.ptr.is_null() { 40 debug_assert!(x.len == 0); 41 return &[]; 42 } 43 // Safety: carrying over safety variants from DiplomatSlice, and we null-checked 44 core::slice::from_raw_parts(x.ptr, x.len) 45 } 46 } 47 } 48 49 impl<T> Deref for DiplomatSlice<'_, T> { 50 type Target = [T]; deref(&self) -> &[T]51 fn deref(&self) -> &[T] { 52 (*self).into() 53 } 54 } 55 56 /// This is equivalent to &mut [T], except it has a stable repr(C) layout 57 #[repr(C)] 58 pub struct DiplomatSliceMut<'a, T> { 59 // Invariant: ptr is a valid ptr to the beginning of an &[T] allocation. It may be null if len is null 60 ptr: *mut T, 61 // Invariant: the allocation contains at least `len` elements 62 len: usize, 63 phantom: PhantomData<&'a mut [T]>, 64 } 65 66 impl<'a, T> From<&'a mut [T]> for DiplomatSliceMut<'a, T> { from(x: &'a mut [T]) -> Self67 fn from(x: &'a mut [T]) -> Self { 68 // Safe to construct since we're constructing it from a slice 69 DiplomatSliceMut { 70 ptr: x.as_mut_ptr(), 71 len: x.len(), 72 phantom: PhantomData, 73 } 74 } 75 } 76 77 impl<'a, T> From<DiplomatSliceMut<'a, T>> for &'a mut [T] { from(x: DiplomatSliceMut<'a, T>) -> Self78 fn from(x: DiplomatSliceMut<'a, T>) -> Self { 79 unsafe { 80 if x.ptr.is_null() { 81 debug_assert!(x.len == 0); 82 return &mut []; 83 } 84 // Safety: carrying over safety variants from DiplomatSliceMut 85 core::slice::from_raw_parts_mut(x.ptr, x.len) 86 } 87 } 88 } 89 90 impl<T> Deref for DiplomatSliceMut<'_, T> { 91 type Target = [T]; deref(&self) -> &[T]92 fn deref(&self) -> &[T] { 93 if self.ptr.is_null() { 94 debug_assert!(self.len == 0); 95 return &[]; 96 } 97 unsafe { 98 // Safety: carrying over safety variants from DiplomatSliceMut 99 100 core::slice::from_raw_parts(self.ptr, self.len) 101 } 102 } 103 } 104 105 impl<T> DerefMut for DiplomatSliceMut<'_, T> { deref_mut(&mut self) -> &mut [T]106 fn deref_mut(&mut self) -> &mut [T] { 107 if self.ptr.is_null() { 108 debug_assert!(self.len == 0); 109 return &mut []; 110 } 111 unsafe { 112 // Safety: carrying over safety variants from DiplomatSliceMut 113 114 core::slice::from_raw_parts_mut(self.ptr, self.len) 115 } 116 } 117 } 118 119 #[repr(C)] 120 pub struct DiplomatOwnedSlice<T> { 121 // Invariant: ptr is a valid ptr to the beginning of an owned Box<[T]> allocation. It may be null if len is null 122 ptr: *mut T, 123 // Invariant: the allocation contains `len` elements 124 len: usize, 125 phantom: PhantomData<Box<[T]>>, 126 } 127 128 impl<T> Drop for DiplomatOwnedSlice<T> { drop(&mut self)129 fn drop(&mut self) { 130 if !self.ptr.is_null() { 131 unsafe { 132 // Safety: This is equivalent to a valid Box 133 drop(Box::from_raw(core::ptr::slice_from_raw_parts_mut( 134 self.ptr, self.len, 135 ))); 136 } 137 } 138 } 139 } 140 141 impl<T> From<Box<[T]>> for DiplomatOwnedSlice<T> { from(x: Box<[T]>) -> Self142 fn from(x: Box<[T]>) -> Self { 143 // Safe to construct since we're constructing it from a valid Box<[T]> 144 let len = x.len(); 145 DiplomatOwnedSlice { 146 ptr: Box::into_raw(x) as *mut T, 147 len, 148 phantom: PhantomData, 149 } 150 } 151 } 152 153 impl<T> From<DiplomatOwnedSlice<T>> for Box<[T]> { from(x: DiplomatOwnedSlice<T>) -> Self154 fn from(x: DiplomatOwnedSlice<T>) -> Self { 155 let x = ManuallyDrop::new(x); 156 unsafe { 157 if x.ptr.is_null() { 158 debug_assert!(x.len == 0); 159 let dangling = core::ptr::NonNull::dangling().as_ptr(); 160 return Box::from_raw(core::ptr::slice_from_raw_parts_mut(dangling, x.len)); 161 } 162 // Safety: carrying over safety variants from DiplomatOwnedSlice 163 Box::from_raw(core::ptr::slice_from_raw_parts_mut(x.ptr, x.len)) 164 } 165 } 166 } 167 168 impl<T> Deref for DiplomatOwnedSlice<T> { 169 type Target = [T]; deref(&self) -> &[T]170 fn deref(&self) -> &[T] { 171 if self.ptr.is_null() { 172 debug_assert!(self.len == 0); 173 return &[]; 174 } 175 // Safety: The type invariants allow us to treat is as a valid Box<[T]> 176 unsafe { core::slice::from_raw_parts(self.ptr, self.len) } 177 } 178 } 179 180 impl<T> DerefMut for DiplomatOwnedSlice<T> { deref_mut(&mut self) -> &mut [T]181 fn deref_mut(&mut self) -> &mut [T] { 182 if self.ptr.is_null() { 183 debug_assert!(self.len == 0); 184 return &mut []; 185 } 186 // Safety: The type invariants allow us to treat is as a valid Box<[T]> 187 unsafe { core::slice::from_raw_parts_mut(self.ptr, self.len) } 188 } 189 } 190 191 /// This is equivalent to &str, except it has a stable repr(C) layout 192 // Safety invariant: contained slice must be valid UTF-8 193 #[repr(transparent)] 194 #[derive(Copy, Clone)] 195 pub struct DiplomatUtf8StrSlice<'a>(DiplomatSlice<'a, u8>); 196 197 impl<'a> From<&'a str> for DiplomatUtf8StrSlice<'a> { from(x: &'a str) -> Self198 fn from(x: &'a str) -> Self { 199 // Safety: invariant upheld; obtained from `str` 200 Self(x.as_bytes().into()) 201 } 202 } 203 204 impl<'a> From<DiplomatUtf8StrSlice<'a>> for &'a str { from(x: DiplomatUtf8StrSlice<'a>) -> Self205 fn from(x: DiplomatUtf8StrSlice<'a>) -> Self { 206 unsafe { 207 // We can assume this because of the invariant on DiplomatUtf8StrSlice 208 core::str::from_utf8_unchecked(<&[u8]>::from(x.0)) 209 } 210 } 211 } 212 213 impl Deref for DiplomatUtf8StrSlice<'_> { 214 type Target = str; deref(&self) -> &str215 fn deref(&self) -> &str { 216 (*self).into() 217 } 218 } 219 220 /// This is equivalent to Box<str>, except it has a stable repr(C) layout 221 // Safety invariant: contained slice must be valid UTF-8 222 #[repr(transparent)] 223 pub struct DiplomatOwnedUTF8StrSlice(DiplomatOwnedSlice<u8>); 224 225 impl From<Box<str>> for DiplomatOwnedUTF8StrSlice { from(x: Box<str>) -> Self226 fn from(x: Box<str>) -> Self { 227 // Safety: invariant upheld; obtained from `str` 228 Self(Box::<[u8]>::from(x).into()) 229 } 230 } 231 232 impl From<DiplomatOwnedUTF8StrSlice> for Box<str> { from(x: DiplomatOwnedUTF8StrSlice) -> Self233 fn from(x: DiplomatOwnedUTF8StrSlice) -> Self { 234 let buf = Box::<[u8]>::from(x.0); 235 let len = buf.len(); 236 let raw = Box::into_raw(buf); 237 let raw = if raw.is_null() { 238 debug_assert!(len == 0); 239 NonNull::<u8>::dangling().as_ptr() 240 } else { 241 raw as *mut u8 242 }; 243 unsafe { 244 // We deconstructed the Box already so we don't have to worry about provenance 245 // We're technically making an &mut [u8] here, because there isn't an easy route to construct 246 // string types that are owned 247 let slice = core::slice::from_raw_parts_mut(raw, len); 248 // We can assume this because of the invariant on DiplomatOwnedUTF8StrSlice 249 let strslice = core::str::from_utf8_unchecked_mut(slice); 250 Box::from_raw(strslice as *mut str) 251 } 252 } 253 } 254 255 impl Deref for DiplomatOwnedUTF8StrSlice { 256 type Target = str; deref(&self) -> &str257 fn deref(&self) -> &str { 258 let slice = &self.0; 259 unsafe { 260 // We can assume this because of the invariant on DiplomatOwnedUTF8StrSlice 261 core::str::from_utf8_unchecked(slice) 262 } 263 } 264 } 265 266 /// Like &str, but unvalidated 267 pub type DiplomatStrSlice<'a> = DiplomatSlice<'a, u8>; 268 /// Like Box<str>, but unvalidated 269 pub type DiplomatOwnedStrSlice = DiplomatOwnedSlice<u8>; 270 /// An unvalidated UTF-16 string 271 pub type DiplomatStr16Slice<'a> = DiplomatSlice<'a, u16>; 272 /// An unvalidated, owned UTF-16 string 273 pub type DiplomatOwnedStr16Slice<'a> = DiplomatOwnedSlice<u16>; 274