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}