1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//! The runtime support library for compiled Schemas.

#[doc(hidden)]
/// Reexport lazy_static for generated code to use.
pub use lazy_static::lazy_static;

pub use preserves;
pub use preserves::value::boundary as B;
pub use preserves::value::Reader;

pub mod interpret;

use preserves::value::ArcValue;
use preserves::value::Domain;
use preserves::value::IOValue;
use preserves::value::NestedValue;
use preserves::value::NoEmbeddedDomainCodec;
use preserves::value::Value;

use std::convert::From;
use std::convert::Into;
use std::convert::TryFrom;
use std::io;
use std::sync::Arc;

use thiserror::Error;

/// Every [language][crate::define_language] implements [NestedValueCodec] as a marker trait.
pub trait NestedValueCodec {} // marker trait
impl NestedValueCodec for () {}

/// Implementors of [Parse] can produce instances of themselves from a [Value], given a
/// supporting [language][crate::define_language]. All Schema-compiler-produced types implement
/// [Parse].
pub trait Parse<L, Value: NestedValue>: Sized {
    /// Decode the given `value` (using auxiliary structure from the `language` instance) to
    /// produce an instance of [Self].
    fn parse(language: L, value: &Value) -> Result<Self, ParseError>;
}

impl<'a, T: NestedValueCodec, Value: NestedValue> Parse<&'a T, Value> for Value {
    fn parse(_language: &'a T, value: &Value) -> Result<Self, ParseError> {
        Ok(value.clone())
    }
}

/// Implementors of [Unparse] can convert themselves into a [Value], given a supporting
/// [language][crate::define_language]. All Schema-compiler-produced types implement [Unparse].
pub trait Unparse<L, Value: NestedValue> {
    /// Encode `self` into a [Value] (using auxiliary structure from the `language` instance).
    fn unparse(&self, language: L) -> Value;
}

impl<'a, T: NestedValueCodec, Value: NestedValue> Unparse<&'a T, Value> for Value {
    fn unparse(&self, _language: &'a T) -> Value {
        self.clone()
    }
}

/// Every [language][crate::define_language] implements [Codec], which supplies convenient
/// shorthand for invoking [Parse::parse] and [Unparse::unparse].
pub trait Codec<N: NestedValue> {
    /// Delegates to [`T::parse`][Parse::parse], using `self` as language and the given `value`
    /// as input.
    fn parse<'a, T: Parse<&'a Self, N>>(&'a self, value: &N) -> Result<T, ParseError>;
    /// Delegates to [`value.unparse`][Unparse::unparse], using `self` as language.
    fn unparse<'a, T: Unparse<&'a Self, N>>(&'a self, value: &T) -> N;
}

impl<L, N: NestedValue> Codec<N> for L {
    fn parse<'a, T: Parse<&'a L, N>>(&'a self, value: &N) -> Result<T, ParseError> {
        T::parse(self, value)
    }

    fn unparse<'a, T: Unparse<&'a L, N>>(&'a self, value: &T) -> N {
        value.unparse(self)
    }
}

/// Implementors of [Deserialize] can produce instances of themselves from a [Value]. All
/// Schema-compiler-produced types implement [Deserialize].
///
/// The difference between [Deserialize] and [Parse] is that implementors of [Deserialize] know
/// which [language][crate::define_language] to use.
pub trait Deserialize<N: NestedValue>
where
    Self: Sized,
{
    fn deserialize<'de, R: Reader<'de, N>>(r: &mut R) -> Result<Self, ParseError>;
}

/// Extracts a simple literal term from a byte array using
/// [PackedReader][preserves::value::packed::PackedReader]. No embedded values are permitted.
pub fn decode_lit<N: NestedValue>(bs: &[u8]) -> io::Result<N> {
    preserves::value::packed::from_bytes(bs, NoEmbeddedDomainCodec)
}

/// When `D` can parse itself from an [IOValue], this function parses all embedded [IOValue]s
/// into `D`s.
pub fn decode_embedded<D: Domain>(v: &IOValue) -> Result<ArcValue<Arc<D>>, ParseError>
where
    for<'a> D: TryFrom<&'a IOValue, Error = ParseError>,
{
    v.copy_via(&mut |d| Ok(Value::Embedded(Arc::new(D::try_from(d)?))))
}

/// When `D` can unparse itself into an [IOValue], this function converts all embedded `D`s
/// into [IOValue]s.
pub fn encode_embedded<D: Domain>(v: &ArcValue<Arc<D>>) -> IOValue
where
    for<'a> IOValue: From<&'a D>,
{
    v.copy_via::<_, _, std::convert::Infallible>(&mut |d| Ok(Value::Embedded(IOValue::from(d))))
        .unwrap()
}

/// Error value yielded when parsing of an [IOValue] into a Schema-compiler-produced type.
#[derive(Error, Debug)]
pub enum ParseError {
    /// Signalled when the input does not match the Preserves Schema associated with the type.
    #[error("Input not conformant with Schema: {0}")]
    ConformanceError(&'static str),
    /// Signalled when the underlying Preserves library signals an error.
    #[error(transparent)]
    Preserves(preserves::error::Error),
}

impl From<preserves::error::Error> for ParseError {
    fn from(v: preserves::error::Error) -> Self {
        match v {
            preserves::error::Error::Expected(_, _) => {
                ParseError::ConformanceError("preserves::error::Error::Expected")
            }
            _ => ParseError::Preserves(v),
        }
    }
}

impl From<io::Error> for ParseError {
    fn from(v: io::Error) -> Self {
        preserves::error::Error::from(v).into()
    }
}

impl From<ParseError> for io::Error {
    fn from(v: ParseError) -> Self {
        match v {
            ParseError::ConformanceError(_) => io::Error::new(io::ErrorKind::InvalidData, v),
            ParseError::Preserves(e) => e.into(),
        }
    }
}

impl ParseError {
    /// Constructs a [ParseError::ConformanceError].
    pub fn conformance_error(context: &'static str) -> Self {
        ParseError::ConformanceError(context)
    }

    /// True iff `self` is a [ParseError::ConformanceError].
    pub fn is_conformance_error(&self) -> bool {
        return if let ParseError::ConformanceError(_) = self {
            true
        } else {
            false
        };
    }
}