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::value::boundary as B;
9pub use preserves::value::Reader;
10
11pub mod interpret;
12
13use preserves::value::ArcValue;
14use preserves::value::Domain;
15use preserves::value::IOValue;
16use preserves::value::NestedValue;
17use preserves::value::NoEmbeddedDomainCodec;
18use preserves::value::Value;
19
20use std::convert::From;
21use std::convert::Into;
22use std::convert::TryFrom;
23use std::io;
24use std::sync::Arc;
25
26use thiserror::Error;
27
28/// Every [language][crate::define_language] implements [NestedValueCodec] as a marker trait.
29pub trait NestedValueCodec {} // marker trait
30impl NestedValueCodec for () {}
31
32/// Implementors of [Parse] can produce instances of themselves from a [Value], given a
33/// supporting [language][crate::define_language]. All Schema-compiler-produced types implement
34/// [Parse].
35pub trait Parse<L, Value: NestedValue>: Sized {
36    /// Decode the given `value` (using auxiliary structure from the `language` instance) to
37    /// produce an instance of [Self].
38    fn parse(language: L, value: &Value) -> Result<Self, ParseError>;
39}
40
41impl<'a, T: NestedValueCodec, Value: NestedValue> Parse<&'a T, Value> for Value {
42    fn parse(_language: &'a T, value: &Value) -> Result<Self, ParseError> {
43        Ok(value.clone())
44    }
45}
46
47/// Implementors of [Unparse] can convert themselves into a [Value], given a supporting
48/// [language][crate::define_language]. All Schema-compiler-produced types implement [Unparse].
49pub trait Unparse<L, Value: NestedValue> {
50    /// Encode `self` into a [Value] (using auxiliary structure from the `language` instance).
51    fn unparse(&self, language: L) -> Value;
52}
53
54impl<'a, T: NestedValueCodec, Value: NestedValue> Unparse<&'a T, Value> for Value {
55    fn unparse(&self, _language: &'a T) -> Value {
56        self.clone()
57    }
58}
59
60/// Every [language][crate::define_language] implements [Codec], which supplies convenient
61/// shorthand for invoking [Parse::parse] and [Unparse::unparse].
62pub trait Codec<N: NestedValue> {
63    /// Delegates to [`T::parse`][Parse::parse], using `self` as language and the given `value`
64    /// as input.
65    fn parse<'a, T: Parse<&'a Self, N>>(&'a self, value: &N) -> Result<T, ParseError>;
66    /// Delegates to [`value.unparse`][Unparse::unparse], using `self` as language.
67    fn unparse<'a, T: Unparse<&'a Self, N>>(&'a self, value: &T) -> N;
68}
69
70impl<L, N: NestedValue> Codec<N> for L {
71    fn parse<'a, T: Parse<&'a L, N>>(&'a self, value: &N) -> Result<T, ParseError> {
72        T::parse(self, value)
73    }
74
75    fn unparse<'a, T: Unparse<&'a L, N>>(&'a self, value: &T) -> N {
76        value.unparse(self)
77    }
78}
79
80/// Implementors of [Deserialize] can produce instances of themselves from a [Value]. All
81/// Schema-compiler-produced types implement [Deserialize].
82///
83/// The difference between [Deserialize] and [Parse] is that implementors of [Deserialize] know
84/// which [language][crate::define_language] to use.
85pub trait Deserialize<N: NestedValue>
86where
87    Self: Sized,
88{
89    fn deserialize<'de, R: Reader<'de, N>>(r: &mut R) -> Result<Self, ParseError>;
90}
91
92/// Extracts a simple literal term from a byte array using
93/// [PackedReader][preserves::value::packed::PackedReader]. No embedded values are permitted.
94pub fn decode_lit<N: NestedValue>(bs: &[u8]) -> io::Result<N> {
95    preserves::value::packed::from_bytes(bs, NoEmbeddedDomainCodec)
96}
97
98/// When `D` can parse itself from an [IOValue], this function parses all embedded [IOValue]s
99/// into `D`s.
100pub fn decode_embedded<D: Domain>(v: &IOValue) -> Result<ArcValue<Arc<D>>, ParseError>
101where
102    for<'a> D: TryFrom<&'a IOValue, Error = ParseError>,
103{
104    v.copy_via(&mut |d| Ok(Value::Embedded(Arc::new(D::try_from(d)?))))
105}
106
107/// When `D` can unparse itself into an [IOValue], this function converts all embedded `D`s
108/// into [IOValue]s.
109pub fn encode_embedded<D: Domain>(v: &ArcValue<Arc<D>>) -> IOValue
110where
111    for<'a> IOValue: From<&'a D>,
112{
113    v.copy_via::<_, _, std::convert::Infallible>(&mut |d| Ok(Value::Embedded(IOValue::from(d))))
114        .unwrap()
115}
116
117/// Error value yielded when parsing of an [IOValue] into a Schema-compiler-produced type.
118#[derive(Error, Debug)]
119pub enum ParseError {
120    /// Signalled when the input does not match the Preserves Schema associated with the type.
121    #[error("Input not conformant with Schema: {0}")]
122    ConformanceError(&'static str),
123    /// Signalled when the underlying Preserves library signals an error.
124    #[error(transparent)]
125    Preserves(preserves::error::Error),
126}
127
128impl From<preserves::error::Error> for ParseError {
129    fn from(v: preserves::error::Error) -> Self {
130        match v {
131            preserves::error::Error::Expected(_, _) => {
132                ParseError::ConformanceError("preserves::error::Error::Expected")
133            }
134            _ => ParseError::Preserves(v),
135        }
136    }
137}
138
139impl From<io::Error> for ParseError {
140    fn from(v: io::Error) -> Self {
141        preserves::error::Error::from(v).into()
142    }
143}
144
145impl From<ParseError> for io::Error {
146    fn from(v: ParseError) -> Self {
147        match v {
148            ParseError::ConformanceError(_) => io::Error::new(io::ErrorKind::InvalidData, v),
149            ParseError::Preserves(e) => e.into(),
150        }
151    }
152}
153
154impl ParseError {
155    /// Constructs a [ParseError::ConformanceError].
156    pub fn conformance_error(context: &'static str) -> Self {
157        ParseError::ConformanceError(context)
158    }
159
160    /// True iff `self` is a [ParseError::ConformanceError].
161    pub fn is_conformance_error(&self) -> bool {
162        return if let ParseError::ConformanceError(_) = self {
163            true
164        } else {
165            false
166        };
167    }
168}