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::{
16    fmt,
17    hash::{Hash, Hasher},
18    iter, mem, slice,
19};
20use 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)]
35pub struct OwnedSlice<T: Sized> {
36    ptr: NonNull<T>,
37    len: usize,
38    _phantom: PhantomData<T>,
39}
40
41impl<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
52impl<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
61unsafe impl<T: Sized + Send> Send for OwnedSlice<T> {}
62unsafe impl<T: Sized + Sync> Sync for OwnedSlice<T> {}
63
64impl<T: Clone> Clone for OwnedSlice<T> {
65    #[inline]
66    fn clone(&self) -> Self {
67        Self::from_slice(&**self)
68    }
69}
70
71impl<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
77impl<T: PartialEq> PartialEq for OwnedSlice<T> {
78    fn eq(&self, other: &Self) -> bool {
79        self.deref().eq(other.deref())
80    }
81}
82
83impl<T: Eq> Eq for OwnedSlice<T> {}
84
85impl<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
110impl<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
120impl<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
129impl<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
136impl<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
150impl<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
157impl<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
163impl<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
169impl<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
178impl<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
185impl<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
194impl<'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
204impl<T: Hash> Hash for OwnedSlice<T> {
205    fn hash<H: Hasher>(&self, state: &mut H) {
206        T::hash_slice(&**self, state)
207    }
208}