1use alloc::borrow::Cow;
2
3use num_bigint::BigUint;
4
5use crate::{DecodeError, ESExpr, ESExprCodec, ESExprEncodedEq, ESExprOptionalFieldCodec, ESExprTag, ESExprTagSet};
6
7impl<A: ESExprEncodedEq> ESExprEncodedEq for Option<A> {
8 fn is_encoded_eq(&self, other: &Self) -> bool {
9 match (self, other) {
10 (Some(a), Some(b)) => a.is_encoded_eq(b),
11 (None, None) => true,
12 _ => false,
13 }
14 }
15}
16
17impl<'a, A: ESExprCodec<'a>> ESExprCodec<'a> for Option<A> {
18 const TAGS: ESExprTagSet = {
19 if A::TAGS.is_empty() {
20 ESExprTagSet::Tags(&[])
21 }
22 else {
23 ESExprTagSet::Concat(&[ESExprTagSet::Tags(&[ESExprTag::Null]), A::TAGS])
24 }
25 };
26
27 fn encode_esexpr(&'a self) -> ESExpr<'a> {
28 match self {
29 Some(a) => match a.encode_esexpr() {
30 ESExpr::Null(level) => ESExpr::Null(Cow::Owned(level.as_ref() + 1u32)),
31 expr => expr,
32 },
33
34 None => ESExpr::Null(Cow::Owned(BigUint::ZERO)),
35 }
36 }
37
38 fn decode_esexpr(expr: ESExpr<'a>) -> Result<Self, DecodeError> {
39 match expr {
40 ESExpr::Null(mut level) => {
41 if *level == BigUint::ZERO {
42 Ok(None)
43 }
44 else {
45 *level.to_mut() -= 1u32;
46 A::decode_esexpr(ESExpr::Null(level)).map(Some)
47 }
48 },
49 _ => A::decode_esexpr(expr).map(Some),
50 }
51 }
52}
53
54impl<'a, A: ESExprCodec<'a>> ESExprOptionalFieldCodec<'a> for Option<A> {
55 type Element = A;
56
57 fn encode_optional_field(&'a self) -> Option<ESExpr<'a>> {
58 self.as_ref().map(A::encode_esexpr)
59 }
60
61 fn decode_optional_field(value: Option<ESExpr<'a>>) -> Result<Self, DecodeError> {
62 value.map(|expr| A::decode_esexpr(expr)).transpose()
63 }
64}