forked from syndicate-lang/preserves
150 lines
3.8 KiB
Rust
150 lines
3.8 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::sync::Arc;
|
|
|
|
use thiserror::Error;
|
|
|
|
pub trait Parse<Value: NestedValue>: Sized {
|
|
type Language;
|
|
|
|
fn parse<'a, LL: Into<&'a Self::Language>>(language: LL, value: &Value) ->
|
|
Result<Self, ParseError> where Self::Language: 'a;
|
|
}
|
|
|
|
impl<Value: NestedValue> Parse<Value> for Value {
|
|
type Language = ();
|
|
|
|
fn parse<'a, LL: Into<&'a Self::Language>>(_language: LL, value: &Value) ->
|
|
Result<Self, ParseError> where Self::Language: 'a
|
|
{
|
|
Ok(value.clone())
|
|
}
|
|
}
|
|
|
|
pub trait Unparse<Value: NestedValue> {
|
|
type Language;
|
|
|
|
fn unparse<'a, LL: Into<&'a Self::Language>>(&self, language: LL) ->
|
|
Value where Self::Language: 'a;
|
|
}
|
|
|
|
impl<Value: NestedValue> Unparse<Value> for Value {
|
|
type Language = ();
|
|
|
|
fn unparse<'a, LL: Into<&'a Self::Language>>(&self, _language: LL) ->
|
|
Value where Self::Language: 'a
|
|
{
|
|
self.clone()
|
|
}
|
|
}
|
|
|
|
pub trait Codec<N: NestedValue, LL> {
|
|
fn parse<T: Parse<N>>(&self, value: &N) -> Result<T, ParseError>
|
|
where for<'a> &'a LL: Into<&'a T::Language>;
|
|
fn unparse<T: Unparse<N>>(&self, value: &T) -> N
|
|
where for<'a> &'a LL: Into<&'a T::Language>;
|
|
}
|
|
|
|
impl<N: NestedValue + 'static, LL> Codec<N, LL> for LL {
|
|
fn parse<T: Parse<N>>(&self, value: &N) -> Result<T, ParseError>
|
|
where for<'a> &'a LL: Into<&'a T::Language>
|
|
{
|
|
T::parse(self, value)
|
|
}
|
|
|
|
fn unparse<T: Unparse<N>>(&self, value: &T) -> N
|
|
where for<'a> &'a LL: Into<&'a T::Language>
|
|
{
|
|
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 }
|
|
}
|
|
}
|