1use crate::{BaseLen, Compatible, Decode, DecodeCursor, DecodeError, DecodeResult, Encode, EncodeCursor, Owned};
2
3#[cfg(any(feature = "std", feature = "alloc"))]
4use crate::Lazy;
5
6#[cfg(any(feature = "std", feature = "alloc"))]
7impl<T: Owned + Compatible<T>> Owned for Vec<T> {
8 type Lazy<'a> = ListLazy<'a, T>;
9
10 fn lazy_to_owned(lazy: Self::Lazy<'_>) -> DecodeResult<Self> {
11 lazy.try_into()
12 }
13}
14
15#[cfg(any(feature = "std", feature = "alloc"))]
16impl<'a, T: Owned + Compatible<T>> Lazy<'a> for ListLazy<'a, T> {
17 type Owned = Vec<T>;
18}
19
20#[cfg(any(feature = "std", feature = "alloc"))]
21impl<'a, T, U> core::convert::TryFrom<ListLazy<'a, T>> for Vec<U>
22where
23 T: Owned,
24 U: Decode<'a> + Compatible<T>,
25{
26 type Error = DecodeError;
27
28 fn try_from(other: ListLazy<'a, T>) -> Result<Self, Self::Error> {
29 let cursor = DecodeCursor::at_offset(other.buffer, other.offset);
30 Decode::decode(&cursor)
31 }
32}
33
34impl<T: BaseLen> BaseLen for [T] {
35 const BASE_LEN: usize = 4 + 4;
36}
37
38impl<T: Encode> Encode for [T] {
39 fn scratch_len(&self) -> usize {
40 self.len() * T::BASE_LEN + self.iter().fold(0, |sum, item| sum + item.scratch_len())
41 }
42
43 fn encode(&self, cursor: &mut EncodeCursor) {
44 cursor
45 .base(4)
46 .copy_from_slice(&(self.len() as u32).to_le_bytes());
47
48 cursor.inner_in_scratch(self.len() * T::BASE_LEN, |cursor| {
49 for item in self {
50 item.encode(cursor);
51 }
52 });
53 }
54}
55
56#[cfg(any(feature = "std", feature = "alloc"))]
57impl<T, U: Compatible<T>> Compatible<Vec<T>> for Vec<U> {}
58#[cfg(any(feature = "std", feature = "alloc"))]
59impl<T, U: Compatible<T>> Compatible<Vec<T>> for [U] {}
60#[cfg(any(feature = "std", feature = "alloc"))]
61impl<T, U: Compatible<T>> Compatible<[T]> for Vec<U> {}
62
63impl<'a> Decode<'a> for &'a [u8] {
64 fn decode(cursor: &DecodeCursor<'a>) -> DecodeResult<Self> {
65 let len = u32::from_le_bytes(cursor.base(4).try_into().map_err(|_| DecodeError)?) as usize;
66
67 Ok(cursor.scratch(len))
68 }
69}
70
71#[cfg(any(feature = "std", feature = "alloc"))]
72impl<T: BaseLen> BaseLen for Vec<T> {
73 const BASE_LEN: usize = 4 + 4;
74}
75
76#[cfg(any(feature = "std", feature = "alloc"))]
77impl<T: Encode> Encode for Vec<T> {
78 fn scratch_len(&self) -> usize {
79 self.len() * T::BASE_LEN + self.iter().fold(0, |sum, item| sum + item.scratch_len())
80 }
81
82 fn encode(&self, cursor: &mut EncodeCursor) {
83 cursor
84 .base(4)
85 .copy_from_slice(&(self.len() as u32).to_le_bytes());
86
87 cursor.inner_in_scratch(self.len() * T::BASE_LEN, |cursor| {
88 for item in self {
89 item.encode(cursor);
90 }
91 });
92 }
93}
94
95#[cfg(any(feature = "std", feature = "alloc"))]
96impl<'a, T: Decode<'a>> Decode<'a> for Vec<T> {
97 fn decode(cursor: &DecodeCursor<'a>) -> DecodeResult<Self> {
98 let len = u32::from_le_bytes(cursor.base(4).try_into().map_err(|_| DecodeError)?) as usize;
99
100 cursor.inner_in_scratch(|cursor| {
101 let mut vec = Vec::with_capacity(len);
102 for _ in 0..len {
103 vec.push(T::decode(cursor)?);
104 }
105 Ok(vec)
106 })
107 }
108}
109
110#[cfg(any(feature = "std", feature = "alloc"))]
111impl<'a, T, U> PartialEq<ListLazy<'a, T>> for Vec<U>
112where
113 T: Owned,
114 U: PartialEq<T::Lazy<'a>>,
115{
116 fn eq(&self, other: &ListLazy<'a, T>) -> bool {
117 for (i, item) in self.iter().enumerate() {
118 if *item != other.get(i).unwrap() {
119 return false;
120 }
121 }
122
123 true
124 }
125}
126
127pub struct ListGen<I: ExactSizeIterator>(pub I);
128
129impl<I: ExactSizeIterator> BaseLen for ListGen<I> {
130 const BASE_LEN: usize = 4 + 4;
131}
132
133impl<I: Clone + ExactSizeIterator> Encode for ListGen<I>
134where
135 I::Item: Encode,
136{
137 fn scratch_len(&self) -> usize {
138 self.0.len() * I::Item::BASE_LEN
139 + self.0.clone().fold(0, |sum, item| sum + item.scratch_len())
140 }
141
142 fn encode(&self, cursor: &mut EncodeCursor) {
143 cursor
144 .base(4)
145 .copy_from_slice(&(self.0.len() as u32).to_le_bytes());
146
147 cursor.inner_in_scratch(self.0.len() * I::Item::BASE_LEN, |cursor| {
148 for item in self.0.clone() {
149 item.encode(cursor);
150 }
151 });
152 }
153}
154
155#[cfg(any(feature = "std", feature = "alloc"))]
156impl<T: Owned, U: Compatible<T>, I: Clone + ExactSizeIterator<Item = U>> Compatible<Vec<T>>
157 for ListGen<I>
158{
159}
160
161pub struct ListLazy<'a, T> {
162 buffer: &'a [u8],
163 offset: usize,
164 item_ty: core::marker::PhantomData<T>,
165}
166
167impl<T: Owned, U: Compatible<T>> Compatible<[U]> for ListLazy<'_, T> {}
168impl<T: Owned, U: Compatible<T>> Compatible<ListLazy<'_, T>> for [U] {}
169
170#[cfg(any(feature = "std", feature = "alloc"))]
171impl<T: Owned, U: Compatible<T>> Compatible<Vec<U>> for ListLazy<'_, T> {}
172#[cfg(any(feature = "std", feature = "alloc"))]
173impl<T: Owned, U: Compatible<T>> Compatible<ListLazy<'_, T>> for Vec<U> {}
174
175impl<'a, T: Owned> BaseLen for ListLazy<'a, T> {
176 const BASE_LEN: usize = 4 + 4;
177}
178
179impl<'a, T: Owned> Encode for ListLazy<'a, T> {
180 fn scratch_len(&self) -> usize {
181 self.len() * T::BASE_LEN + self.iter().fold(0, |sum, item| sum + item.scratch_len())
182 }
183
184 fn encode(&self, cursor: &mut EncodeCursor) {
185 cursor
186 .base(4)
187 .copy_from_slice(&(self.len() as u32).to_le_bytes());
188
189 cursor.inner_in_scratch(self.len() * T::BASE_LEN, |cursor| {
190 for item in self {
191 item.encode(cursor);
192 }
193 });
194 }
195}
196
197impl<'a, T: Owned> ListLazy<'a, T> {
198 pub fn len(&self) -> usize {
199 u32::from_le_bytes(
200 self.buffer[self.offset..self.offset + 4]
201 .try_into()
202 .unwrap(),
203 ) as usize
204 }
205
206 pub fn get(&self, index: usize) -> DecodeResult<T::Lazy<'a>> {
207 if index >= self.len() {
208 return Err(DecodeError);
209 }
210
211 let list_scratch_offset = u32::from_le_bytes(
212 self.buffer[self.offset + 4..self.offset + 8]
213 .try_into()
214 .map_err(|_| DecodeError)?,
215 ) as usize;
216
217 Decode::decode(&DecodeCursor::at_offset(
218 self.buffer,
219 list_scratch_offset + (index * T::BASE_LEN),
220 ))
221 }
222
223 pub fn iter<'s>(&'s self) -> ListLazyIter<'s, 'a, T> {
224 let len = self.len();
225 ListLazyIter {
226 list_lazy: self,
227 len,
228 cursor: 0,
229 }
230 }
231}
232
233impl<'a, T: Owned> Decode<'a> for ListLazy<'a, T> {
234 fn decode(cursor: &DecodeCursor<'a>) -> DecodeResult<Self> {
235 let offset = cursor.offset();
236 cursor.advance(Self::BASE_LEN);
237 Ok(ListLazy {
238 buffer: cursor.buffer(),
239 offset,
240 item_ty: core::marker::PhantomData,
241 })
242 }
243}
244
245impl<'s, 'a, T: Owned> IntoIterator for &'s ListLazy<'a, T> {
246 type Item = T::Lazy<'a>;
247 type IntoIter = ListLazyIter<'s, 'a, T>;
248
249 fn into_iter(self) -> Self::IntoIter {
250 let len = self.len();
251 ListLazyIter {
252 list_lazy: self,
253 len,
254 cursor: 0,
255 }
256 }
257}
258
259pub struct ListLazyIter<'s, 'a, T> {
260 list_lazy: &'s ListLazy<'a, T>,
261 len: usize,
262 cursor: usize,
263}
264
265impl<'s, 'a, T: Owned> Iterator for ListLazyIter<'s, 'a, T> {
266 type Item = T::Lazy<'a>;
267
268 fn next(&mut self) -> Option<Self::Item> {
269 let i = self.cursor;
270 self.cursor += 1;
271
272 if i < self.len {
273 Some(self.list_lazy.get(i).unwrap())
274 } else {
275 None
276 }
277 }
278}
279
280impl<'a, T, const N: usize> core::convert::TryInto<[T::Lazy<'a>; N]> for ListLazy<'a, T>
281where
282 T: Owned + Clone,
283 for<'b> T::Lazy<'b>: Sized,
284{
285 type Error = ();
286
287 fn try_into(self) -> Result<[T::Lazy<'a>; N], Self::Error> {
288 use core::mem::MaybeUninit;
289
290 if self.len() != N {
291 return Err(());
292 }
293
294 let mut out: [MaybeUninit<T::Lazy<'_>>; N] =
295 [const { MaybeUninit::<T::Lazy<'_>>::uninit() }; N];
296 for (out, item) in out.iter_mut().zip(self.iter()) {
297 out.write(item);
298 }
299
300 Ok(unsafe { core::mem::transmute_copy(&out) })
308 }
309}
310
311impl<'a> From<ListLazy<'a, u8>> for &'a [u8] {
312 fn from(other: ListLazy<'a, u8>) -> Self {
313 let list_scratch_offset = u32::from_le_bytes(
314 other.buffer[other.offset + 4..other.offset + 8]
315 .try_into()
316 .unwrap(),
317 ) as usize;
318 &other.buffer[list_scratch_offset..list_scratch_offset + other.len()]
319 }
320}
321
322impl<T: Owned> Copy for ListLazy<'_, T> {}
323impl<T: Owned> Clone for ListLazy<'_, T> {
324 fn clone(&self) -> Self {
325 Self {
326 buffer: self.buffer,
327 offset: self.offset,
328 item_ty: core::marker::PhantomData,
329 }
330 }
331}
332impl<T> core::fmt::Debug for ListLazy<'_, T>
333where
334 T: Owned,
335 for<'a> T::Lazy<'a>: core::fmt::Debug,
336{
337 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
338 write!(f, "[")?;
339 for i in 0..self.len() {
340 if i > 0 {
341 write!(f, ", ")?;
342 }
343 write!(f, "{:?}", self.get(i))?;
344 }
345 write!(f, "]")?;
346 Ok(())
347 }
348}
349
350impl<T> PartialEq for ListLazy<'_, T>
351where
352 T: Owned,
353 for<'a> T::Lazy<'a>: PartialEq,
354{
355 fn eq(&self, other: &Self) -> bool {
357 if self.len() != other.len() {
358 return false;
359 }
360 for (item, other_item) in self.iter().zip(other.iter()) {
361 if !item.eq(&other_item) {
362 return false;
363 }
364 }
365 true
366 }
367}
368
369impl<T> Eq for ListLazy<'_, T>
370where
371 T: Owned,
372 for<'a> T::Lazy<'a>: Eq,
373{
374}