use crate::SimpleType; /// A Rust type that can be represented as a Dhall type. /// /// A typical example is `Option`, represented by the Dhall expression `Optional Bool`. /// /// This trait can be automatically derived, and this is the recommended way of implementing it. /// /// Some Rust types cannot implement this trait, because there isn't a single Dhall type that /// corresponds to them. For example, `HashMap` could correspond to multiple different /// Dhall types, e.g. `{ foo: Natural, bar: Natural }` and `{ baz: Natural }`. /// /// # Example /// /// ```rust /// # fn main() -> serde_dhall::Result<()> { /// use serde_dhall::{SimpleType, StaticType}; /// /// #[derive(StaticType)] /// struct Foo { /// x: bool, /// y: Vec, /// } /// /// let ty: SimpleType = /// serde_dhall::from_str("{ x: Bool, y: List Natural }")?; /// /// assert_eq!(Foo::static_type(), ty); /// # Ok(()) /// # } /// ``` /// /// # Type correspondence /// /// The following Dhall types correspond to the following Rust types: /// /// Dhall | Rust /// -------|------ /// `Bool` | `bool` /// `Natural` | `u64`, `u32`, ... /// `Integer` | `i64`, `i32`, ... /// `Double` | `f64`, `f32`, ... /// `Text` | `String` /// `List T` | `Vec` /// `Optional T` | `Option` /// `{ x: T, y: U }` | structs /// `{ _1: T, _2: U }` | `(T, U)`, structs /// `{ x: T, y: T }` | `HashMap`, structs /// `< x: T \| y: U >` | enums /// `T -> U` | unsupported /// `Prelude.JSON.Type` | unsupported /// `Prelude.Map.Type T U` | unsupported pub trait StaticType { /// Return the Dhall type that represents this type. /// /// # Example /// /// ```rust /// # fn main() -> serde_dhall::Result<()> { /// use serde::Deserialize; /// use serde_dhall::{SimpleType, StaticType}; /// /// // Using `derive(StaticType)` here would give it the type `{ _1: List Natural }`. /// #[derive(Deserialize)] /// #[serde(transparent)] /// struct Foo(Vec); /// /// impl StaticType for Foo { /// fn static_type() -> SimpleType { /// SimpleType::List(Box::new(SimpleType::Natural)) /// } /// } /// /// let foo: Foo = serde_dhall::from_str_static_type("[ 1, 2 ]")?; /// /// assert_eq!(foo.0, vec![1, 2]); /// # Ok(()) /// # } /// ``` fn static_type() -> SimpleType; } macro_rules! derive_builtin { ($rust_ty:ty, $dhall_ty:ident) => { impl StaticType for $rust_ty { fn static_type() -> SimpleType { SimpleType::$dhall_ty } } }; } derive_builtin!(bool, Bool); derive_builtin!(usize, Natural); derive_builtin!(u64, Natural); derive_builtin!(u32, Natural); derive_builtin!(isize, Integer); derive_builtin!(i64, Integer); derive_builtin!(i32, Integer); derive_builtin!(f64, Double); derive_builtin!(f32, Double); derive_builtin!(String, Text); impl StaticType for (A, B) where A: StaticType, B: StaticType, { fn static_type() -> SimpleType { SimpleType::Record( vec![ ("_1".to_owned(), A::static_type()), ("_2".to_owned(), B::static_type()), ] .into_iter() .collect(), ) .into() } } impl StaticType for std::result::Result where T: StaticType, E: StaticType, { fn static_type() -> SimpleType { SimpleType::Union( vec![ ("Ok".to_owned(), Some(T::static_type())), ("Err".to_owned(), Some(E::static_type())), ] .into_iter() .collect(), ) .into() } } impl StaticType for Option where T: StaticType, { fn static_type() -> SimpleType { SimpleType::Optional(Box::new(T::static_type())).into() } } impl StaticType for Vec where T: StaticType, { fn static_type() -> SimpleType { SimpleType::List(Box::new(T::static_type())).into() } } impl<'a, T> StaticType for &'a T where T: StaticType, { fn static_type() -> SimpleType { T::static_type() } }