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}