owned_slice.rs (5340B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ 4 5 #![allow(unsafe_code)] 6 7 //! A replacement for `Box<[T]>` that cbindgen can understand. 8 9 use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps}; 10 use serde::de::{Deserialize, Deserializer}; 11 use serde::ser::{Serialize, Serializer}; 12 use std::marker::PhantomData; 13 use std::ops::{Deref, DerefMut}; 14 use std::ptr::NonNull; 15 use std::{ 16 fmt, 17 hash::{Hash, Hasher}, 18 iter, mem, slice, 19 }; 20 use to_shmem::{SharedMemoryBuilder, ToShmem}; 21 22 /// A struct that basically replaces a `Box<[T]>`, but which cbindgen can 23 /// understand. 24 /// 25 /// We could rely on the struct layout of `Box<[T]>` per: 26 /// 27 /// https://github.com/rust-lang/unsafe-code-guidelines/blob/master/reference/src/layout/pointers.md 28 /// 29 /// But handling fat pointers with cbindgen both in structs and argument 30 /// positions more generally is a bit tricky. 31 /// 32 /// cbindgen:derive-eq=false 33 /// cbindgen:derive-neq=false 34 #[repr(C)] 35 pub struct OwnedSlice<T: Sized> { 36 ptr: NonNull<T>, 37 len: usize, 38 _phantom: PhantomData<T>, 39 } 40 41 impl<T: Sized> Default for OwnedSlice<T> { 42 #[inline] 43 fn default() -> Self { 44 Self { 45 len: 0, 46 ptr: NonNull::dangling(), 47 _phantom: PhantomData, 48 } 49 } 50 } 51 52 impl<T: Sized> Drop for OwnedSlice<T> { 53 #[inline] 54 fn drop(&mut self) { 55 if self.len != 0 { 56 let _ = mem::replace(self, Self::default()).into_vec(); 57 } 58 } 59 } 60 61 unsafe impl<T: Sized + Send> Send for OwnedSlice<T> {} 62 unsafe impl<T: Sized + Sync> Sync for OwnedSlice<T> {} 63 64 impl<T: Clone> Clone for OwnedSlice<T> { 65 #[inline] 66 fn clone(&self) -> Self { 67 Self::from_slice(&**self) 68 } 69 } 70 71 impl<T: fmt::Debug> fmt::Debug for OwnedSlice<T> { 72 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 73 self.deref().fmt(formatter) 74 } 75 } 76 77 impl<T: PartialEq> PartialEq for OwnedSlice<T> { 78 fn eq(&self, other: &Self) -> bool { 79 self.deref().eq(other.deref()) 80 } 81 } 82 83 impl<T: Eq> Eq for OwnedSlice<T> {} 84 85 impl<T: Sized> OwnedSlice<T> { 86 /// Convert the OwnedSlice into a boxed slice. 87 #[inline] 88 pub fn into_box(self) -> Box<[T]> { 89 self.into_vec().into_boxed_slice() 90 } 91 92 /// Convert the OwnedSlice into a Vec. 93 #[inline] 94 pub fn into_vec(self) -> Vec<T> { 95 let ret = unsafe { Vec::from_raw_parts(self.ptr.as_ptr(), self.len, self.len) }; 96 mem::forget(self); 97 ret 98 } 99 100 /// Convert the regular slice into an owned slice. 101 #[inline] 102 pub fn from_slice(s: &[T]) -> Self 103 where 104 T: Clone, 105 { 106 Self::from(s.to_vec()) 107 } 108 } 109 110 impl<T> IntoIterator for OwnedSlice<T> { 111 type Item = T; 112 type IntoIter = <Vec<T> as IntoIterator>::IntoIter; 113 114 #[inline] 115 fn into_iter(self) -> Self::IntoIter { 116 self.into_vec().into_iter() 117 } 118 } 119 120 impl<T> Deref for OwnedSlice<T> { 121 type Target = [T]; 122 123 #[inline(always)] 124 fn deref(&self) -> &Self::Target { 125 unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) } 126 } 127 } 128 129 impl<T> DerefMut for OwnedSlice<T> { 130 #[inline(always)] 131 fn deref_mut(&mut self) -> &mut Self::Target { 132 unsafe { slice::from_raw_parts_mut(self.ptr.as_ptr(), self.len) } 133 } 134 } 135 136 impl<T> From<Box<[T]>> for OwnedSlice<T> { 137 #[inline] 138 fn from(mut b: Box<[T]>) -> Self { 139 let len = b.len(); 140 let ptr = unsafe { NonNull::new_unchecked(b.as_mut_ptr()) }; 141 mem::forget(b); 142 Self { 143 len, 144 ptr, 145 _phantom: PhantomData, 146 } 147 } 148 } 149 150 impl<T> From<Vec<T>> for OwnedSlice<T> { 151 #[inline] 152 fn from(b: Vec<T>) -> Self { 153 Self::from(b.into_boxed_slice()) 154 } 155 } 156 157 impl<T: Sized> MallocShallowSizeOf for OwnedSlice<T> { 158 fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { 159 unsafe { ops.malloc_size_of(self.ptr.as_ptr()) } 160 } 161 } 162 163 impl<T: MallocSizeOf + Sized> MallocSizeOf for OwnedSlice<T> { 164 fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { 165 self.shallow_size_of(ops) + (**self).size_of(ops) 166 } 167 } 168 169 impl<T: ToShmem + Sized> ToShmem for OwnedSlice<T> { 170 fn to_shmem(&self, builder: &mut SharedMemoryBuilder) -> to_shmem::Result<Self> { 171 unsafe { 172 let dest = to_shmem::to_shmem_slice(self.iter(), builder)?; 173 Ok(mem::ManuallyDrop::new(Self::from(Box::from_raw(dest)))) 174 } 175 } 176 } 177 178 impl<T> iter::FromIterator<T> for OwnedSlice<T> { 179 #[inline] 180 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self { 181 Vec::from_iter(iter).into() 182 } 183 } 184 185 impl<T: Serialize> Serialize for OwnedSlice<T> { 186 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 187 where 188 S: Serializer, 189 { 190 self.deref().serialize(serializer) 191 } 192 } 193 194 impl<'de, T: Deserialize<'de>> Deserialize<'de> for OwnedSlice<T> { 195 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 196 where 197 D: Deserializer<'de>, 198 { 199 let r = Box::<[T]>::deserialize(deserializer)?; 200 Ok(r.into()) 201 } 202 } 203 204 impl<T: Hash> Hash for OwnedSlice<T> { 205 fn hash<H: Hasher>(&self, state: &mut H) { 206 T::hash_slice(&**self, state) 207 } 208 }