esexpr/codecs/
option.rs

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}