elrond_codec/impl_for_types/
impl_array.rs

1use crate::{
2    top_decode_from_nested_or_handle_err, DecodeError, DecodeErrorHandler, EncodeErrorHandler,
3    NestedDecode, NestedDecodeInput, NestedEncode, NestedEncodeOutput, TopDecode, TopDecodeInput,
4    TopEncode, TopEncodeOutput,
5};
6use alloc::boxed::Box;
7use arrayvec::ArrayVec;
8
9impl<T: NestedEncode, const N: usize> NestedEncode for [T; N] {
10    #[inline]
11    fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
12    where
13        O: NestedEncodeOutput,
14        H: EncodeErrorHandler,
15    {
16        super::impl_slice::dep_encode_slice_contents(&self[..], dest, h)
17    }
18}
19
20impl<T: NestedEncode, const N: usize> TopEncode for [T; N] {
21    #[inline]
22    fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
23    where
24        O: TopEncodeOutput,
25        H: EncodeErrorHandler,
26    {
27        // the top encoded slice does not serialize its length, so just like the array
28        (&self[..]).top_encode_or_handle_err(output, h)
29    }
30}
31
32impl<T: NestedDecode, const N: usize> NestedDecode for [T; N] {
33    #[allow(clippy::reversed_empty_ranges)]
34    fn dep_decode_or_handle_err<I, H>(input: &mut I, h: H) -> Result<Self, H::HandledErr>
35    where
36        I: NestedDecodeInput,
37        H: DecodeErrorHandler,
38    {
39        let mut r = ArrayVec::new();
40        for _ in 0..N {
41            r.push(T::dep_decode_or_handle_err(input, h)?);
42        }
43        let i = r.into_inner();
44
45        match i {
46            Ok(a) => Ok(a),
47            Err(_) => Err(h.handle_error(DecodeError::ARRAY_DECODE_ERROR)),
48        }
49    }
50}
51
52impl<T: NestedDecode, const N: usize> TopDecode for [T; N] {
53    fn top_decode_or_handle_err<I, H>(input: I, h: H) -> Result<Self, H::HandledErr>
54    where
55        I: TopDecodeInput,
56        H: DecodeErrorHandler,
57    {
58        top_decode_from_nested_or_handle_err(input, h)
59    }
60
61    fn top_decode_boxed_or_handle_err<I, H>(input: I, h: H) -> Result<Box<Self>, H::HandledErr>
62    where
63        I: TopDecodeInput,
64        H: DecodeErrorHandler,
65    {
66        T::if_u8(
67            input,
68            |input| {
69                // transmute directly
70                let bs = input.into_boxed_slice_u8();
71                if bs.len() != N {
72                    return Err(h.handle_error(DecodeError::ARRAY_DECODE_ERROR));
73                }
74                let raw = Box::into_raw(bs);
75                let array_box = unsafe { Box::<[T; N]>::from_raw(raw as *mut [T; N]) };
76                Ok(array_box)
77            },
78            |input| Ok(Box::new(Self::top_decode_or_handle_err(input, h)?)),
79        )
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use crate::test_util::check_top_encode;
86
87    use super::*;
88    use alloc::vec::Vec;
89
90    #[test]
91    fn test_array_16384() {
92        let arr = [7i32; 16384];
93        let mut expected_bytes = Vec::<u8>::with_capacity(16384 * 4);
94        for _ in 0..16384 {
95            expected_bytes.push(0);
96            expected_bytes.push(0);
97            expected_bytes.push(0);
98            expected_bytes.push(7);
99        }
100
101        // serialize
102        let serialized_bytes = check_top_encode(&arr);
103        assert_eq!(serialized_bytes, expected_bytes);
104
105        // deserialize
106        let deserialized = <[i32; 16384]>::top_decode(&serialized_bytes[..]).unwrap();
107        for byte in deserialized {
108            assert_eq!(byte, 7i32);
109        }
110    }
111}