esexpr/codecs/
scalar.rs

1use alloc::borrow::Cow;
2use alloc::format;
3use alloc::string::String;
4use half::f16;
5use num_bigint::{BigInt, BigUint};
6use esexpr::ESExprEncodedEq;
7use crate::cowstr::CowStr;
8use crate::{DecodeError, DecodeErrorPath, DecodeErrorType, ESExpr, ESExprCodec, ESExprTag, ESExprTagSet};
9
10macro_rules! encoded_as_partial_eq {
11    ($t: ty) => {
12		impl ESExprEncodedEq for $t {
13			fn is_encoded_eq(&self, other: &Self) -> bool {
14				*self == *other
15			}
16		}
17	};
18}
19
20encoded_as_partial_eq!(bool);
21
22impl<'a> ESExprCodec<'a> for bool {
23	const TAGS: ESExprTagSet = ESExprTagSet::Tags(&[ESExprTag::Bool]);
24
25	fn encode_esexpr(&'a self) -> ESExpr<'a> {
26		ESExpr::Bool(*self)
27	}
28
29	fn decode_esexpr(expr: ESExpr<'a>) -> Result<Self, DecodeError> {
30		match expr {
31			ESExpr::Bool(b) => Ok(b),
32			_ => Err(DecodeError::new(
33				DecodeErrorType::UnexpectedExpr {
34					expected_tags: Self::TAGS,
35					actual_tag: expr.tag().into_owned(),
36				},
37				DecodeErrorPath::Current,
38			)),
39		}
40	}
41}
42
43encoded_as_partial_eq!(BigInt);
44
45impl<'a> ESExprCodec<'a> for BigInt {
46	const TAGS: ESExprTagSet = ESExprTagSet::Tags(&[ESExprTag::Int]);
47
48	fn encode_esexpr(&'a self) -> ESExpr<'a> {
49		ESExpr::Int(Cow::Borrowed(self))
50	}
51
52	fn decode_esexpr(expr: ESExpr<'a>) -> Result<Self, DecodeError> {
53		match expr {
54			ESExpr::Int(i) => Ok(i.into_owned()),
55			_ => Err(DecodeError::new(
56				DecodeErrorType::UnexpectedExpr {
57					expected_tags: Self::TAGS,
58					actual_tag: expr.tag().into_owned(),
59				},
60				DecodeErrorPath::Current,
61			)),
62		}
63	}
64}
65
66encoded_as_partial_eq!(BigUint);
67
68impl<'a> ESExprCodec<'a> for BigUint {
69	const TAGS: ESExprTagSet = ESExprTagSet::Tags(&[ESExprTag::Int]);
70
71	fn encode_esexpr(&'a self) -> ESExpr<'a> {
72		ESExpr::Int(Cow::Owned(BigInt::from(self.clone())))
73	}
74
75	fn decode_esexpr(expr: ESExpr<'a>) -> Result<Self, DecodeError> {
76		match expr {
77			ESExpr::Int(i) => match BigUint::try_from(i.into_owned()) {
78				Ok(i) => Ok(i),
79				Err(_) => Err(DecodeError::new(
80					DecodeErrorType::OutOfRange(format!("Unexpected integer value for {}", stringify!($T))),
81					DecodeErrorPath::Current,
82				)),
83			},
84			_ => Err(DecodeError::new(
85				DecodeErrorType::UnexpectedExpr {
86					expected_tags: Self::TAGS,
87					actual_tag: expr.tag().into_owned(),
88				},
89				DecodeErrorPath::Current,
90			)),
91		}
92	}
93}
94
95macro_rules! int_codec {
96	($T: ty) => {
97		encoded_as_partial_eq!($T);
98		impl<'a> ESExprCodec<'a> for $T {
99			const TAGS: ESExprTagSet = ESExprTagSet::Tags(&[ESExprTag::Int]);
100
101			fn encode_esexpr(&self) -> ESExpr<'a> {
102				ESExpr::Int(Cow::Owned(BigInt::from(*self)))
103			}
104
105			fn decode_esexpr(expr: ESExpr<'a>) -> Result<Self, DecodeError> {
106				match expr {
107					ESExpr::Int(i) => match <$T>::try_from(i.into_owned()) {
108						Ok(i) => Ok(i),
109						Err(_) => Err(DecodeError::new(
110							DecodeErrorType::OutOfRange(format!("Unexpected integer value for {}", stringify!($T))),
111							DecodeErrorPath::Current,
112						)),
113					},
114					_ => Err(DecodeError::new(
115						DecodeErrorType::UnexpectedExpr {
116							expected_tags: Self::TAGS,
117							actual_tag: expr.tag().into_owned(),
118						},
119						DecodeErrorPath::Current,
120					)),
121				}
122			}
123		}
124	};
125}
126
127int_codec!(isize);
128int_codec!(usize);
129int_codec!(i128);
130int_codec!(u128);
131int_codec!(i64);
132int_codec!(u64);
133int_codec!(i32);
134int_codec!(u32);
135int_codec!(i16);
136int_codec!(u16);
137int_codec!(i8);
138int_codec!(u8);
139
140
141
142encoded_as_partial_eq!(String);
143
144impl<'a> ESExprCodec<'a> for String {
145	const TAGS: ESExprTagSet = ESExprTagSet::Tags(&[ESExprTag::Str]);
146
147	fn encode_esexpr(&'a self) -> ESExpr<'a> {
148		ESExpr::Str(CowStr::Borrowed(self))
149	}
150
151	fn decode_esexpr(expr: ESExpr<'a>) -> Result<Self, DecodeError> {
152		match expr {
153			ESExpr::Str(s) => Ok(s.into_string()),
154			_ => Err(DecodeError::new(
155				DecodeErrorType::UnexpectedExpr {
156					expected_tags: Self::TAGS,
157					actual_tag: expr.tag().into_owned(),
158				},
159				DecodeErrorPath::Current,
160			)),
161		}
162	}
163}
164
165
166impl <'a> ESExprEncodedEq for Cow<'a, str> {
167	fn is_encoded_eq(&self, other: &Self) -> bool {
168		self == other
169	}
170}
171
172impl<'a> ESExprCodec<'a> for Cow<'a, str> {
173	const TAGS: ESExprTagSet = ESExprTagSet::Tags(&[ESExprTag::Str]);
174
175	fn encode_esexpr(&'a self) -> ESExpr<'a> {
176		ESExpr::Str(CowStr::Borrowed(self.as_ref()))
177	}
178
179	fn decode_esexpr(expr: ESExpr<'a>) -> Result<Self, DecodeError> {
180		match expr {
181			ESExpr::Str(s) => Ok(Cow::from(s)),
182			_ => Err(DecodeError::new(
183				DecodeErrorType::UnexpectedExpr {
184					expected_tags: Self::TAGS,
185					actual_tag: expr.tag().into_owned(),
186				},
187				DecodeErrorPath::Current,
188			)),
189		}
190	}
191}
192
193
194impl <'a> ESExprEncodedEq for CowStr<'a> {
195	fn is_encoded_eq(&self, other: &Self) -> bool {
196		self == other
197	}
198}
199
200impl<'a> ESExprCodec<'a> for CowStr<'a> {
201	const TAGS: ESExprTagSet = ESExprTagSet::Tags(&[ESExprTag::Str]);
202
203	fn encode_esexpr(&'a self) -> ESExpr<'a> {
204		ESExpr::Str(self.as_borrowed())
205	}
206
207	fn decode_esexpr(expr: ESExpr<'a>) -> Result<Self, DecodeError> {
208		match expr {
209			ESExpr::Str(s) => Ok(s),
210			_ => Err(DecodeError::new(
211				DecodeErrorType::UnexpectedExpr {
212					expected_tags: Self::TAGS,
213					actual_tag: expr.tag().into_owned(),
214				},
215				DecodeErrorPath::Current,
216			)),
217		}
218	}
219}
220
221
222
223impl <'a> ESExprEncodedEq for f16 {
224	fn is_encoded_eq(&self, other: &Self) -> bool {
225		self.to_bits() == other.to_bits()
226	}
227}
228
229impl<'a> ESExprCodec<'a> for f16 {
230	const TAGS: ESExprTagSet = ESExprTagSet::Tags(&[ESExprTag::Float16]);
231
232	fn encode_esexpr(&self) -> ESExpr<'a> {
233		ESExpr::Float16(*self)
234	}
235
236	fn decode_esexpr(expr: ESExpr<'a>) -> Result<Self, DecodeError> {
237		match expr {
238			ESExpr::Float16(f) => Ok(f),
239			_ => Err(DecodeError::new(
240				DecodeErrorType::UnexpectedExpr {
241					expected_tags: Self::TAGS,
242					actual_tag: expr.tag().into_owned(),
243				},
244				DecodeErrorPath::Current,
245			)),
246		}
247	}
248}
249
250impl <'a> ESExprEncodedEq for f32 {
251	fn is_encoded_eq(&self, other: &Self) -> bool {
252		self.to_bits() == other.to_bits()
253	}
254}
255
256impl<'a> ESExprCodec<'a> for f32 {
257	const TAGS: ESExprTagSet = ESExprTagSet::Tags(&[ESExprTag::Float32]);
258
259	fn encode_esexpr(&self) -> ESExpr<'a> {
260		ESExpr::Float32(*self)
261	}
262
263	fn decode_esexpr(expr: ESExpr<'a>) -> Result<Self, DecodeError> {
264		match expr {
265			ESExpr::Float32(f) => Ok(f),
266			_ => Err(DecodeError::new(
267				DecodeErrorType::UnexpectedExpr {
268					expected_tags: Self::TAGS,
269					actual_tag: expr.tag().into_owned(),
270				},
271				DecodeErrorPath::Current,
272			)),
273		}
274	}
275}
276
277impl <'a> ESExprEncodedEq for f64 {
278	fn is_encoded_eq(&self, other: &Self) -> bool {
279		self.to_bits() == other.to_bits()
280	}
281}
282
283impl<'a> ESExprCodec<'a> for f64 {
284	const TAGS: ESExprTagSet = ESExprTagSet::Tags(&[ESExprTag::Float64]);
285
286	fn encode_esexpr(&'a self) -> ESExpr<'a> {
287		ESExpr::Float64(*self)
288	}
289
290	fn decode_esexpr(expr: ESExpr<'a>) -> Result<Self, DecodeError> {
291		match expr {
292			ESExpr::Float64(f) => Ok(f),
293			_ => Err(DecodeError::new(
294				DecodeErrorType::UnexpectedExpr {
295					expected_tags: Self::TAGS,
296					actual_tag: expr.tag().into_owned(),
297				},
298				DecodeErrorPath::Current,
299			)),
300		}
301	}
302}
303
304
305encoded_as_partial_eq!(());
306
307impl<'a> ESExprCodec<'a> for () {
308	const TAGS: ESExprTagSet = ESExprTagSet::Tags(&[ESExprTag::Null]);
309
310	fn encode_esexpr<'b>(&'b self) -> ESExpr<'b> {
311		ESExpr::Null(Cow::Owned(BigUint::ZERO))
312	}
313
314	fn decode_esexpr(expr: ESExpr<'a>) -> Result<Self, DecodeError> {
315		match expr {
316			ESExpr::Null(level) if *level == BigUint::ZERO => Ok(()),
317			_ => Err(DecodeError::new(
318				DecodeErrorType::UnexpectedExpr {
319					expected_tags: Self::TAGS,
320					actual_tag: expr.tag().into_owned(),
321				},
322				DecodeErrorPath::Current,
323			)),
324		}
325	}
326}