1#![no_std]
3
4extern crate alloc;
5extern crate core;
6
7use alloc::borrow::Cow;
8use alloc::collections::BTreeMap;
9use alloc::string::String;
10use alloc::vec::Vec;
11use core::f32;
12
13use base64::Engine;
14use base64::prelude::BASE64_STANDARD;
15use esexpr::cowstr::CowStr;
16use esexpr::{ESExpr, ESExprCodec, ESExprConstructor, ESExprEncodedEq};
17use half::f16;
18use num_bigint::{BigInt, BigUint};
19
20#[derive(ESExprCodec, ESExprEncodedEq, Debug, PartialEq)]
22pub enum JsonExpr {
23	Obj {
25		#[esexpr(dict)]
27		values: BTreeMap<String, JsonExpr>,
28	},
29
30	#[esexpr(inline_value)]
32	Arr(Vec<JsonExpr>),
33
34	#[esexpr(inline_value)]
36	Str(String),
37
38	#[esexpr(inline_value)]
40	Num(f64),
41
42	#[esexpr(inline_value)]
44	Bool(bool),
45
46	#[esexpr(inline_value)]
48	Null(()),
49}
50
51impl JsonExpr {
52	pub fn from_json(value: serde_json::Value) -> Option<JsonExpr> {
54		Some(match value {
55			serde_json::Value::Null => JsonExpr::Null(()),
56			serde_json::Value::Bool(b) => JsonExpr::Bool(b),
57			serde_json::Value::Number(n) => JsonExpr::Num(n.as_f64()?),
58			serde_json::Value::String(s) => JsonExpr::Str(s),
59			serde_json::Value::Array(arr) => {
60				JsonExpr::Arr(arr.into_iter().map(Self::from_json).collect::<Option<Vec<_>>>()?)
61			},
62			serde_json::Value::Object(obj) => {
63				let values = obj
64					.into_iter()
65					.map(|(k, v)| Some((k, Self::from_json(v)?)))
66					.collect::<Option<BTreeMap<_, _>>>()?;
67
68				JsonExpr::Obj { values }
69			},
70		})
71	}
72
73	pub fn into_json(self) -> Option<serde_json::Value> {
75		Some(match self {
76			JsonExpr::Obj { values } => {
77				let obj = values
78					.into_iter()
79					.map(|(k, v)| Some((k, v.into_json()?)))
80					.collect::<Option<serde_json::Map<_, _>>>()?;
81
82				serde_json::Value::Object(obj)
83			},
84			JsonExpr::Arr(arr) => {
85				serde_json::Value::Array(arr.into_iter().map(Self::into_json).collect::<Option<Vec<_>>>()?)
86			},
87			JsonExpr::Str(s) => serde_json::Value::String(s),
88			JsonExpr::Num(n) => serde_json::Value::Number(serde_json::Number::from_f64(n)?),
89			JsonExpr::Bool(b) => serde_json::Value::Bool(b),
90			JsonExpr::Null(_) => serde_json::Value::Null,
91		})
92	}
93}
94
95#[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)]
97#[serde(untagged)]
98pub enum JsonEncodedESExpr {
99	Constructor {
101		constructor_name: String,
103		args: Option<Vec<JsonEncodedESExpr>>,
105		kwargs: Option<BTreeMap<String, JsonEncodedESExpr>>,
107	},
108	List(Vec<JsonEncodedESExpr>),
110
111	Bool(bool),
113
114	Int {
116		#[serde(with = "serde_bigint")]
118		int: BigInt,
119	},
120
121	Str(String),
123
124	BinaryBase64 {
126		base64: Base64Value,
128	},
129
130	Array8 {
132		array8: Vec<u8>,
134	},
135
136	Array16 {
138		array16: Vec<u16>,
140	},
141
142	Array32 {
144		array32: Vec<u32>,
146	},
147
148	Array64 {
150		array64: Vec<u64>,
152	},
153
154	Array128 {
156		#[serde(with = "serde_u128_vec")]
158		array128: Vec<u128>,
159	},
160
161	Float16 {
163		#[serde(with = "serde_f16")]
165		float16: f16,
166	},
167
168	Float32 {
170		#[serde(with = "serde_f32")]
172		float32: f32,
173	},
174
175	Float64 {
177		#[serde(with = "serde_f64")]
179		float64: f64,
180	},
181
182	Null(()),
184
185	NullLevel {
187		#[serde(with = "serde_biguint")]
189		null: BigUint,
190	},
191}
192
193impl JsonEncodedESExpr {
194	pub fn from_esexpr(expr: ESExpr) -> Self {
196		match expr {
197			ESExpr::Constructor(ESExprConstructor { name, args, kwargs }) => JsonEncodedESExpr::Constructor {
198				constructor_name: name.into_string(),
199				args: Some(args.into_iter().map(Self::from_esexpr).collect()),
200				kwargs: Some(
201					kwargs
202						.into_iter()
203						.map(|(k, v)| (k.into_string(), Self::from_esexpr(v)))
204						.collect(),
205				),
206			},
207			ESExpr::Bool(b) => JsonEncodedESExpr::Bool(b),
208			ESExpr::Int(i) => JsonEncodedESExpr::Int { int: i.into_owned() },
209			ESExpr::Str(s) => JsonEncodedESExpr::Str(s.into_string()),
210			ESExpr::Float16(float16) => JsonEncodedESExpr::Float16 { float16 },
211			ESExpr::Float32(float32) => JsonEncodedESExpr::Float32 { float32 },
212			ESExpr::Float64(float64) => JsonEncodedESExpr::Float64 { float64 },
213			ESExpr::Array8(b) => JsonEncodedESExpr::BinaryBase64 {
214				base64: Base64Value(b.into_owned()),
215			},
216			ESExpr::Array16(b) => JsonEncodedESExpr::Array16 {
217				array16: b.into_owned(),
218			},
219			ESExpr::Array32(b) => JsonEncodedESExpr::Array32 {
220				array32: b.into_owned(),
221			},
222			ESExpr::Array64(b) => JsonEncodedESExpr::Array64 {
223				array64: b.into_owned(),
224			},
225			ESExpr::Array128(b) => JsonEncodedESExpr::Array128 {
226				array128: b.into_owned(),
227			},
228			ESExpr::Null(level) if *level == BigUint::ZERO => JsonEncodedESExpr::Null(()),
229			ESExpr::Null(level) => JsonEncodedESExpr::NullLevel {
230				null: level.into_owned(),
231			},
232		}
233	}
234
235	pub fn into_esexpr(self) -> ESExpr<'static> {
237		match self {
238			JsonEncodedESExpr::Constructor {
239				constructor_name,
240				args,
241				kwargs,
242			} => ESExpr::constructor(
243				constructor_name,
244				args.unwrap_or_default()
245					.into_iter()
246					.map(Self::into_esexpr)
247					.collect::<Vec<_>>(),
248				kwargs
249					.unwrap_or_default()
250					.into_iter()
251					.map(|(k, v)| (CowStr::Owned(k), v.into_esexpr()))
252					.collect::<BTreeMap<_, _>>(),
253			),
254			JsonEncodedESExpr::List(l) => {
255				ESExpr::constructor("list", l.into_iter().map(Self::into_esexpr).collect::<Vec<_>>(), [])
256			},
257
258			JsonEncodedESExpr::Bool(b) => ESExpr::Bool(b),
259			JsonEncodedESExpr::Int { int } => ESExpr::Int(Cow::Owned(int)),
260			JsonEncodedESExpr::Str(s) => ESExpr::Str(CowStr::Owned(s)),
261			JsonEncodedESExpr::BinaryBase64 { base64 } => ESExpr::Array8(Cow::Owned(base64.0)),
262			JsonEncodedESExpr::Array8 { array8 } => ESExpr::Array8(Cow::Owned(array8)),
263			JsonEncodedESExpr::Array16 { array16 } => ESExpr::Array16(Cow::Owned(array16)),
264			JsonEncodedESExpr::Array32 { array32 } => ESExpr::Array32(Cow::Owned(array32)),
265			JsonEncodedESExpr::Array64 { array64 } => ESExpr::Array64(Cow::Owned(array64)),
266			JsonEncodedESExpr::Array128 { array128 } => ESExpr::Array128(Cow::Owned(array128)),
267			JsonEncodedESExpr::Float16 { float16 } => ESExpr::Float16(float16),
268			JsonEncodedESExpr::Float32 { float32 } => ESExpr::Float32(float32),
269			JsonEncodedESExpr::Float64 { float64 } => ESExpr::Float64(float64),
270			JsonEncodedESExpr::Null(_) => ESExpr::Null(Cow::Owned(BigUint::ZERO)),
271			JsonEncodedESExpr::NullLevel { null } => ESExpr::Null(Cow::Owned(null)),
272		}
273	}
274}
275
276#[derive(Debug, PartialEq)]
278pub struct Base64Value(Vec<u8>);
279
280impl serde::Serialize for Base64Value {
281	fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
282		let encoded = BASE64_STANDARD.encode(&self.0);
283		serializer.serialize_str(&encoded)
284	}
285}
286
287struct Base64Visitor;
288
289impl<'de> serde::de::Visitor<'de> for Base64Visitor {
290	type Value = Vec<u8>;
291
292	fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
293		formatter.write_str("a base64 encoded string")
294	}
295
296	fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<Vec<u8>, E> {
297		BASE64_STANDARD
298			.decode(value)
299			.map_err(|_| serde::de::Error::invalid_value(serde::de::Unexpected::Str(value), &self))
300	}
301}
302
303impl<'de> serde::Deserialize<'de> for Base64Value {
304	fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
305		let bytes = deserializer.deserialize_str(Base64Visitor)?;
306		Ok(Base64Value(bytes))
307	}
308}
309
310mod serde_u128_vec {
313	use alloc::format;
314	use alloc::vec::Vec;
315
316	use serde::{Deserialize, Serialize};
317
318	pub fn serialize<S: serde::Serializer>(f: &Vec<u128>, serializer: S) -> Result<S::Ok, S::Error> {
319		<Vec<u128>>::serialize(f, serializer)
320	}
321
322	pub fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<Vec<u128>, D::Error> {
323		let value = serde_json::Value::deserialize(deserializer)?;
324		match serde_json::from_value(value) {
325			Ok(v) => Ok(v),
326			Err(e) => Err(serde::de::Error::custom(format!("{e:?}"))),
327		}
328	}
329}
330
331mod serde_f16 {
333	use half::f16;
334
335	use crate::serde_f32;
336
337	#[expect(clippy::trivially_copy_pass_by_ref, reason = "serde requires this to be a reference")]
338	pub fn serialize<S: serde::Serializer>(f: &f16, serializer: S) -> Result<S::Ok, S::Error> {
339		serde_f32::serialize(&f32::from(*f), serializer)
340	}
341
342	pub fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<f16, D::Error> {
343		serde_f32::deserialize(deserializer).map(f16::from_f32)
344	}
345}
346
347mod serde_f32 {
349	#[expect(clippy::trivially_copy_pass_by_ref, reason = "serde requires this to be a reference")]
350	pub fn serialize<S: serde::Serializer>(f: &f32, serializer: S) -> Result<S::Ok, S::Error> {
351		match *f {
352			f if f.is_nan() => serializer.serialize_str("nan"),
353			f if f.is_infinite() && f.is_sign_positive() => serializer.serialize_str("+inf"),
354			f if f.is_infinite() && f.is_sign_negative() => serializer.serialize_str("-inf"),
355			f => serializer.serialize_f32(f),
356		}
357	}
358
359	pub fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<f32, D::Error> {
360		struct Float32ValueVisitor;
361
362		impl<'de> serde::de::Visitor<'de> for Float32ValueVisitor {
363			type Value = f32;
364
365			fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
366				formatter.write_str("a number or a string containing nan, +inf, or -inf")
367			}
368
369			#[expect(clippy::cast_precision_loss, reason = "The format makes it explicit this is a f32")]
370			fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<f32, E> {
371				Ok(v as f32)
372			}
373
374			#[expect(clippy::cast_precision_loss, reason = "The format makes it explicit this is a f32")]
375			fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<f32, E> {
376				Ok(v as f32)
377			}
378
379			#[expect(
380				clippy::cast_possible_truncation,
381				reason = "The format makes it explicit this is a f64"
382			)]
383			fn visit_f64<E: serde::de::Error>(self, v: f64) -> Result<f32, E> {
384				Ok(v as f32)
385			}
386
387			fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<f32, E> {
388				match value {
389					"nan" => Ok(f32::NAN),
390					"+inf" => Ok(f32::INFINITY),
391					"-inf" => Ok(f32::NEG_INFINITY),
392					_ => Err(serde::de::Error::invalid_value(
393						serde::de::Unexpected::Str(value),
394						&self,
395					)),
396				}
397			}
398		}
399
400		deserializer.deserialize_any(Float32ValueVisitor)
401	}
402}
403
404mod serde_f64 {
406	#[expect(clippy::trivially_copy_pass_by_ref, reason = "serde requires this to be a reference")]
407	pub fn serialize<S: serde::Serializer>(f: &f64, serializer: S) -> Result<S::Ok, S::Error> {
408		match *f {
409			f if f.is_nan() => serializer.serialize_str("nan"),
410			f if f.is_infinite() && f.is_sign_positive() => serializer.serialize_str("+inf"),
411			f if f.is_infinite() && f.is_sign_negative() => serializer.serialize_str("-inf"),
412			f => serializer.serialize_f64(f),
413		}
414	}
415
416	pub fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<f64, D::Error> {
417		struct Float64ValueVisitor;
418
419		impl<'de> serde::de::Visitor<'de> for Float64ValueVisitor {
420			type Value = f64;
421
422			fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
423				formatter.write_str("a number or a string containing nan, +inf, or -inf")
424			}
425
426			#[expect(clippy::cast_precision_loss, reason = "The format makes it explicit this is a f64")]
427			fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<f64, E> {
428				Ok(v as f64)
429			}
430
431			#[expect(clippy::cast_precision_loss, reason = "The format makes it explicit this is a f64")]
432			fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<f64, E> {
433				Ok(v as f64)
434			}
435
436			fn visit_f64<E: serde::de::Error>(self, v: f64) -> Result<f64, E> {
437				Ok(v)
438			}
439
440			fn visit_str<E: serde::de::Error>(self, value: &str) -> Result<f64, E> {
441				match value {
442					"nan" => Ok(f64::NAN),
443					"+inf" => Ok(f64::INFINITY),
444					"-inf" => Ok(f64::NEG_INFINITY),
445					_ => Err(serde::de::Error::invalid_value(
446						serde::de::Unexpected::Str(value),
447						&self,
448					)),
449				}
450			}
451		}
452
453		deserializer.deserialize_any(Float64ValueVisitor)
454	}
455}
456
457mod serde_bigint {
459	use alloc::string::{String, ToString};
460
461	use num_bigint::BigInt;
462	use serde::Deserialize;
463
464	pub fn serialize<S: serde::Serializer>(value: &BigInt, serializer: S) -> Result<S::Ok, S::Error> {
465		serializer.serialize_str(&value.to_string())
466	}
467
468	pub fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<BigInt, D::Error> {
469		let s = String::deserialize(deserializer)?;
470		BigInt::parse_bytes(s.as_bytes(), 10).ok_or_else(|| {
471			serde::de::Error::invalid_value(serde::de::Unexpected::Str(&s), &"a string containing a big integer")
472		})
473	}
474}
475
476mod serde_biguint {
478	use alloc::string::{String, ToString};
479
480	use num_bigint::BigUint;
481	use serde::Deserialize;
482
483	pub fn serialize<S: serde::Serializer>(value: &BigUint, serializer: S) -> Result<S::Ok, S::Error> {
484		serializer.serialize_str(&value.to_string())
485	}
486
487	pub fn deserialize<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Result<BigUint, D::Error> {
488		let s = String::deserialize(deserializer)?;
489		BigUint::parse_bytes(s.as_bytes(), 10).ok_or_else(|| {
490			serde::de::Error::invalid_value(
491				serde::de::Unexpected::Str(&s),
492				&"a string containing an unsigned big integer",
493			)
494		})
495	}
496}