elrond_codec/impl_for_types/
impl_slice.rs

1use crate::{
2    vec_into_boxed_slice, DecodeErrorHandler, EncodeErrorHandler, NestedDecode, NestedEncode,
3    NestedEncodeOutput, TopDecode, TopDecodeInput, TopEncode, TopEncodeOutput,
4};
5use alloc::{boxed::Box, vec::Vec};
6
7/// Adds the concantenated encoded contents of a slice to an output buffer,
8/// without serializing the slice length.
9/// Byte slice is treated separately, via direct transmute.
10pub fn dep_encode_slice_contents<T, O, H>(
11    slice: &[T],
12    dest: &mut O,
13    h: H,
14) -> Result<(), H::HandledErr>
15where
16    T: NestedEncode,
17    O: NestedEncodeOutput,
18    H: EncodeErrorHandler,
19{
20    T::if_u8(
21        dest,
22        |dest| {
23            // cast &[T] to &[u8]
24            let slice: &[u8] =
25                unsafe { core::slice::from_raw_parts(slice.as_ptr() as *const u8, slice.len()) };
26            dest.write(slice);
27            Ok(())
28        },
29        |dest| {
30            for x in slice {
31                x.dep_encode_or_handle_err(dest, h)?;
32            }
33            Ok(())
34        },
35    )
36}
37
38impl<T: NestedEncode> TopEncode for &[T] {
39    fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
40    where
41        O: TopEncodeOutput,
42        H: EncodeErrorHandler,
43    {
44        T::if_u8(
45            output,
46            |output| {
47                // transmute to &[u8]
48                // save directly, without passing through the buffer
49                let slice: &[u8] =
50                    unsafe { core::slice::from_raw_parts(self.as_ptr() as *const u8, self.len()) };
51                output.set_slice_u8(slice);
52                Ok(())
53            },
54            |output| {
55                // only using `dep_encode_slice_contents` for non-u8,
56                // because it always appends to the buffer,
57                // which is not necessary above
58                let mut buffer = output.start_nested_encode();
59                dep_encode_slice_contents(self, &mut buffer, h)?;
60                output.finalize_nested_encode(buffer);
61                Ok(())
62            },
63        )
64    }
65}
66
67impl<T: NestedEncode> TopEncode for Box<[T]> {
68    #[inline]
69    fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
70    where
71        O: TopEncodeOutput,
72        H: EncodeErrorHandler,
73    {
74        self.as_ref().top_encode_or_handle_err(output, h)
75    }
76}
77
78// Allowed to implement this because [T] cannot implement NestedDecode, being ?Sized.
79impl<T: NestedDecode> TopDecode for Box<[T]> {
80    fn top_decode_or_handle_err<I, H>(input: I, h: H) -> Result<Self, H::HandledErr>
81    where
82        I: TopDecodeInput,
83        H: DecodeErrorHandler,
84    {
85        T::if_u8(
86            input,
87            |input| {
88                let bytes = input.into_boxed_slice_u8();
89                let cast_bytes: Box<[T]> = unsafe { core::mem::transmute(bytes) };
90                Ok(cast_bytes)
91            },
92            |input| {
93                let vec = Vec::<T>::top_decode_or_handle_err(input, h)?;
94                Ok(vec_into_boxed_slice(vec))
95            },
96        )
97    }
98}
99
100impl<T: NestedEncode> NestedEncode for &[T] {
101    fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
102    where
103        O: NestedEncodeOutput,
104        H: EncodeErrorHandler,
105    {
106        // push size
107        self.len().dep_encode_or_handle_err(dest, h)?;
108        // actual data
109        dep_encode_slice_contents(self, dest, h)
110    }
111}
112
113impl<T: NestedEncode> NestedEncode for Box<[T]> {
114    fn dep_encode_or_handle_err<O, H>(&self, dest: &mut O, h: H) -> Result<(), H::HandledErr>
115    where
116        O: NestedEncodeOutput,
117        H: EncodeErrorHandler,
118    {
119        self.as_ref().dep_encode_or_handle_err(dest, h)
120    }
121}
122
123// TODO: NestedDecode for Box<[T]> missing