serde_dhall/
static_type.rs

1use crate::SimpleType;
2
3/// A Rust type that can be represented as a Dhall type.
4///
5/// A typical example is `Option<bool>`, represented by the Dhall expression `Optional Bool`.
6///
7/// This trait can be automatically derived, and this is the recommended way of implementing it.
8///
9/// Some Rust types cannot implement this trait, because there isn't a single Dhall type that
10/// corresponds to them. For example, `HashMap<String, u64>` could correspond to multiple different
11/// Dhall types, e.g. `{ foo: Natural, bar: Natural }` and `{ baz: Natural }`.
12///
13/// See also [the table of type correspondances].
14///
15/// [the table of type correspondances]: SimpleType#type-correspondence
16///
17/// # Example
18///
19/// ```rust
20/// # fn main() -> serde_dhall::Result<()> {
21/// use serde_dhall::{SimpleType, StaticType};
22///
23/// #[derive(StaticType)]
24/// struct Foo {
25///     x: bool,
26///     y: Vec<u64>,
27/// }
28///
29/// let ty: SimpleType =
30///     serde_dhall::from_str("{ x: Bool, y: List Natural }").parse()?;
31///
32/// assert_eq!(Foo::static_type(), ty);
33/// # Ok(())
34/// # }
35/// ```
36pub trait StaticType {
37    /// Return the Dhall type that represents this type.
38    ///
39    /// # Example
40    ///
41    /// ```rust
42    /// # fn main() -> serde_dhall::Result<()> {
43    /// use serde::Deserialize;
44    /// use serde_dhall::{SimpleType, StaticType};
45    ///
46    /// // Using `derive(StaticType)` here would give it the type `{ _1: List Natural }`.
47    /// #[derive(Deserialize)]
48    /// #[serde(transparent)]
49    /// struct Foo(Vec<u64>);
50    ///
51    /// impl StaticType for Foo {
52    ///     fn static_type() -> SimpleType {
53    ///         SimpleType::List(Box::new(SimpleType::Natural))
54    ///     }
55    /// }
56    ///
57    /// let foo = serde_dhall::from_str("[ 1, 2 ]")
58    ///     .static_type_annotation()
59    ///     .parse::<Foo>()?;
60    ///
61    /// assert_eq!(foo.0, vec![1, 2]);
62    /// # Ok(())
63    /// # }
64    /// ```
65    fn static_type() -> SimpleType;
66}
67
68macro_rules! derive_builtin {
69    ($rust_ty:ty, $dhall_ty:ident) => {
70        impl StaticType for $rust_ty {
71            fn static_type() -> SimpleType {
72                SimpleType::$dhall_ty
73            }
74        }
75    };
76}
77
78derive_builtin!(bool, Bool);
79derive_builtin!(usize, Natural);
80derive_builtin!(u64, Natural);
81derive_builtin!(u32, Natural);
82derive_builtin!(u16, Natural);
83derive_builtin!(isize, Integer);
84derive_builtin!(i64, Integer);
85derive_builtin!(i32, Integer);
86derive_builtin!(f64, Double);
87derive_builtin!(f32, Double);
88derive_builtin!(String, Text);
89derive_builtin!(&str, Text);
90
91impl StaticType for () {
92    fn static_type() -> SimpleType {
93        SimpleType::Record(vec![].into_iter().collect())
94    }
95}
96
97impl<A> StaticType for (A,)
98where
99    A: StaticType,
100{
101    fn static_type() -> SimpleType {
102        SimpleType::Record(
103            vec![("_1".to_owned(), A::static_type())]
104                .into_iter()
105                .collect(),
106        )
107    }
108}
109
110impl<A, B> StaticType for (A, B)
111where
112    A: StaticType,
113    B: StaticType,
114{
115    fn static_type() -> SimpleType {
116        SimpleType::Record(
117            vec![
118                ("_1".to_owned(), A::static_type()),
119                ("_2".to_owned(), B::static_type()),
120            ]
121            .into_iter()
122            .collect(),
123        )
124    }
125}
126
127impl<A, B, C> StaticType for (A, B, C)
128where
129    A: StaticType,
130    B: StaticType,
131    C: StaticType,
132{
133    fn static_type() -> SimpleType {
134        SimpleType::Record(
135            vec![
136                ("_1".to_owned(), A::static_type()),
137                ("_2".to_owned(), B::static_type()),
138                ("_3".to_owned(), C::static_type()),
139            ]
140            .into_iter()
141            .collect(),
142        )
143    }
144}
145
146impl<A, B, C, D> StaticType for (A, B, C, D)
147where
148    A: StaticType,
149    B: StaticType,
150    C: StaticType,
151    D: StaticType,
152{
153    fn static_type() -> SimpleType {
154        SimpleType::Record(
155            vec![
156                ("_1".to_owned(), A::static_type()),
157                ("_2".to_owned(), B::static_type()),
158                ("_3".to_owned(), C::static_type()),
159                ("_4".to_owned(), D::static_type()),
160            ]
161            .into_iter()
162            .collect(),
163        )
164    }
165}
166
167impl<T, E> StaticType for std::result::Result<T, E>
168where
169    T: StaticType,
170    E: StaticType,
171{
172    fn static_type() -> SimpleType {
173        SimpleType::Union(
174            vec![
175                ("Ok".to_owned(), Some(T::static_type())),
176                ("Err".to_owned(), Some(E::static_type())),
177            ]
178            .into_iter()
179            .collect(),
180        )
181    }
182}
183
184impl<T> StaticType for Option<T>
185where
186    T: StaticType,
187{
188    fn static_type() -> SimpleType {
189        SimpleType::Optional(Box::new(T::static_type()))
190    }
191}
192
193impl<T> StaticType for Vec<T>
194where
195    T: StaticType,
196{
197    fn static_type() -> SimpleType {
198        SimpleType::List(Box::new(T::static_type()))
199    }
200}
201
202impl<'a, T> StaticType for &'a T
203where
204    T: StaticType,
205{
206    fn static_type() -> SimpleType {
207        T::static_type()
208    }
209}