1use std::{
2 fmt::{Debug, Display},
3 marker::PhantomData,
4 mem::MaybeUninit,
5 ops::{Add, Mul, Sub},
6 sync::Arc,
7 vec,
8};
9
10use bytemuck::{box_bytes_of, from_box_bytes, BoxBytes, Pod};
11use derive_more::derive::{AsMut, AsRef, Deref, DerefMut, IntoIterator};
12use hybrid_array::{Array, ArraySize};
13use rayon::iter::{FromParallelIterator, IntoParallelIterator, ParallelIterator};
14use serde::{Deserialize, Serialize};
15use typenum::{Diff, Prod, Sum, Unsigned, U1, U2, U3, U5};
16
17use crate::{
18 errors::PrimitiveError,
19 types::Positive,
20 utils::codec::{packed_size, read_packed_le_bytes, write_packed_le_bytes, InPlaceCodec},
21};
22
23#[derive(Deref, DerefMut, Clone, IntoIterator, AsRef, AsMut, Eq)]
25#[into_iterator(owned, ref, ref_mut)]
26pub struct HeapArray<T: Sized, M: Positive> {
27 #[deref]
28 #[deref_mut]
29 #[as_ref(forward)]
30 #[as_mut(forward)]
31 pub(super) data: Box<[T]>,
32 #[into_iterator(ignore)]
33 pub(super) _len: PhantomData<fn() -> M>,
36}
37
38impl<T: Sized, M: Positive> HeapArray<T, M> {
39 pub(super) fn new(data: Box<[T]>) -> Self {
40 Self {
41 data,
42 _len: PhantomData,
43 }
44 }
45}
46
47impl<T: Sized, M: Positive> HeapArray<T, M> {
48 pub fn peel_transparent<U>(self) -> HeapArray<U, M>
50 where
51 T: bytemuck::TransparentWrapper<U>,
52 {
53 use bytemuck::allocation::TransparentWrapperAlloc;
54 HeapArray::new(T::peel_vec(self.data.into_vec()).into_boxed_slice())
55 }
56
57 pub fn wrap_transparent<W>(self) -> HeapArray<W, M>
59 where
60 W: bytemuck::TransparentWrapper<T>,
61 {
62 use bytemuck::allocation::TransparentWrapperAlloc;
63 HeapArray::new(W::wrap_vec(self.data.into_vec()).into_boxed_slice())
64 }
65}
66
67impl<T: Pod, M: Positive> HeapArray<T, M> {
69 pub fn into_box_bytes(self) -> BoxBytes {
70 box_bytes_of(self.data)
71 }
72
73 pub fn from_box_bytes(buf: BoxBytes) -> Self {
74 Self {
75 data: from_box_bytes(buf),
76 _len: PhantomData,
77 }
78 }
79}
80
81unsafe impl<T: InPlaceCodec, M: Positive> InPlaceCodec for HeapArray<T, M> {
85 const ENCODED_SIZE: usize = packed_size::<T>(M::USIZE);
86
87 fn write_le_bytes(&self, out: &mut [MaybeUninit<u8>]) {
88 write_packed_le_bytes(&self.data, out);
89 }
90
91 fn read_le_bytes(bytes: &[u8]) -> Result<Self, PrimitiveError> {
92 let mut data = Box::<[T]>::new_uninit_slice(M::USIZE);
93 read_packed_le_bytes(bytes, &mut data)?;
94 Ok(Self::new(unsafe { data.assume_init() }))
97 }
98}
99
100impl<T: Sized, M: Positive> HeapArray<T, M> {
101 pub fn map<F, U>(self, f: F) -> HeapArray<U, M>
102 where
103 F: FnMut(T) -> U,
104 {
105 self.into_iter().map(f).collect()
106 }
107
108 pub fn into_array<const K: usize>(self) -> [T; K] {
114 const {
115 assert!(
116 M::USIZE == K,
117 "HeapArray length does not match destructured array length",
118 );
119 }
120 let raw: *mut [T] = Box::into_raw(self.data);
123 unsafe { *Box::from_raw(raw.cast::<[T; K]>()) }
124 }
125}
126
127impl<T: Sized + Default, M: Positive> HeapArray<T, M> {
128 pub fn from_single_value(val: T) -> Self {
129 Self {
130 data: vec![val].into_boxed_slice(),
131 _len: PhantomData,
132 }
133 }
134}
135
136impl<T: Sized + Default, M: Positive> Default for HeapArray<T, M> {
137 fn default() -> Self {
138 Self {
139 data: (0..M::USIZE).map(|_| T::default()).collect(),
140 _len: PhantomData,
141 }
142 }
143}
144
145impl<T: Sized + Debug, M: Positive> Debug for HeapArray<T, M> {
146 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
147 f.debug_struct(format!("HeapArray<{}>", M::USIZE).as_str())
148 .field("data", &self.data)
149 .finish()
150 }
151}
152
153impl<T: Sized + InPlaceCodec, M: Positive> Serialize for HeapArray<T, M> {
154 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
155 serializer.serialize_bytes(self.to_inplace_bytes().as_slice())
156 }
157}
158
159impl<'de, T: Sized + InPlaceCodec, M: Positive> Deserialize<'de> for HeapArray<T, M> {
160 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
161 let bytes: &[u8] = Deserialize::deserialize(deserializer)?;
163 HeapArray::<T, M>::from_inplace_bytes(bytes).map_err(serde::de::Error::custom)
164 }
165}
166
167impl<T: Sized, M: Positive> FromIterator<T> for HeapArray<T, M> {
168 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
169 let data = iter.into_iter().collect::<Box<_>>();
170 assert_eq!(data.len(), M::USIZE,);
171 Self {
172 data,
173 _len: PhantomData,
174 }
175 }
176}
177
178impl<T: Sized + Send, M: Positive> IntoParallelIterator for HeapArray<T, M> {
179 type Item = T;
180 type Iter = rayon::vec::IntoIter<T>;
181
182 fn into_par_iter(self) -> Self::Iter {
183 self.data.into_par_iter()
184 }
185}
186
187impl<T: Sized + Send, M: Positive> FromParallelIterator<T> for HeapArray<T, M> {
188 fn from_par_iter<I: IntoParallelIterator<Item = T>>(par_iter: I) -> Self {
189 let data: Box<[T]> = par_iter.into_par_iter().collect::<Vec<T>>().into();
190 assert_eq!(data.len(), M::USIZE);
191 Self {
192 data,
193 _len: PhantomData,
194 }
195 }
196}
197
198impl<T: Sized + Copy, M: Positive> HeapArray<T, M> {
203 pub fn split<M1, M2>(&self) -> (HeapArray<T, M1>, HeapArray<T, M2>)
204 where
205 M1: Positive,
206 M2: Positive + Add<M1, Output = M>,
207 {
208 let (m1, m2) = self.split_at(M1::USIZE);
209 (
210 HeapArray::<T, M1> {
211 data: m1.into(),
212 _len: PhantomData,
213 },
214 HeapArray::<T, M2> {
215 data: m2.into(),
216 _len: PhantomData,
217 },
218 )
219 }
220
221 pub fn split_last_pos<M1>(self) -> (HeapArray<T, M1>, T)
222 where
223 M1: Positive + Add<typenum::B1, Output = M>,
224 {
225 let Self { data, .. } = self;
226 let mut data = data.into_vec();
227 let last = data.pop().expect("HeapArray is empty");
228 (
229 HeapArray::<T, M1> {
230 data: data.into_boxed_slice(),
231 _len: PhantomData,
232 },
233 last,
234 )
235 }
236
237 pub fn split_halves<MDiv2>(&self) -> (HeapArray<T, MDiv2>, HeapArray<T, MDiv2>)
238 where
239 MDiv2: Positive + Mul<U2, Output = M>,
240 {
241 let (m1, m2) = self.split_at(MDiv2::USIZE);
242 (
243 HeapArray::<T, MDiv2> {
244 data: m1.into(),
245 _len: PhantomData,
246 },
247 HeapArray::<T, MDiv2> {
248 data: m2.into(),
249 _len: PhantomData,
250 },
251 )
252 }
253
254 pub fn merge_halves(this: Self, other: Self) -> HeapArray<T, Prod<M, U2>>
255 where
256 M: Mul<U2, Output: Positive>,
257 {
258 let mut vec = this.data.into_vec();
259 vec.extend(other.data.into_vec());
260 HeapArray::<T, Prod<M, U2>> {
261 data: vec.into_boxed_slice(),
262 _len: PhantomData,
263 }
264 }
265
266 pub fn split3<M1, M2, M3>(&self) -> (HeapArray<T, M1>, HeapArray<T, M2>, HeapArray<T, M3>)
267 where
268 M1: Positive,
269 M2: Positive + Add<M1>,
270 M3: Positive + Add<Sum<M2, M1>, Output = M>,
271 {
272 let (m1, m_rest) = self.split_at(M1::USIZE);
273 let (m2, m3) = m_rest.split_at(M2::USIZE);
274 (
275 HeapArray::<T, M1> {
276 data: m1.into(),
277 _len: PhantomData,
278 },
279 HeapArray::<T, M2> {
280 data: m2.into(),
281 _len: PhantomData,
282 },
283 HeapArray::<T, M3> {
284 data: m3.into(),
285 _len: PhantomData,
286 },
287 )
288 }
289
290 pub fn split_thirds<MDiv3>(
291 &self,
292 ) -> (
293 HeapArray<T, MDiv3>,
294 HeapArray<T, MDiv3>,
295 HeapArray<T, MDiv3>,
296 )
297 where
298 MDiv3: Positive + Mul<U3, Output = M>,
299 {
300 let (m1, m_rest) = self.split_at(MDiv3::USIZE);
301 let (m2, m3) = m_rest.split_at(MDiv3::USIZE);
302 (
303 HeapArray::<T, MDiv3> {
304 data: m1.into(),
305 _len: PhantomData,
306 },
307 HeapArray::<T, MDiv3> {
308 data: m2.into(),
309 _len: PhantomData,
310 },
311 HeapArray::<T, MDiv3> {
312 data: m3.into(),
313 _len: PhantomData,
314 },
315 )
316 }
317
318 pub fn merge_thirds(first: Self, second: Self, third: Self) -> HeapArray<T, Prod<M, U3>>
319 where
320 M: Mul<U3, Output: Positive>,
321 {
322 let mut vec = first.data.into_vec();
323 vec.extend(second.data.into_vec());
324 vec.extend(third.data.into_vec());
325 HeapArray::<T, Prod<M, U3>> {
326 data: vec.into_boxed_slice(),
327 _len: PhantomData,
328 }
329 }
330
331 pub fn merge_fifths(
332 first: Self,
333 second: Self,
334 third: Self,
335 fourth: Self,
336 fifth: Self,
337 ) -> HeapArray<T, Prod<M, U5>>
338 where
339 M: Mul<U5, Output: Positive>,
340 {
341 let mut vec = first.data.into_vec();
342 vec.reserve_exact(M::USIZE * 4);
343 vec.extend(second.data.into_vec());
344 vec.extend(third.data.into_vec());
345 vec.extend(fourth.data.into_vec());
346 vec.extend(fifth.data.into_vec());
347 HeapArray::<T, Prod<M, U5>> {
348 data: vec.into_boxed_slice(),
349 _len: PhantomData,
350 }
351 }
352}
353
354pub struct HeapArrayTuple<T1: Sized, T2: Sized, M: Positive>(
355 pub HeapArray<T1, M>,
356 pub HeapArray<T2, M>,
357);
358
359impl<T1: Sized, T2: Sized, M: Positive> FromIterator<(T1, T2)> for HeapArrayTuple<T1, T2, M> {
360 fn from_iter<I: IntoIterator<Item = (T1, T2)>>(iter: I) -> Self {
361 let (data1, data2): (Vec<_>, Vec<_>) = iter.into_iter().unzip();
362
363 assert_eq!(data1.len(), M::USIZE);
364 assert_eq!(data2.len(), M::USIZE);
365 HeapArrayTuple(
366 HeapArray::<T1, M> {
367 data: data1.into_boxed_slice(),
368 _len: PhantomData,
369 },
370 HeapArray::<T2, M> {
371 data: data2.into_boxed_slice(),
372 _len: PhantomData,
373 },
374 )
375 }
376}
377
378impl<T: Sized, M: Positive> TryFrom<Vec<T>> for HeapArray<T, M> {
379 type Error = PrimitiveError;
380
381 fn try_from(data: Vec<T>) -> Result<Self, PrimitiveError> {
382 if data.len() == M::USIZE {
383 Ok(Self {
384 data: data.into_boxed_slice(),
385 _len: PhantomData,
386 })
387 } else {
388 Err(PrimitiveError::InvalidSize(M::USIZE, data.len()))
389 }
390 }
391}
392
393impl<T: Sized, M: Positive> TryFrom<Box<[T]>> for HeapArray<T, M> {
394 type Error = PrimitiveError;
395
396 fn try_from(data: Box<[T]>) -> Result<Self, PrimitiveError> {
397 if data.len() == M::USIZE {
398 Ok(Self {
399 data,
400 _len: PhantomData,
401 })
402 } else {
403 Err(PrimitiveError::InvalidSize(M::USIZE, data.len()))
404 }
405 }
406}
407
408impl<T: Sized + Clone, M: Positive> TryFrom<Arc<[T]>> for HeapArray<T, M> {
409 type Error = PrimitiveError;
410
411 fn try_from(data: Arc<[T]>) -> Result<Self, PrimitiveError> {
412 if data.len() != M::USIZE {
413 return Err(PrimitiveError::InvalidSize(M::USIZE, data.len()));
414 }
415 Ok(Self {
416 data: data.to_vec().into_boxed_slice(),
417 _len: PhantomData,
418 })
419 }
420}
421
422impl<T: Sized> From<T> for HeapArray<T, U1> {
423 fn from(element: T) -> Self {
424 Self {
425 data: Box::new([element]),
426 _len: PhantomData,
427 }
428 }
429}
430
431impl<T: Sized, M: Positive> From<HeapArray<T, M>> for Vec<T> {
432 fn from(array: HeapArray<T, M>) -> Self {
433 array.data.into_vec()
434 }
435}
436
437impl<T: Sized + Clone, M: Positive + ArraySize> From<Array<T, M>> for HeapArray<T, M> {
438 fn from(array: Array<T, M>) -> Self {
439 Self {
440 data: array.to_vec().into_boxed_slice(),
441 _len: PhantomData,
442 }
443 }
444}
445
446impl<T: Sized, M: Positive> HeapArray<T, M> {
447 pub fn truncate<N>(self) -> HeapArray<T, N>
450 where
451 N: Positive,
452 M: Sub<N, Output: Unsigned>,
453 {
454 let mut vec = self.data.into_vec();
455 vec.truncate(N::USIZE);
456 HeapArray {
457 data: vec.into_boxed_slice(),
458 _len: PhantomData,
459 }
460 }
461
462 pub fn split_last<N: Positive>(self) -> (HeapArray<T, Diff<M, N>>, HeapArray<T, N>)
463 where
464 M: Sub<N, Output: Positive>,
465 {
466 let mut vec = self.data.into_vec();
467 let last_n = vec.split_off(M::USIZE - N::USIZE);
468
469 (
470 HeapArray {
471 data: vec.into_boxed_slice(),
472 _len: PhantomData,
473 },
474 HeapArray {
475 data: last_n.into_boxed_slice(),
476 _len: PhantomData,
477 },
478 )
479 }
480
481 pub fn from_fn(f: impl FnMut(usize) -> T) -> Self {
482 Self {
483 data: (0..M::USIZE).map(f).collect::<Box<_>>(),
484 _len: PhantomData,
485 }
486 }
487
488 pub fn from_constant(c: T) -> Self
489 where
490 T: Copy,
491 {
492 Self {
493 data: (0..M::USIZE).map(|_| c).collect::<Box<_>>(),
494 _len: PhantomData,
495 }
496 }
497}
498
499impl<T: Sized, M: Positive> Display for HeapArray<T, M>
500where
501 T: Display,
502{
503 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
504 write!(f, "[")?;
505 for (i, item) in self.data.iter().enumerate() {
506 if i != 0 {
507 write!(f, ", ")?;
508 }
509 write!(f, "{item}")?;
510 }
511 write!(f, "]")
512 }
513}
514
515#[cfg(test)]
516pub mod tests {
517 use hybrid_array::sizes::{U2, U3, U6};
518 use typenum::{U1, U4};
519
520 use super::*;
521 use crate::utils::codec::bincode_io;
522
523 #[test]
524 fn test_heap_array() {
525 let array = HeapArray::<_, U3>::from_fn(|i| i);
526 assert_eq!(array.into_iter().collect::<Vec<_>>(), vec![0, 1, 2]);
527 }
528
529 #[test]
530 fn test_default() {
531 let array = HeapArray::<usize, U3>::default();
532 assert_eq!(array.len(), 3);
533 }
534
535 #[test]
536 fn test_heap_array_split_last() {
537 let array = HeapArray::<_, U6>::from_fn(|i| i);
538 let (first, last) = array.split_last::<U2>();
539 assert_eq!(first.into_iter().collect::<Vec<_>>(), vec![0, 1, 2, 3]);
540 assert_eq!(last.into_iter().collect::<Vec<_>>(), vec![4, 5]);
541 }
542
543 #[test]
544 fn test_heap_array_from_array() {
545 let array = Array::<_, U3>::from_fn(|i| i);
546 let heap_array = HeapArray::<_, U3>::from(array);
547 assert_eq!(heap_array.into_iter().collect::<Vec<_>>(), vec![0, 1, 2]);
548 }
549
550 #[test]
551 fn test_heap_array_from_vec() {
552 let vec = vec![0, 1, 2];
553 let heap_array = HeapArray::<_, U3>::try_from(vec).unwrap();
554 assert_eq!(heap_array.into_iter().collect::<Vec<_>>(), vec![0, 1, 2]);
555
556 let vec = vec![0, 1];
557 let heap_array = HeapArray::<_, U3>::try_from(vec);
558 assert!(heap_array.is_err());
559 }
560
561 #[test]
562 fn test_heap_array_from_iter() {
563 let heap_array = HeapArray::<_, U3>::from_fn(|i| i);
564 assert_eq!(heap_array.into_iter().collect::<Vec<_>>(), vec![0, 1, 2]);
565 }
566
567 #[test]
568 #[should_panic]
569 fn test_heap_array_from_iter_wrong_size() {
570 HeapArray::<_, U2>::from_iter(0..3);
571 }
572
573 #[test]
574 fn test_heap_array_deserialize() {
575 let array = HeapArray::<usize, U6>::from_fn(|i| i);
576 let serialized = bincode_io::serialize(&array).unwrap();
577 bincode_io::deserialize::<HeapArray<usize, U6>>(&serialized).unwrap();
578
579 use bincode::Options;
583 let config = bincode::DefaultOptions::new()
584 .with_fixint_encoding()
585 .reject_trailing_bytes();
586
587 let wrong_deserialize = config.deserialize::<HeapArray<usize, U3>>(&serialized);
588 assert!(wrong_deserialize.is_err());
589 }
590
591 #[test]
592 fn test_heap_array_split() {
593 let array = HeapArray::<_, U6>::from_fn(|i| i);
594 let (first, second) = array.split::<U4, U2>();
595 assert_eq!(first.into_iter().collect::<Vec<_>>(), vec![0, 1, 2, 3]);
596 assert_eq!(second.into_iter().collect::<Vec<_>>(), vec![4, 5]);
597
598 let (first, second) = array.split_halves::<U3>();
599 assert_eq!(first.into_iter().collect::<Vec<_>>(), vec![0, 1, 2]);
600 assert_eq!(second.into_iter().collect::<Vec<_>>(), vec![3, 4, 5]);
601
602 }
606
607 #[test]
608 fn test_heap_array_split3() {
609 let array = HeapArray::<_, U6>::from_fn(|i| i);
610 let (first, second, third) = array.split3::<U3, U2, U1>();
611 assert_eq!(first.into_iter().collect::<Vec<_>>(), vec![0, 1, 2]);
612 assert_eq!(second.into_iter().collect::<Vec<_>>(), vec![3, 4]);
613 assert_eq!(third.into_iter().collect::<Vec<_>>(), vec![5]);
614
615 let (first, second, third) = array.split_thirds::<U2>();
616 assert_eq!(first.into_iter().collect::<Vec<_>>(), vec![0, 1]);
617 assert_eq!(second.into_iter().collect::<Vec<_>>(), vec![2, 3]);
618 assert_eq!(third.into_iter().collect::<Vec<_>>(), vec![4, 5]);
619
620 }
624
625 #[test]
626 fn test_heap_array_wrap_transparent() {
627 #[repr(transparent)]
628 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
629 struct Wrap(u32);
630 unsafe impl bytemuck::TransparentWrapper<u32> for Wrap {}
632
633 let array = HeapArray::<u32, U3>::from_fn(|i| (i as u32) * 10);
634 let wrapped: HeapArray<Wrap, U3> = array.wrap_transparent();
635 assert_eq!(
636 wrapped.into_iter().collect::<Vec<_>>(),
637 vec![Wrap(0), Wrap(10), Wrap(20)],
638 );
639 }
640
641 #[test]
642 fn test_heap_array_peel_transparent() {
643 #[repr(transparent)]
644 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
645 struct Wrap(u32);
646 unsafe impl bytemuck::TransparentWrapper<u32> for Wrap {}
648
649 let array = HeapArray::<Wrap, U3>::from_fn(|i| Wrap((i as u32) * 10));
650 let peeled: HeapArray<u32, U3> = array.peel_transparent();
651 assert_eq!(peeled.into_iter().collect::<Vec<_>>(), vec![0, 10, 20]);
652 }
653
654 #[test]
655 fn test_heap_array_wrap_peel_roundtrip() {
656 #[repr(transparent)]
657 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
658 struct Wrap(u32);
659 unsafe impl bytemuck::TransparentWrapper<u32> for Wrap {}
661
662 let original = HeapArray::<u32, U4>::from_fn(|i| i as u32 + 1);
663 let expected = original.clone().into_iter().collect::<Vec<_>>();
664 let roundtripped: HeapArray<u32, U4> =
665 original.wrap_transparent::<Wrap>().peel_transparent();
666 assert_eq!(roundtripped.into_iter().collect::<Vec<_>>(), expected);
667 }
668
669 #[test]
670 fn test_heap_array_inplace_roundtrip() {
671 use crate::algebra::field::mersenne::Mersenne107;
672
673 let array = HeapArray::<Mersenne107, U6>::from_fn(|i| Mersenne107::from(i as u64));
674 let inplace_ser = array.to_inplace_bytes();
675
676 let bin_ser = bincode_io::serialize(&array).unwrap();
679 assert_eq!(
680 bincode_io::deserialize::<HeapArray<Mersenne107, U6>>(&bin_ser).unwrap(),
681 array
682 );
683
684 let deserialized = HeapArray::<Mersenne107, U6>::from_inplace_bytes(&inplace_ser).unwrap();
685 assert_eq!(deserialized, array);
686
687 assert!(HeapArray::<Mersenne107, U6>::from_inplace_bytes(&inplace_ser[..1]).is_err());
689
690 let mut bad_bytes = inplace_ser.clone();
692 bad_bytes[..14].copy_from_slice(&[0xFF; 14]);
693 assert!(HeapArray::<Mersenne107, U6>::from_inplace_bytes(&bad_bytes).is_err());
694
695 let mut bad_bytes = inplace_ser.clone();
700 let last_real = 5 * 14;
701 bad_bytes[last_real..last_real + 14].copy_from_slice(&[0xFF; 14]);
702 assert!(HeapArray::<Mersenne107, U6>::from_inplace_bytes(&bad_bytes).is_err());
703 }
704
705 #[test]
708 fn test_field_extension_inplace_roundtrip() {
709 use crate::{
710 algebra::{
711 elliptic_curve::{BaseField, Curve25519Ristretto, Point, ScalarField},
712 field::{
713 binary::{Gf2, Gf2_128},
714 mersenne::Mersenne107,
715 FieldElement,
716 SubfieldElement,
717 },
718 },
719 random::{test_rng, Random},
720 utils::codec::InPlaceCodec,
721 };
722
723 fn check<T>()
724 where
725 T: InPlaceCodec + Random + PartialEq + std::fmt::Debug,
726 {
727 let name = std::any::type_name::<T>();
728 let mut rng = test_rng();
729 let array = HeapArray::<T, U6>::random(&mut rng);
730 let inplace = array.to_inplace_bytes();
731 assert_eq!(
732 inplace.len(),
733 <HeapArray<T, U6> as InPlaceCodec>::ENCODED_SIZE,
734 "encoded size mismatch for {name}"
735 );
736
737 let back = HeapArray::<T, U6>::from_inplace_bytes(&inplace).unwrap();
738 assert_eq!(back, array, "round-trip failed for {name}");
739 }
740
741 check::<Gf2>();
742 check::<Gf2_128>();
743 check::<Mersenne107>();
744 check::<ScalarField<Curve25519Ristretto>>();
745 check::<BaseField<Curve25519Ristretto>>();
746 check::<FieldElement<Gf2_128>>();
747 check::<SubfieldElement<Gf2_128>>();
748 check::<Point<Curve25519Ristretto>>();
749 }
750
751 #[test]
755 fn test_heap_array_pack_roundtrip_and_layout() {
756 use typenum::{U16, U20};
757
758 use crate::{
759 algebra::field::{binary::Gf2, mersenne::Mersenne107},
760 random::{test_rng, Random},
761 utils::codec::InPlaceCodec,
762 };
763
764 let mut rng = test_rng();
765
766 assert_eq!(
769 <HeapArray<Gf2, U20> as InPlaceCodec>::ENCODED_SIZE,
770 20usize.div_ceil(8)
771 );
772 let gf2 = HeapArray::<Gf2, U20>::random(&mut rng);
773 let gf2_bytes = gf2.to_inplace_bytes();
774 assert_eq!(gf2_bytes.len(), 3);
775 assert_eq!(
776 HeapArray::<Gf2, U20>::from_inplace_bytes(&gf2_bytes).unwrap(),
777 gf2
778 );
779
780 let mers16 = HeapArray::<Mersenne107, U16>::random(&mut rng);
783 let mers16_bytes = mers16.to_inplace_bytes();
784 let reference: Vec<u8> = mers16.iter().flat_map(|e| e.to_inplace_bytes()).collect();
785 assert_eq!(
786 mers16_bytes, reference,
787 "packed Mersenne107 must be byte-identical to the per-element encoding"
788 );
789 assert_eq!(
790 HeapArray::<Mersenne107, U16>::from_inplace_bytes(&mers16_bytes).unwrap(),
791 mers16
792 );
793
794 assert_eq!(
799 <HeapArray<Mersenne107, U20> as InPlaceCodec>::ENCODED_SIZE,
800 20 * 14
801 );
802 let mers20 = HeapArray::<Mersenne107, U20>::random(&mut rng);
803 let mers20_bytes = mers20.to_inplace_bytes();
804 assert_eq!(mers20_bytes.len(), 20 * 14);
805 assert_eq!(
806 HeapArray::<Mersenne107, U20>::from_inplace_bytes(&mers20_bytes).unwrap(),
807 mers20
808 );
809 }
810}