style_traits/
owned_slice.rs

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