Skip to main content

multiversx_sc/contract_base/wrappers/
serializer.rs

1use core::{convert::Infallible, marker::PhantomData};
2
3use unwrap_infallible::UnwrapInfallible;
4
5use crate::codec::{
6    DecodeError, DecodeErrorHandler, EncodeError, EncodeErrorHandler, TopDecode, TopEncode,
7};
8
9use crate::{
10    api::{ErrorApi, ErrorApiImpl, ManagedTypeApi},
11    err_msg,
12    types::{ManagedBuffer, ManagedType, heap::BoxedBytes},
13};
14
15#[derive(Default)]
16pub struct ManagedSerializer<M>
17where
18    M: ManagedTypeApi + ErrorApi + 'static,
19{
20    _phantom: PhantomData<M>,
21}
22
23impl<M> ManagedSerializer<M>
24where
25    M: ManagedTypeApi + ErrorApi + 'static,
26{
27    pub fn new() -> Self {
28        ManagedSerializer {
29            _phantom: PhantomData,
30        }
31    }
32
33    pub fn top_encode_to_managed_buffer<T: TopEncode>(&self, value: &T) -> ManagedBuffer<M> {
34        let mut result = ManagedBuffer::new();
35        value
36            .top_encode_or_handle_err(
37                &mut result,
38                ExitCodecErrorHandler::<M>::from(err_msg::SERIALIZER_ENCODE_ERROR),
39            )
40            .unwrap_infallible();
41        result
42    }
43
44    pub fn top_encode_to_boxed_bytes<T: TopEncode>(&self, value: &T) -> BoxedBytes {
45        let mut result = BoxedBytes::empty();
46        value
47            .top_encode_or_handle_err(
48                &mut result,
49                ExitCodecErrorHandler::<M>::from(err_msg::SERIALIZER_ENCODE_ERROR),
50            )
51            .unwrap_infallible();
52        result
53    }
54
55    pub fn top_decode_from_managed_buffer<T: TopDecode>(&self, buffer: &ManagedBuffer<M>) -> T {
56        self.top_decode_from_managed_buffer_custom_message(buffer, err_msg::SERIALIZER_DECODE_ERROR)
57    }
58
59    pub fn top_decode_from_managed_buffer_custom_message<T: TopDecode>(
60        &self,
61        buffer: &ManagedBuffer<M>,
62        error_message: &'static str,
63    ) -> T {
64        T::top_decode_or_handle_err(
65            buffer.clone(), // TODO: remove clone
66            ExitCodecErrorHandler::<M>::from(error_message),
67        )
68        .unwrap_infallible()
69    }
70
71    pub fn top_decode_from_byte_slice<T: TopDecode>(&self, slice: &[u8]) -> T {
72        T::top_decode_or_handle_err(
73            slice,
74            ExitCodecErrorHandler::<M>::from(err_msg::SERIALIZER_DECODE_ERROR),
75        )
76        .unwrap_infallible()
77    }
78}
79
80#[derive(Clone)]
81pub struct ExitCodecErrorHandler<M>
82where
83    M: ManagedTypeApi + ErrorApi,
84{
85    _phantom: PhantomData<M>,
86    pub base_message: &'static str,
87}
88
89impl<M> Copy for ExitCodecErrorHandler<M> where M: ManagedTypeApi + ErrorApi {}
90
91impl<M> From<&'static str> for ExitCodecErrorHandler<M>
92where
93    M: ManagedTypeApi + ErrorApi,
94{
95    fn from(base_message: &'static str) -> Self {
96        ExitCodecErrorHandler {
97            _phantom: PhantomData,
98            base_message,
99        }
100    }
101}
102
103impl<M> EncodeErrorHandler for ExitCodecErrorHandler<M>
104where
105    M: ManagedTypeApi + ErrorApi,
106{
107    type HandledErr = Infallible;
108
109    fn handle_error(&self, err: EncodeError) -> Self::HandledErr {
110        let mut message_buffer = ManagedBuffer::<M>::new_from_bytes(self.base_message.as_bytes());
111        message_buffer.append_bytes(err.message_bytes());
112        M::error_api_impl().signal_error_from_buffer(message_buffer.get_handle())
113    }
114}
115
116impl<M> DecodeErrorHandler for ExitCodecErrorHandler<M>
117where
118    M: ManagedTypeApi + ErrorApi,
119{
120    type HandledErr = Infallible;
121
122    fn handle_error(&self, err: DecodeError) -> Self::HandledErr {
123        let mut message_buffer = ManagedBuffer::<M>::new_from_bytes(self.base_message.as_bytes());
124        message_buffer.append_bytes(err.message_bytes());
125        M::error_api_impl().signal_error_from_buffer(message_buffer.get_handle())
126    }
127}