1use std::{
2 fmt::{Debug, Display},
3 marker::PhantomData,
4 mem::{ManuallyDrop, MaybeUninit},
5 ops::{Add, Mul, Sub},
6 vec,
7};
8
9use bytemuck::{box_bytes_of, from_box_bytes, BoxBytes, Pod};
10use derive_more::derive::{AsMut, AsRef, Deref, DerefMut, IntoIterator};
11use hybrid_array::{Array, ArraySize};
12use rayon::iter::IntoParallelIterator;
13use serde::{Deserialize, Serialize};
14use typenum::{Diff, Prod, Sum, U1, U2, U3};
15use wincode::{
16 io::{Reader, Writer},
17 ReadResult,
18 SchemaRead,
19 SchemaWrite,
20 TypeMeta,
21 WriteResult,
22};
23
24use crate::{errors::PrimitiveError, types::Positive};
25
26#[derive(Deref, DerefMut, Clone, IntoIterator, AsRef, AsMut, Eq)]
28#[into_iterator(owned, ref, ref_mut)]
29pub struct HeapArray<T: Sized, M: Positive> {
30 #[deref]
31 #[deref_mut]
32 #[as_ref(forward)]
33 #[as_mut(forward)]
34 pub(super) data: Box<[T]>,
35 #[into_iterator(ignore)]
36 pub(super) _len: PhantomData<fn() -> M>,
39}
40
41impl<T: Sized, M: Positive> HeapArray<T, M> {
42 pub(super) fn new(data: Box<[T]>) -> Self {
43 Self {
44 data,
45 _len: PhantomData,
46 }
47 }
48}
49
50impl<T: Pod, M: Positive> HeapArray<T, M> {
52 pub fn into_box_bytes(self) -> BoxBytes {
53 box_bytes_of(self.data)
54 }
55
56 pub fn from_box_bytes(buf: BoxBytes) -> Self {
57 Self {
58 data: from_box_bytes(buf),
59 _len: PhantomData,
60 }
61 }
62}
63
64impl<T: Sized, M: Positive> HeapArray<T, M> {
65 pub fn map<F, U>(self, f: F) -> HeapArray<U, M>
66 where
67 F: FnMut(T) -> U,
68 {
69 self.into_iter().map(f).collect()
70 }
71}
72
73impl<T: Sized + Default, M: Positive> HeapArray<T, M> {
74 pub fn from_single_value(val: T) -> Self {
75 Self {
76 data: vec![val].into_boxed_slice(),
77 _len: PhantomData,
78 }
79 }
80}
81
82impl<T: Sized + Default, M: Positive> Default for HeapArray<T, M> {
83 fn default() -> Self {
84 Self {
85 data: (0..M::USIZE).map(|_| T::default()).collect(),
86 _len: PhantomData,
87 }
88 }
89}
90
91impl<T: Sized + Debug, M: Positive> Debug for HeapArray<T, M> {
92 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93 f.debug_struct(format!("HeapArray<{}>", M::USIZE).as_str())
94 .field("data", &self.data)
95 .finish()
96 }
97}
98
99impl<T: Sized + Serialize, M: Positive> Serialize for HeapArray<T, M> {
100 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
101 use serde::ser::SerializeTuple;
102 let mut tuple = serializer.serialize_tuple(M::USIZE)?;
103 for element in self.data.iter() {
104 tuple.serialize_element(element)?;
105 }
106 tuple.end()
107 }
108}
109
110impl<'de, T: Sized + Deserialize<'de>, M: Positive> Deserialize<'de> for HeapArray<T, M> {
111 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
112 struct HeapArrayVisitor<T, M: Positive> {
113 _phantom: PhantomData<(T, M)>,
114 }
115
116 impl<'de, T: Deserialize<'de>, M: Positive> serde::de::Visitor<'de> for HeapArrayVisitor<T, M> {
117 type Value = HeapArray<T, M>;
118
119 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
120 write!(formatter, "a tuple of {} elements", M::USIZE)
121 }
122
123 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
124 where
125 A: serde::de::SeqAccess<'de>,
126 {
127 let mut data = Vec::with_capacity(M::USIZE);
128 for i in 0..M::USIZE {
129 let element = seq
130 .next_element()?
131 .ok_or_else(|| serde::de::Error::invalid_length(i, &self))?;
132 data.push(element);
133 }
134
135 Ok(HeapArray {
136 data: data.into_boxed_slice(),
137 _len: PhantomData,
138 })
139 }
140 }
141
142 deserializer.deserialize_tuple(
143 M::USIZE,
144 HeapArrayVisitor {
145 _phantom: PhantomData,
146 },
147 )
148 }
149}
150
151impl<T: Sized + SchemaWrite<Src = T>, M: Positive> SchemaWrite for HeapArray<T, M> {
152 type Src = HeapArray<T, M>;
153
154 const TYPE_META: wincode::TypeMeta = match <T as SchemaWrite>::TYPE_META {
155 TypeMeta::Static { size, zero_copy } => TypeMeta::Static {
156 size: size * M::USIZE,
157 zero_copy,
158 },
159 TypeMeta::Dynamic => TypeMeta::Dynamic,
160 };
161
162 #[inline]
163 fn size_of(src: &Self::Src) -> WriteResult<usize> {
164 if let TypeMeta::Static { size, .. } = <Self as SchemaWrite>::TYPE_META {
165 return Ok(size);
166 }
167
168 src.iter()
170 .map(T::size_of)
171 .try_fold(0usize, |acc, x| x.map(|x| acc + x))
172 }
173
174 #[inline]
175 fn write(writer: &mut impl Writer, src: &Self::Src) -> WriteResult<()> {
176 if let TypeMeta::Static {
177 size,
178 zero_copy: true,
179 } = <Self as SchemaWrite>::TYPE_META
180 {
181 let writer = &mut unsafe { writer.as_trusted_for(size) }?;
184 unsafe { writer.write_slice_t(&src.data)? };
187 writer.finish()?;
188 } else if let TypeMeta::Static { size, .. } = <Self as SchemaWrite>::TYPE_META {
189 #[allow(clippy::arithmetic_side_effects)]
190 let mut writer = unsafe { writer.as_trusted_for(size) }?;
194 for item in src {
195 T::write(&mut writer, item)?;
196 }
197 writer.finish()?;
198 } else {
199 for item in src {
200 T::write(writer, item)?;
201 }
202 }
203
204 Ok(())
205 }
206}
207
208pub(crate) struct SliceDropGuard<T> {
209 ptr: *mut MaybeUninit<T>,
210 initialized_len: usize,
211}
212
213impl<T> SliceDropGuard<T> {
214 pub(crate) fn new(ptr: *mut MaybeUninit<T>) -> Self {
215 Self {
216 ptr,
217 initialized_len: 0,
218 }
219 }
220
221 #[inline(always)]
222 #[allow(clippy::arithmetic_side_effects)]
223 pub(crate) fn inc_len(&mut self) {
224 self.initialized_len += 1;
225 }
226}
227
228impl<T> Drop for SliceDropGuard<T> {
229 #[inline(always)]
230 fn drop(&mut self) {
231 unsafe {
232 std::ptr::drop_in_place(std::ptr::slice_from_raw_parts_mut(
233 self.ptr.cast::<T>(),
234 self.initialized_len,
235 ));
236 }
237 }
238}
239
240impl<'de, T: Sized + SchemaRead<'de, Dst = T>, M: Positive> SchemaRead<'de> for HeapArray<T, M> {
241 type Dst = HeapArray<T::Dst, M>;
242
243 const TYPE_META: TypeMeta = const {
244 match T::TYPE_META {
245 TypeMeta::Static { size, zero_copy } => TypeMeta::Static {
246 size: M::USIZE * size,
247 zero_copy,
248 },
249 TypeMeta::Dynamic => TypeMeta::Dynamic,
250 }
251 };
252
253 #[inline]
254 fn read(reader: &mut impl Reader<'de>, dst: &mut MaybeUninit<Self::Dst>) -> ReadResult<()> {
255 struct DropGuardRawCopy<T>(*mut [MaybeUninit<T>]);
260 impl<T> Drop for DropGuardRawCopy<T> {
261 #[inline]
262 fn drop(&mut self) {
263 let container = unsafe { Box::from_raw(self.0) };
264 drop(container);
265 }
266 }
267 struct DropGuardElemCopy<T> {
272 inner: ManuallyDrop<SliceDropGuard<T>>,
273 fat: *mut [MaybeUninit<T>],
274 }
275 impl<T> DropGuardElemCopy<T> {
276 #[inline(always)]
277 fn new(fat: *mut [MaybeUninit<T>], raw: *mut MaybeUninit<T>) -> Self {
278 Self {
279 inner: ManuallyDrop::new(SliceDropGuard::new(raw)),
280 fat,
281 }
282 }
283 }
284 impl<T> Drop for DropGuardElemCopy<T> {
285 #[inline]
286 fn drop(&mut self) {
287 unsafe {
288 ManuallyDrop::drop(&mut self.inner);
289 }
290 let container = unsafe { Box::from_raw(self.fat) };
291 drop(container);
292 }
293 }
294 let mem = Box::<[T::Dst]>::new_uninit_slice(M::USIZE);
295 let fat = Box::into_raw(mem);
296 match T::TYPE_META {
297 TypeMeta::Static {
298 zero_copy: true, ..
299 } => {
300 let guard = DropGuardRawCopy(fat);
301 let dst = unsafe { &mut *fat };
302 unsafe { reader.copy_into_slice_t(dst)? };
303 std::mem::forget(guard);
304 }
305 TypeMeta::Static {
306 size,
307 zero_copy: false,
308 } => {
309 let raw_base = unsafe { (*fat).as_mut_ptr() };
310 let mut guard: DropGuardElemCopy<T::Dst> = DropGuardElemCopy::new(fat, raw_base);
311 #[allow(clippy::arithmetic_side_effects)]
312 let reader = &mut unsafe { reader.as_trusted_for(size * M::USIZE) }?;
313 for i in 0..M::USIZE {
314 let slot = unsafe { &mut *raw_base.add(i) };
315 T::read(reader, slot)?;
316 guard.inner.inc_len();
317 }
318 std::mem::forget(guard);
319 }
320 TypeMeta::Dynamic => {
321 let raw_base = unsafe { (*fat).as_mut_ptr() };
322 let mut guard: DropGuardElemCopy<T::Dst> = DropGuardElemCopy::new(fat, raw_base);
323 for i in 0..M::USIZE {
324 let slot = unsafe { &mut *raw_base.add(i) };
325 T::read(reader, slot)?;
326 guard.inner.inc_len();
327 }
328 std::mem::forget(guard);
329 }
330 }
331 let container = unsafe { Box::from_raw(fat) };
332 let container = unsafe { container.assume_init().try_into().unwrap() };
333 dst.write(container);
334 Ok(())
335 }
336}
337
338impl<T: Sized, M: Positive> FromIterator<T> for HeapArray<T, M> {
339 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
340 let data = iter.into_iter().collect::<Box<_>>();
341 assert_eq!(data.len(), M::USIZE,);
342 Self {
343 data,
344 _len: PhantomData,
345 }
346 }
347}
348
349impl<T: Sized + Send, M: Positive> IntoParallelIterator for HeapArray<T, M> {
350 type Item = T;
351 type Iter = rayon::vec::IntoIter<T>;
352
353 fn into_par_iter(self) -> Self::Iter {
354 self.data.into_par_iter()
355 }
356}
357
358impl<T: Sized + Copy, M: Positive> HeapArray<T, M> {
363 pub fn split<M1, M2>(&self) -> (HeapArray<T, M1>, HeapArray<T, M2>)
364 where
365 M1: Positive,
366 M2: Positive + Add<M1, Output = M>,
367 {
368 let (m1, m2) = self.split_at(M1::USIZE);
369 (
370 HeapArray::<T, M1> {
371 data: m1.into(),
372 _len: PhantomData,
373 },
374 HeapArray::<T, M2> {
375 data: m2.into(),
376 _len: PhantomData,
377 },
378 )
379 }
380
381 pub fn split_halves<MDiv2>(&self) -> (HeapArray<T, MDiv2>, HeapArray<T, MDiv2>)
382 where
383 MDiv2: Positive + Mul<U2, Output = M>,
384 {
385 let (m1, m2) = self.split_at(MDiv2::USIZE);
386 (
387 HeapArray::<T, MDiv2> {
388 data: m1.into(),
389 _len: PhantomData,
390 },
391 HeapArray::<T, MDiv2> {
392 data: m2.into(),
393 _len: PhantomData,
394 },
395 )
396 }
397
398 pub fn merge_halves(this: Self, other: Self) -> HeapArray<T, Prod<M, U2>>
399 where
400 M: Mul<U2, Output: Positive>,
401 {
402 let mut vec = this.data.into_vec();
403 vec.extend(other.data.into_vec());
404 HeapArray::<T, Prod<M, U2>> {
405 data: vec.into_boxed_slice(),
406 _len: PhantomData,
407 }
408 }
409
410 pub fn split3<M1, M2, M3>(&self) -> (HeapArray<T, M1>, HeapArray<T, M2>, HeapArray<T, M3>)
411 where
412 M1: Positive,
413 M2: Positive + Add<M1>,
414 M3: Positive + Add<Sum<M2, M1>, Output = M>,
415 {
416 let (m1, m_rest) = self.split_at(M1::USIZE);
417 let (m2, m3) = m_rest.split_at(M2::USIZE);
418 (
419 HeapArray::<T, M1> {
420 data: m1.into(),
421 _len: PhantomData,
422 },
423 HeapArray::<T, M2> {
424 data: m2.into(),
425 _len: PhantomData,
426 },
427 HeapArray::<T, M3> {
428 data: m3.into(),
429 _len: PhantomData,
430 },
431 )
432 }
433
434 pub fn split_thirds<MDiv3>(
435 &self,
436 ) -> (
437 HeapArray<T, MDiv3>,
438 HeapArray<T, MDiv3>,
439 HeapArray<T, MDiv3>,
440 )
441 where
442 MDiv3: Positive + Mul<U3, Output = M>,
443 {
444 let (m1, m_rest) = self.split_at(MDiv3::USIZE);
445 let (m2, m3) = m_rest.split_at(MDiv3::USIZE);
446 (
447 HeapArray::<T, MDiv3> {
448 data: m1.into(),
449 _len: PhantomData,
450 },
451 HeapArray::<T, MDiv3> {
452 data: m2.into(),
453 _len: PhantomData,
454 },
455 HeapArray::<T, MDiv3> {
456 data: m3.into(),
457 _len: PhantomData,
458 },
459 )
460 }
461
462 pub fn merge_thirds(first: Self, second: Self, third: Self) -> HeapArray<T, Prod<M, U3>>
463 where
464 M: Mul<U3, Output: Positive>,
465 {
466 let mut vec = first.data.into_vec();
467 vec.extend(second.data.into_vec());
468 vec.extend(third.data.into_vec());
469 HeapArray::<T, Prod<M, U3>> {
470 data: vec.into_boxed_slice(),
471 _len: PhantomData,
472 }
473 }
474}
475
476pub struct HeapArrayTuple<T1: Sized, T2: Sized, M: Positive>(
477 pub HeapArray<T1, M>,
478 pub HeapArray<T2, M>,
479);
480
481impl<T1: Sized, T2: Sized, M: Positive> FromIterator<(T1, T2)> for HeapArrayTuple<T1, T2, M> {
482 fn from_iter<I: IntoIterator<Item = (T1, T2)>>(iter: I) -> Self {
483 let (data1, data2): (Vec<_>, Vec<_>) = iter.into_iter().unzip();
484
485 assert_eq!(data1.len(), M::USIZE);
486 assert_eq!(data2.len(), M::USIZE);
487 HeapArrayTuple(
488 HeapArray::<T1, M> {
489 data: data1.into_boxed_slice(),
490 _len: PhantomData,
491 },
492 HeapArray::<T2, M> {
493 data: data2.into_boxed_slice(),
494 _len: PhantomData,
495 },
496 )
497 }
498}
499
500impl<T: Sized, M: Positive> TryFrom<Vec<T>> for HeapArray<T, M> {
501 type Error = PrimitiveError;
502
503 fn try_from(data: Vec<T>) -> Result<Self, PrimitiveError> {
504 if data.len() == M::USIZE {
505 Ok(Self {
506 data: data.into_boxed_slice(),
507 _len: PhantomData,
508 })
509 } else {
510 Err(PrimitiveError::InvalidSize(M::USIZE, data.len()))
511 }
512 }
513}
514
515impl<T: Sized, M: Positive> TryFrom<Box<[T]>> for HeapArray<T, M> {
516 type Error = PrimitiveError;
517
518 fn try_from(data: Box<[T]>) -> Result<Self, PrimitiveError> {
519 if data.len() == M::USIZE {
520 Ok(Self {
521 data,
522 _len: PhantomData,
523 })
524 } else {
525 Err(PrimitiveError::InvalidSize(M::USIZE, data.len()))
526 }
527 }
528}
529
530impl<T: Sized> From<T> for HeapArray<T, U1> {
531 fn from(element: T) -> Self {
532 Self {
533 data: Box::new([element]),
534 _len: PhantomData,
535 }
536 }
537}
538
539impl<T: Sized, M: Positive> From<HeapArray<T, M>> for Vec<T> {
540 fn from(array: HeapArray<T, M>) -> Self {
541 array.data.into_vec()
542 }
543}
544
545impl<T: Sized + Clone, M: Positive + ArraySize> From<Array<T, M>> for HeapArray<T, M> {
546 fn from(array: Array<T, M>) -> Self {
547 Self {
548 data: array.to_vec().into_boxed_slice(),
549 _len: PhantomData,
550 }
551 }
552}
553
554impl<T: Sized, M: Positive> HeapArray<T, M> {
555 pub fn split_last<N: Positive>(self) -> (HeapArray<T, Diff<M, N>>, HeapArray<T, N>)
556 where
557 M: Sub<N, Output: Positive>,
558 {
559 let mut vec = self.data.into_vec();
560 let last_n = vec.split_off(M::USIZE - N::USIZE);
561
562 (
563 HeapArray {
564 data: vec.into_boxed_slice(),
565 _len: PhantomData,
566 },
567 HeapArray {
568 data: last_n.into_boxed_slice(),
569 _len: PhantomData,
570 },
571 )
572 }
573
574 pub fn from_fn(f: impl FnMut(usize) -> T) -> Self {
575 Self {
576 data: (0..M::USIZE).map(f).collect::<Box<_>>(),
577 _len: PhantomData,
578 }
579 }
580
581 pub fn from_constant(c: T) -> Self
582 where
583 T: Copy,
584 {
585 Self {
586 data: (0..M::USIZE).map(|_| c).collect::<Box<_>>(),
587 _len: PhantomData,
588 }
589 }
590}
591
592impl<T: Sized, M: Positive> Display for HeapArray<T, M>
593where
594 T: Display,
595{
596 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
597 write!(f, "[")?;
598 for (i, item) in self.data.iter().enumerate() {
599 if i != 0 {
600 write!(f, ", ")?;
601 }
602 write!(f, "{item}")?;
603 }
604 write!(f, "]")
605 }
606}
607
608#[cfg(test)]
609pub mod tests {
610 use hybrid_array::sizes::{U2, U3, U6};
611 use typenum::{U1, U4};
612
613 use super::*;
614
615 #[test]
616 fn test_heap_array() {
617 let array = HeapArray::<_, U3>::from_fn(|i| i);
618 assert_eq!(array.into_iter().collect::<Vec<_>>(), vec![0, 1, 2]);
619 }
620
621 #[test]
622 fn test_default() {
623 let array = HeapArray::<usize, U3>::default();
624 assert_eq!(array.len(), 3);
625 }
626
627 #[test]
628 fn test_heap_array_split_last() {
629 let array = HeapArray::<_, U6>::from_fn(|i| i);
630 let (first, last) = array.split_last::<U2>();
631 assert_eq!(first.into_iter().collect::<Vec<_>>(), vec![0, 1, 2, 3]);
632 assert_eq!(last.into_iter().collect::<Vec<_>>(), vec![4, 5]);
633 }
634
635 #[test]
636 fn test_heap_array_from_array() {
637 let array = Array::<_, U3>::from_fn(|i| i);
638 let heap_array = HeapArray::<_, U3>::from(array);
639 assert_eq!(heap_array.into_iter().collect::<Vec<_>>(), vec![0, 1, 2]);
640 }
641
642 #[test]
643 fn test_heap_array_from_vec() {
644 let vec = vec![0, 1, 2];
645 let heap_array = HeapArray::<_, U3>::try_from(vec).unwrap();
646 assert_eq!(heap_array.into_iter().collect::<Vec<_>>(), vec![0, 1, 2]);
647
648 let vec = vec![0, 1];
649 let heap_array = HeapArray::<_, U3>::try_from(vec);
650 assert!(heap_array.is_err());
651 }
652
653 #[test]
654 fn test_heap_array_from_iter() {
655 let heap_array = HeapArray::<_, U3>::from_fn(|i| i);
656 assert_eq!(heap_array.into_iter().collect::<Vec<_>>(), vec![0, 1, 2]);
657 }
658
659 #[test]
660 #[should_panic]
661 fn test_heap_array_from_iter_wrong_size() {
662 HeapArray::<_, U2>::from_iter(0..3);
663 }
664
665 #[test]
666 fn test_heap_array_deserialize() {
667 let array = HeapArray::<usize, U6>::from_fn(|i| i);
668 let serialized = bincode::serialize(&array).unwrap();
669 bincode::deserialize::<HeapArray<usize, U6>>(&serialized).unwrap();
670
671 use bincode::Options;
675 let config = bincode::DefaultOptions::new()
676 .with_fixint_encoding()
677 .reject_trailing_bytes();
678
679 let wrong_deserialize = config.deserialize::<HeapArray<usize, U3>>(&serialized);
680 assert!(wrong_deserialize.is_err());
681 }
682
683 #[test]
684 fn test_heap_array_split() {
685 let array = HeapArray::<_, U6>::from_fn(|i| i);
686 let (first, second) = array.split::<U4, U2>();
687 assert_eq!(first.into_iter().collect::<Vec<_>>(), vec![0, 1, 2, 3]);
688 assert_eq!(second.into_iter().collect::<Vec<_>>(), vec![4, 5]);
689
690 let (first, second) = array.split_halves::<U3>();
691 assert_eq!(first.into_iter().collect::<Vec<_>>(), vec![0, 1, 2]);
692 assert_eq!(second.into_iter().collect::<Vec<_>>(), vec![3, 4, 5]);
693
694 }
698
699 #[test]
700 fn test_heap_array_split3() {
701 let array = HeapArray::<_, U6>::from_fn(|i| i);
702 let (first, second, third) = array.split3::<U3, U2, U1>();
703 assert_eq!(first.into_iter().collect::<Vec<_>>(), vec![0, 1, 2]);
704 assert_eq!(second.into_iter().collect::<Vec<_>>(), vec![3, 4]);
705 assert_eq!(third.into_iter().collect::<Vec<_>>(), vec![5]);
706
707 let (first, second, third) = array.split_thirds::<U2>();
708 assert_eq!(first.into_iter().collect::<Vec<_>>(), vec![0, 1]);
709 assert_eq!(second.into_iter().collect::<Vec<_>>(), vec![2, 3]);
710 assert_eq!(third.into_iter().collect::<Vec<_>>(), vec![4, 5]);
711
712 }
716
717 #[test]
718 fn test_heap_array_wincode_roundtrip() {
719 let array = HeapArray::<u32, U4>::from_fn(|i| (i * 10) as u32);
721 let ser = wincode::serialize(&array).unwrap();
722 let bin_ser = bincode::serialize(&array).unwrap();
723 let deserialized: HeapArray<u32, U4> = wincode::deserialize(&ser).unwrap();
724
725 assert_eq!(ser, bin_ser);
726 assert_eq!(deserialized, array);
727
728 #[derive(
730 Debug, Copy, Clone, PartialEq, SchemaRead, SchemaWrite, Serialize, Deserialize,
731 )]
732 struct NonZeroCopy {
733 a: u8,
734 b: u16,
735 }
736 let array = HeapArray::<NonZeroCopy, U3>::from_fn(|i| NonZeroCopy {
737 a: i as u8,
738 b: (i * 100) as u16,
739 });
740 let ser = wincode::serialize(&array).unwrap();
741 let bin_ser = bincode::serialize(&array).unwrap();
742 let deserialized: HeapArray<NonZeroCopy, U3> = wincode::deserialize(&ser).unwrap();
743 assert_eq!(ser, bin_ser);
744 assert_eq!(deserialized, array);
745
746 let array = HeapArray::<String, U2>::from_fn(|i| format!("String {i}"));
748 let ser = wincode::serialize(&array).unwrap();
749 let bin_ser = bincode::serialize(&array).unwrap();
750 let deserialized: HeapArray<String, U2> = wincode::deserialize(&ser).unwrap();
751 assert_eq!(ser, bin_ser);
752 assert_eq!(deserialized, array);
753 }
754}