use crate::expr::*; use dhall_core::*; use dhall_generator::*; use std::borrow::Cow; #[derive(Debug, Clone)] pub enum ConversionError {} pub trait StaticType { fn get_static_type() -> Type; } /// Trait for rust types that can be represented in dhall in /// a single way, independent of the value. A typical example is `Option`, /// represented by the dhall expression `Optional Bool`. A typical counterexample /// is `HashMap` because dhall cannot represent records with a /// variable number of fields. pub trait SimpleStaticType { fn get_simple_static_type() -> SimpleType; } pub type Error = (); pub type Result = std::result::Result; pub trait Deserialize<'a>: Sized { fn from_str(s: &'a str, ty: Option<&Type>) -> Result; } impl<'a> Deserialize<'a> for Parsed { /// Simply parses the provided string. Ignores the /// provided type. fn from_str(s: &'a str, _ty: Option<&Type>) -> Result { Ok(Parsed::parse_str(s).map_err(|_| ())?) } } impl<'a> Deserialize<'a> for Resolved { /// Parses and resolves the provided string. Ignores the /// provided type. fn from_str(s: &'a str, ty: Option<&Type>) -> Result { Ok(Parsed::from_str(s, ty)? .resolve() .map_err(|_| ())? ) } } impl<'a> Deserialize<'a> for Typed { /// Parses, resolves and typechecks the provided string. fn from_str(s: &'a str, ty: Option<&Type>) -> Result { // TODO: compare with provided type Ok(Resolved::from_str(s, ty)? .typecheck() .map_err(|_| ())? ) } } impl<'a> Deserialize<'a> for Normalized { /// Parses, resolves, typechecks and normalizes the provided string. fn from_str(s: &'a str, ty: Option<&Type>) -> Result { Ok(Typed::from_str(s, ty)?.normalize()) } } impl<'a> Deserialize<'a> for Type { fn from_str(s: &'a str, ty: Option<&Type>) -> Result { Ok(Normalized::from_str(s, ty)?.into_type()) } } fn mktype(x: SubExpr) -> SimpleType { SimpleType(x) } impl StaticType for T { fn get_static_type() -> Type { crate::expr::Normalized( T::get_simple_static_type().into(), Type::const_type(), ) .into_type() } } impl StaticType for SimpleType { fn get_static_type() -> Type { Type::const_type() } } impl SimpleStaticType for bool { fn get_simple_static_type() -> SimpleType { mktype(dhall_expr!(Bool)) } } impl SimpleStaticType for Natural { fn get_simple_static_type() -> SimpleType { mktype(dhall_expr!(Natural)) } } impl SimpleStaticType for Integer { fn get_simple_static_type() -> SimpleType { mktype(dhall_expr!(Integer)) } } impl SimpleStaticType for String { fn get_simple_static_type() -> SimpleType { mktype(dhall_expr!(Text)) } } impl SimpleStaticType for (A, B) { fn get_simple_static_type() -> SimpleType { let ta: SubExpr<_, _> = A::get_simple_static_type().into(); let tb: SubExpr<_, _> = B::get_simple_static_type().into(); mktype(dhall_expr!({ _1: ta, _2: tb })) } } impl SimpleStaticType for Option { fn get_simple_static_type() -> SimpleType { let t: SubExpr<_, _> = T::get_simple_static_type().into(); mktype(dhall_expr!(Optional t)) } } impl SimpleStaticType for Vec { fn get_simple_static_type() -> SimpleType { let t: SubExpr<_, _> = T::get_simple_static_type().into(); mktype(dhall_expr!(List t)) } } impl<'a, T: SimpleStaticType> SimpleStaticType for &'a T { fn get_simple_static_type() -> SimpleType { T::get_simple_static_type() } } impl SimpleStaticType for std::marker::PhantomData { fn get_simple_static_type() -> SimpleType { mktype(dhall_expr!({})) } } impl SimpleStaticType for std::result::Result { fn get_simple_static_type() -> SimpleType { let tt: SubExpr<_, _> = T::get_simple_static_type().into(); let te: SubExpr<_, _> = E::get_simple_static_type().into(); mktype(dhall_expr!(< Ok: tt | Err: te>)) } }