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
pub use lazy_static::lazy_static;

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

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;

pub trait NestedValueCodec {} // marker trait
impl NestedValueCodec for () {}

pub trait Parse<L, Value: NestedValue>: Sized {
    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())
    }
}

pub trait Unparse<L, Value: NestedValue> {
    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()
    }
}

pub trait Codec<N: NestedValue> {
    fn parse<'a, T: Parse<&'a Self, N>>(&'a self, value: &N) -> Result<T, ParseError>;
    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)
    }
}

pub trait Deserialize<'de, N: NestedValue, R: Reader<'de, N>>
where
    Self: Sized
{
    fn deserialize(r: &mut R) -> Result<Self, ParseError>;
}

pub fn decode_lit<N: NestedValue>(bs: &[u8]) -> io::Result<N> {
    preserves::value::packed::from_bytes(bs, NoEmbeddedDomainCodec)
}

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)?))))
}

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()
}

#[derive(Error, Debug)]
pub enum ParseError {
    #[error("Input not conformant with Schema: {0}")]
    ConformanceError(&'static str),
    #[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 {
    pub fn conformance_error(context: &'static str) -> Self {
        ParseError::ConformanceError(context)
    }

    pub fn is_conformance_error(&self) -> bool {
        return if let ParseError::ConformanceError(_) = self { true } else { false }
    }
}