light_zero_copy/
slice_mut.rs

1use core::{
2    fmt,
3    mem::size_of,
4    ops::{Index, IndexMut},
5    slice,
6};
7#[cfg(feature = "std")]
8use std::vec::Vec;
9
10use zerocopy::{little_endian::U32, Ref};
11
12use crate::{add_padding, errors::ZeroCopyError, ZeroCopyTraits};
13
14pub type ZeroCopySliceMutU64<'a, T> = ZeroCopySliceMut<'a, u64, T>;
15pub type ZeroCopySliceMutU32<'a, T> = ZeroCopySliceMut<'a, u32, T>;
16pub type ZeroCopySliceMutU16<'a, T> = ZeroCopySliceMut<'a, u16, T>;
17pub type ZeroCopySliceMutU8<'a, T> = ZeroCopySliceMut<'a, u8, T>;
18pub type ZeroCopySliceMutBorsh<'a, T> = ZeroCopySliceMut<'a, U32, T, false>;
19
20pub struct ZeroCopySliceMut<'a, L, T, const PAD: bool = true>
21where
22    L: ZeroCopyTraits,
23    T: ZeroCopyTraits,
24{
25    length: Ref<&'a [u8], L>,
26    bytes: Ref<&'a mut [u8], [T]>,
27}
28
29impl<'a, L, T, const PAD: bool> ZeroCopySliceMut<'a, L, T, PAD>
30where
31    L: ZeroCopyTraits,
32    T: ZeroCopyTraits,
33    u64: From<L>,
34{
35    pub fn new(length: L, bytes: &'a mut [u8]) -> Result<Self, ZeroCopyError> {
36        Ok(Self::new_at(length, bytes)?.0)
37    }
38
39    pub fn new_at(length: L, bytes: &'a mut [u8]) -> Result<(Self, &'a mut [u8]), ZeroCopyError> {
40        let len = Self::required_size_for_capacity(length);
41        if len > bytes.len() {
42            return Err(ZeroCopyError::InsufficientMemoryAllocated(bytes.len(), len));
43        }
44        // write new value then deserialize as immutable
45        {
46            let (mut len, _) = Ref::<&mut [u8], L>::from_prefix(bytes)?;
47            if u64::from(*len) != 0 {
48                return Err(ZeroCopyError::MemoryNotZeroed);
49            }
50            Ref::<&mut [u8], L>::write(&mut len, length);
51        }
52        Self::from_bytes_at(bytes)
53    }
54
55    #[inline]
56    pub fn from_bytes(bytes: &'a mut [u8]) -> Result<Self, ZeroCopyError> {
57        Ok(Self::from_bytes_at(bytes)?.0)
58    }
59
60    #[inline]
61    pub fn from_bytes_at(
62        bytes: &'a mut [u8],
63    ) -> Result<(ZeroCopySliceMut<'a, L, T, PAD>, &'a mut [u8]), ZeroCopyError> {
64        let metadata_size = Self::metadata_size();
65        if bytes.len() < metadata_size {
66            return Err(ZeroCopyError::InsufficientMemoryAllocated(
67                bytes.len(),
68                metadata_size,
69            ));
70        }
71
72        let (meta_data, bytes) = bytes.split_at_mut(metadata_size);
73        let (length, _padding) = Ref::<&[u8], L>::from_prefix(meta_data)?;
74        let usize_len: usize = u64::from(*length) as usize;
75        let full_vector_size = Self::data_size(*length);
76        if bytes.len() < full_vector_size {
77            return Err(ZeroCopyError::InsufficientMemoryAllocated(
78                bytes.len() + metadata_size,
79                full_vector_size + metadata_size,
80            ));
81        }
82        let (bytes, remaining_bytes) =
83            Ref::<&mut [u8], [T]>::from_prefix_with_elems(bytes, usize_len)?;
84        Ok((ZeroCopySliceMut { length, bytes }, remaining_bytes))
85    }
86
87    #[cfg(feature = "std")]
88    pub fn try_into_array<const N: usize>(&self) -> Result<[T; N], ZeroCopyError> {
89        if self.len() != N {
90            return Err(ZeroCopyError::ArraySize(N, self.len()));
91        }
92        Ok(core::array::from_fn(|i| *self.get(i).unwrap()))
93    }
94
95    #[inline]
96    pub fn metadata_size() -> usize {
97        let mut size = size_of::<L>();
98        if PAD {
99            add_padding::<L, T>(&mut size);
100        }
101        size
102    }
103
104    #[inline]
105    pub fn data_size(length: L) -> usize {
106        let usize_len: usize = u64::from(length) as usize;
107        usize_len.saturating_mul(size_of::<T>())
108    }
109
110    #[inline]
111    pub fn required_size_for_capacity(capacity: L) -> usize {
112        Self::metadata_size().saturating_add(Self::data_size(capacity))
113    }
114
115    #[inline]
116    pub fn len(&self) -> usize {
117        let usize_len: usize = u64::from(*self.length) as usize;
118        usize_len
119    }
120
121    #[inline]
122    pub fn is_empty(&self) -> bool {
123        self.len() == 0
124    }
125
126    #[inline]
127    pub fn first(&self) -> Option<&T> {
128        self.get(0)
129    }
130
131    #[inline]
132    pub fn first_mut(&mut self) -> Option<&mut T> {
133        self.get_mut(0)
134    }
135
136    #[inline]
137    pub fn last(&self) -> Option<&T> {
138        self.get(self.len().saturating_sub(1))
139    }
140
141    #[inline]
142    pub fn last_mut(&mut self) -> Option<&mut T> {
143        self.get_mut(self.len().saturating_sub(1))
144    }
145
146    #[inline]
147    pub fn as_slice(&self) -> &[T] {
148        self.bytes.as_ref()
149    }
150
151    #[inline]
152    pub fn as_mut_slice(&mut self) -> &mut [T] {
153        self.bytes.as_mut()
154    }
155
156    #[inline]
157    pub fn data_as_ptr(&self) -> *const T {
158        self.as_slice().as_ptr()
159    }
160
161    #[inline]
162    pub fn data_as_mut_ptr(&mut self) -> *mut T {
163        self.as_mut_slice().as_mut_ptr()
164    }
165
166    #[inline]
167    pub fn get(&self, index: usize) -> Option<&T> {
168        self.as_slice().get(index)
169    }
170
171    #[inline]
172    pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
173        self.as_mut_slice().get_mut(index)
174    }
175
176    #[cfg(feature = "std")]
177    #[inline]
178    pub fn to_vec(&self) -> Vec<T> {
179        self.as_slice().to_vec()
180    }
181}
182
183impl<L, T, const PAD: bool> IndexMut<usize> for ZeroCopySliceMut<'_, L, T, PAD>
184where
185    L: ZeroCopyTraits,
186    T: ZeroCopyTraits,
187    u64: From<L>,
188{
189    #[inline]
190    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
191        &mut self.as_mut_slice()[index]
192    }
193}
194
195impl<L, T, const PAD: bool> Index<usize> for ZeroCopySliceMut<'_, L, T, PAD>
196where
197    L: ZeroCopyTraits,
198    T: ZeroCopyTraits,
199    u64: From<L>,
200{
201    type Output = T;
202
203    #[inline]
204    fn index(&self, index: usize) -> &Self::Output {
205        &self.as_slice()[index]
206    }
207}
208
209impl<'a, L, T, const PAD: bool> IntoIterator for &'a ZeroCopySliceMut<'_, L, T, PAD>
210where
211    L: ZeroCopyTraits,
212    T: ZeroCopyTraits,
213    u64: From<L>,
214{
215    type Item = &'a T;
216    type IntoIter = slice::Iter<'a, T>;
217
218    #[inline]
219    fn into_iter(self) -> Self::IntoIter {
220        self.iter()
221    }
222}
223
224impl<'a, L, T, const PAD: bool> IntoIterator for &'a mut ZeroCopySliceMut<'_, L, T, PAD>
225where
226    L: ZeroCopyTraits,
227    T: ZeroCopyTraits,
228    u64: From<L>,
229{
230    type Item = &'a mut T;
231    type IntoIter = slice::IterMut<'a, T>;
232
233    #[inline]
234    fn into_iter(self) -> Self::IntoIter {
235        self.iter_mut()
236    }
237}
238
239impl<'a, L, T, const PAD: bool> ZeroCopySliceMut<'_, L, T, PAD>
240where
241    L: ZeroCopyTraits,
242    T: ZeroCopyTraits,
243    u64: From<L>,
244{
245    #[inline]
246    pub fn iter(&'a self) -> slice::Iter<'a, T> {
247        self.as_slice().iter()
248    }
249
250    #[inline]
251    pub fn iter_mut(&'a mut self) -> slice::IterMut<'a, T> {
252        self.as_mut_slice().iter_mut()
253    }
254}
255
256impl<L, T, const PAD: bool> PartialEq for ZeroCopySliceMut<'_, L, T, PAD>
257where
258    L: ZeroCopyTraits,
259    T: ZeroCopyTraits + PartialEq,
260    u64: From<L>,
261{
262    #[inline]
263    fn eq(&self, other: &Self) -> bool {
264        self.as_slice() == other.as_slice()
265    }
266}
267
268impl<L, T, const PAD: bool> fmt::Debug for ZeroCopySliceMut<'_, L, T, PAD>
269where
270    T: ZeroCopyTraits + fmt::Debug,
271    L: ZeroCopyTraits,
272    u64: From<L>,
273{
274    #[inline]
275    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
276        write!(f, "{:?}", self.as_slice())
277    }
278}
279
280#[cfg(feature = "std")]
281impl<'a, T: ZeroCopyTraits + crate::traits::ZeroCopyAtMut<'a>> crate::traits::ZeroCopyAtMut<'a>
282    for ZeroCopySliceMutBorsh<'_, T>
283{
284    type ZeroCopyAtMut = ZeroCopySliceMutBorsh<'a, T>;
285
286    fn zero_copy_at_mut(
287        bytes: &'a mut [u8],
288    ) -> Result<(Self::ZeroCopyAtMut, &'a mut [u8]), ZeroCopyError> {
289        ZeroCopySliceMutBorsh::from_bytes_at(bytes)
290    }
291}