multiversx_sc_codec/multi_types/
multi_value_optional.rs

1use core::fmt::Debug;
2
3use crate::{
4    DecodeErrorHandler, EncodeErrorHandler, TopDecodeMulti, TopDecodeMultiInput, TopEncodeMulti,
5    TopEncodeMultiOutput,
6};
7
8/// A smart contract argument or result that can be missing.
9///
10/// If arguments stop before this argument, None will be returned.
11/// As an endpoint result, the contract decides if it produces it or not.
12///
13/// As a principle, optional arguments or results should come last,
14/// otherwise there is ambiguity as to how to interpret what comes after.
15#[must_use]
16#[derive(Clone)]
17pub enum OptionalValue<T> {
18    Some(T),
19    None,
20}
21
22impl<T> From<Option<T>> for OptionalValue<T> {
23    fn from(v: Option<T>) -> Self {
24        match v {
25            Some(arg) => OptionalValue::Some(arg),
26            None => OptionalValue::None,
27        }
28    }
29}
30
31impl<T> OptionalValue<T> {
32    pub fn into_option(self) -> Option<T> {
33        match self {
34            OptionalValue::Some(arg) => Some(arg),
35            OptionalValue::None => None,
36        }
37    }
38
39    pub fn is_some(&self) -> bool {
40        matches!(self, OptionalValue::Some(_))
41    }
42
43    pub fn is_none(&self) -> bool {
44        !self.is_some()
45    }
46}
47
48impl<T> TopEncodeMulti for OptionalValue<T>
49where
50    T: TopEncodeMulti,
51{
52    fn multi_encode_or_handle_err<O, H>(&self, output: &mut O, h: H) -> Result<(), H::HandledErr>
53    where
54        O: TopEncodeMultiOutput,
55        H: EncodeErrorHandler,
56    {
57        if let OptionalValue::Some(t) = self {
58            t.multi_encode_or_handle_err(output, h)?;
59        }
60        Ok(())
61    }
62}
63
64impl<T> TopDecodeMulti for OptionalValue<T>
65where
66    T: TopDecodeMulti,
67{
68    fn multi_decode_or_handle_err<I, H>(input: &mut I, h: H) -> Result<Self, H::HandledErr>
69    where
70        I: TopDecodeMultiInput,
71        H: DecodeErrorHandler,
72    {
73        if input.has_next() {
74            Ok(OptionalValue::Some(T::multi_decode_or_handle_err(
75                input, h,
76            )?))
77        } else {
78            Ok(OptionalValue::None)
79        }
80    }
81}
82
83impl<T> Debug for OptionalValue<T>
84where
85    T: Debug,
86{
87    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
88        match self {
89            Self::Some(arg0) => f.debug_tuple("Some").field(arg0).finish(),
90            Self::None => write!(f, "None"),
91        }
92    }
93}