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 {
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}