• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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