preserves_schema/support/
mod.rs

1//! The runtime support library for compiled Schemas.
2
3#[doc(hidden)]
4/// Reexport lazy_static for generated code to use.
5pub use lazy_static::lazy_static;
6
7pub use preserves;
8pub use preserves::boundary as B;
9pub use preserves::Error;
10pub use preserves::Reader;
11pub use preserves::ReaderResult;
12pub use preserves::SyntaxError;
13
14pub mod interpret;
15
16use preserves::Domain;
17use preserves::ExpectedKind;
18use preserves::IOValue;
19use preserves::NoEmbeddedDomainCodec;
20use preserves::Value;
21use preserves::packed::Packed;
22
23use std::convert::From;
24use std::convert::Into;
25use std::convert::TryFrom;
26
27/// Every [language][crate::define_language] implements [ValueCodec] as a marker trait.
28pub trait ValueCodec {} // marker trait
29impl ValueCodec for () {}
30
31/// Implementors of [Parse] can produce instances of themselves from a [Value], given a
32/// supporting [language][crate::define_language]. All Schema-compiler-produced types implement
33/// [Parse].
34pub trait Parse<L, D: Domain>: Sized {
35    /// Decode the given `value` (using auxiliary structure from the `language` instance) to
36    /// produce an instance of [Self].
37    fn parse(language: L, value: &Value<D>) -> ReaderResult<Self>;
38}
39
40impl<'a, T: ValueCodec, D: Domain> Parse<&'a T, D> for Value<D> {
41    fn parse(_language: &'a T, value: &Value<D>) -> ReaderResult<Self> {
42        Ok(value.clone())
43    }
44}
45
46/// Implementors of [Unparse] can convert themselves into a [Value], given a supporting
47/// [language][crate::define_language]. All Schema-compiler-produced types implement [Unparse].
48pub trait Unparse<L, D: Domain> {
49    /// Encode `self` into a [Value] (using auxiliary structure from the `language` instance).
50    fn unparse(&self, language: L) -> Value<D>;
51}
52
53impl<'a, T: ValueCodec, D: Domain> Unparse<&'a T, D> for Value<D> {
54    fn unparse(&self, _language: &'a T) -> Value<D> {
55        self.clone()
56    }
57}
58
59/// Every [language][crate::define_language] implements [Codec], which supplies convenient
60/// shorthand for invoking [Parse::parse] and [Unparse::unparse].
61pub trait Codec<D: Domain> {
62    /// Delegates to [`T::parse`][Parse::parse], using `self` as language and the given `value`
63    /// as input.
64    fn parse<'a, T: Parse<&'a Self, D>>(&'a self, value: &Value<D>) -> ReaderResult<T>;
65    /// Delegates to [`value.unparse`][Unparse::unparse], using `self` as language.
66    fn unparse<'a, T: Unparse<&'a Self, D>>(&'a self, value: &T) -> Value<D>;
67}
68
69impl<L, D: Domain> Codec<D> for L {
70    fn parse<'a, T: Parse<&'a L, D>>(&'a self, value: &Value<D>) -> ReaderResult<T> {
71        T::parse(self, value)
72    }
73
74    fn unparse<'a, T: Unparse<&'a L, D>>(&'a self, value: &T) -> Value<D> {
75        value.unparse(self)
76    }
77}
78
79/// Implementors of [Deserialize] can produce instances of themselves from a [Value]. All
80/// Schema-compiler-produced types implement [Deserialize].
81///
82/// The difference between [Deserialize] and [Parse] is that implementors of [Deserialize] know
83/// which [language][crate::define_language] to use.
84pub trait Deserialize<D: Domain>
85where
86    Self: Sized,
87{
88    fn deserialize<
89        'de,
90        R: Reader<'de> + ?Sized,
91        Dec: preserves::DomainDecode<D>
92    >(r: &mut R, dec: &mut Dec) -> ReaderResult<Self>;
93}
94
95/// Extracts a simple literal term from a byte array using
96/// [View][preserves::packed::view::View]. No embedded values are permitted.
97pub fn decode_lit<D: Domain, P: Packed + 'static>(bs: P) -> ReaderResult<Value<D>> {
98    preserves::packed::view(bs, &mut NoEmbeddedDomainCodec, false)
99}
100
101/// When `D` can parse itself from an [IOValue], this function parses all embedded [IOValue]s
102/// into `D`s.
103pub fn decode_embedded<D: Domain>(v: &IOValue) -> ReaderResult<Value<D>>
104where
105    for<'a> D: TryFrom<&'a IOValue, Error = Error>,
106{
107    preserves::value_deepcopy_via(v.into(), &mut |d| Ok(Value::new(preserves::Embedded::new(D::try_from(d)?))))
108}
109
110/// When `D` can unparse itself into an [IOValue], this function converts all embedded `D`s
111/// into [IOValue]s.
112pub fn encode_embedded<D: Domain>(v: &Value<D>) -> IOValue
113where
114    for<'a> IOValue: From<&'a D>,
115{
116    preserves::value_deepcopy_via(v, &mut |d| Result::<_, std::convert::Infallible>::Ok(
117        IOValue::new(preserves::Embedded::new(IOValue::from(d)))))
118        .unwrap().into()
119}
120
121/// True iff `e` is a [Error::SyntaxError].
122pub fn is_syntax_error(e: &Error) -> bool {
123    matches!(e, Error::SyntaxError { .. })
124}
125
126pub fn _expect<T>(r: Result<T, ExpectedKind>) -> ReaderResult<T> {
127    r.map_err(|e| SyntaxError::Expected(e).at(None))
128}
129