Skip to main content

multiversx_sc_codec/impl_for_types/
impl_array.rs

1use crate::{
2    DecodeError, DecodeErrorHandler, EncodeErrorHandler, NestedDecode, NestedDecodeInput,
3    NestedEncode, NestedEncodeOutput, TopDecode, TopDecodeInput, TopEncode, TopEncodeOutput,
4    top_decode_from_nested_or_handle_err,
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_dep_encode_decode, check_top_encode, check_top_encode_decode};
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
112    #[test]
113    fn test_top_array_u8() {
114        check_top_encode_decode([1u8, 2u8, 3u8], &[1, 2, 3]);
115    }
116
117    #[test]
118    fn test_top_array_u8_empty() {
119        check_top_encode_decode([0u8; 0], &[]);
120    }
121
122    #[test]
123    fn test_top_array_i32() {
124        check_top_encode_decode([1i32, 2i32], &[0, 0, 0, 1, 0, 0, 0, 2]);
125    }
126
127    #[test]
128    fn test_dep_array_u8() {
129        check_dep_encode_decode([1u8, 2u8, 3u8], &[1, 2, 3]);
130    }
131
132    #[test]
133    fn test_dep_array_i32() {
134        check_dep_encode_decode([1i32, 2i32], &[0, 0, 0, 1, 0, 0, 0, 2]);
135    }
136
137    #[test]
138    fn test_top_array_32_bytes() {
139        let arr = [0xABu8; 32];
140        check_top_encode_decode(arr, &[0xAB; 32]);
141    }
142}