multiversx_sc_codec/single/
top_de.rs

1use alloc::boxed::Box;
2
3use crate::{
4    codec_err::DecodeError, DecodeErrorHandler, DefaultErrorHandler, NestedDecode,
5    NestedDecodeInput, TopDecodeInput,
6};
7
8/// Trait that allows zero-copy read of values from an underlying API in big endian format.
9///
10/// 'Top' stands for the fact that values are deserialized on their own,
11/// so we have the benefit of knowing their length.
12/// This is useful in many scnearios, such as not having to encode Vec length and others.
13///
14/// The opther optimization that can be done when deserializing top-level objects
15/// is using special functions from the underlying API that do some of the work for the deserializer.
16/// These include getting values directly as i64/u64 or wrapping them directly into an owned Box<[u8]>.
17///
18/// BigInt/BigUint handling is not included here, because these are API-dependent
19/// and would overly complicate the trait.
20///
21pub trait TopDecode: Sized {
22    /// Attempt to deserialize the value from input.
23    fn top_decode<I>(input: I) -> Result<Self, DecodeError>
24    where
25        I: TopDecodeInput,
26    {
27        Self::top_decode_or_handle_err(input, DefaultErrorHandler)
28    }
29
30    /// Version of `top_decode` that can handle errors as soon as they occur.
31    /// For instance it can exit immediately and make sure that if it returns, it is a success.
32    /// By not deferring error handling, this can lead to somewhat smaller bytecode.
33    fn top_decode_or_handle_err<I, H>(input: I, h: H) -> Result<Self, H::HandledErr>
34    where
35        I: TopDecodeInput,
36        H: DecodeErrorHandler,
37    {
38        match Self::top_decode(input) {
39            Ok(v) => Ok(v),
40            Err(e) => Err(h.handle_error(e)),
41        }
42    }
43
44    /// Allows types to provide optimized implementations for their boxed version.
45    /// Especially designed for byte arrays that can be transmuted directly from the input sometimes.
46    /// TODO: switch to the specialized mechanism
47    #[doc(hidden)]
48    #[inline]
49    fn top_decode_boxed_or_handle_err<I, H>(input: I, h: H) -> Result<Box<Self>, H::HandledErr>
50    where
51        I: TopDecodeInput,
52        H: DecodeErrorHandler,
53    {
54        Ok(Box::new(Self::top_decode_or_handle_err(input, h)?))
55    }
56}
57
58/// Top-decodes the result using the NestedDecode implementation.
59pub fn top_decode_from_nested_or_handle_err<I, T, H>(input: I, h: H) -> Result<T, H::HandledErr>
60where
61    I: TopDecodeInput,
62    T: NestedDecode,
63    H: DecodeErrorHandler,
64{
65    let mut nested_buffer = input.into_nested_buffer();
66    let result = T::dep_decode_or_handle_err(&mut nested_buffer, h)?;
67    if !nested_buffer.is_depleted() {
68        return Err(h.handle_error(DecodeError::INPUT_TOO_LONG));
69    }
70    Ok(result)
71}
72
73/// Top-decodes the result using the NestedDecode implementation.
74#[inline]
75pub fn top_decode_from_nested<T, I>(input: I) -> Result<T, DecodeError>
76where
77    I: TopDecodeInput,
78    T: NestedDecode,
79{
80    top_decode_from_nested_or_handle_err(input, DefaultErrorHandler)
81}