preserves/implementations/rust/preserves-schema/src/support/mod.rs

133 lines
3.6 KiB
Rust

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::marker::PhantomData;
use std::sync::Arc;
use thiserror::Error;
pub trait Parse<L, Value: NestedValue>: Sized {
// fn parse(literals: &L, value: &Value) -> Result<Self, ParseError>;
fn parse<'a, LL: Into<&'a L>>(literals: LL, value: &Value) -> Result<Self, ParseError> where L: 'a;
}
impl<L, Value: NestedValue> Parse<L, Value> for Value {
fn parse<'a, LL: Into<&'a L>>(_literals: LL, value: &Value) -> Result<Self, ParseError> where L: 'a {
Ok(value.clone())
}
}
pub trait Unparse<L, Value: NestedValue> {
// fn unparse(&self, literals: &L) -> Value;
fn unparse<'a, LL: Into<&'a L>>(&self, literals: LL) -> Value where L: 'a;
}
impl<L, Value: NestedValue> Unparse<L, Value> for Value {
fn unparse<'a, LL: Into<&'a L>>(&self, _literals: LL) -> Value where L: 'a {
self.clone()
}
}
pub trait Codec<L, N: NestedValue> {
fn parse<T: Parse<L, N>>(&self, value: &N) -> Result<T, ParseError>;
fn unparse<T: Unparse<L, N>>(&self, value: &T) -> N;
}
impl<L, N: NestedValue, LL> Codec<L, N> for LL where for<'a> &'a LL: Into<&'a L> {
fn parse<T: Parse<L, N>>(&self, value: &N) -> Result<T, ParseError> {
T::parse(self, value)
}
fn unparse<T: Unparse<L, N>>(&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 }
}
}