Skip to main content

lm15/serde/
mod.rs

1//! Canonical JSON serde (docs/serde-rules.md, spec/invariants.md
2//! ยง Serde leniency).
3//!
4//! Every canonical type implements [`Canonical`]: `from_json` reads the
5//! lenient canonical form and runs the constructor invariants (INV-046);
6//! `to_json` writes the one canonical wire form under the omission rule.
7//! The impls are written by hand over `serde_json::Value` because the
8//! leniency rules (INV-040..048), the Number rule coercions and the
9//! omission rule are not expressible with derive attributes. `Serialize`
10//! and `Deserialize` delegate to them, so `serde_json::to_string(&x)` and
11//! `serde_json::from_str::<Request>(s)` work as the api-family expects.
12
13mod config;
14mod credential;
15mod endpoints;
16mod helpers;
17mod kinds;
18mod live;
19mod message;
20mod model_info;
21mod parts;
22mod request;
23mod stream;
24
25use serde_json::Value;
26
27use crate::types::ValidationError;
28
29/// The Number-rule coercions (INV-007/008), shared with the MAP-12 decoder.
30pub(crate) use helpers::{float_from_value, int_from_value};
31pub use kinds::{roundtrip, validate, KINDS};
32
33/// The canonical JSON form of a type.
34pub trait Canonical: Sized {
35    /// Read the canonical form leniently, then validate (INV-046).
36    fn from_json(value: &Value) -> Result<Self, ValidationError>;
37
38    /// Write the one canonical wire form (omission rule).
39    fn to_json(&self) -> Value;
40
41    /// `from_json` on a JSON text.
42    fn from_json_str(text: &str) -> Result<Self, ValidationError> {
43        let value: Value = serde_json::from_str(text)
44            .map_err(|e| ValidationError::value(format!("invalid JSON: {e}")))?;
45        Self::from_json(&value)
46    }
47
48    /// `to_json` as compact JSON text.
49    fn to_json_string(&self) -> String {
50        self.to_json().to_string()
51    }
52}
53
54/// `Serialize`/`Deserialize` through the canonical form.
55macro_rules! impl_serde_via_canonical {
56    ($($ty:ty),+ $(,)?) => {
57        $(
58            impl ::serde::Serialize for $ty {
59                fn serialize<S: ::serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
60                    $crate::serde::Canonical::to_json(self).serialize(serializer)
61                }
62            }
63
64            impl<'de> ::serde::Deserialize<'de> for $ty {
65                fn deserialize<D: ::serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
66                    let value = ::serde_json::Value::deserialize(deserializer)?;
67                    <$ty as $crate::serde::Canonical>::from_json(&value).map_err(::serde::de::Error::custom)
68                }
69            }
70        )+
71    };
72}
73
74pub(crate) use impl_serde_via_canonical;