Skip to main content

serde_dhall/
deserialize.rs

1use std::borrow::Cow;
2use std::collections::BTreeMap;
3use std::fmt;
4
5use serde::de::value::{
6    MapAccessDeserializer, MapDeserializer, SeqDeserializer,
7};
8use serde::de::VariantAccess as _;
9
10use dhall::syntax::NumKind;
11
12use crate::value::SimpleValue;
13use crate::{Error, ErrorKind, Value};
14
15pub trait Sealed {}
16
17/// A data structure that can be deserialized from a Dhall expression.
18///
19/// This is automatically implemented for any type that [serde] can deserialize.
20/// In fact, this trait cannot be implemented manually. To implement it for your type,
21/// use serde's derive mechanism.
22///
23/// # Example
24///
25/// ```rust
26/// # fn main() -> serde_dhall::Result<()> {
27/// use serde::Deserialize;
28///
29/// // Use serde's derive
30/// #[derive(Deserialize)]
31/// struct Point {
32///     x: u64,
33///     y: u64,
34/// }
35///
36/// // Convert a Dhall string to a Point.
37/// let point: Point = serde_dhall::from_str("{ x = 1, y = 1 + 1 }").parse()?;
38/// # Ok(())
39/// # }
40/// ```
41///
42/// [serde]: https://serde.rs
43pub trait FromDhall: Sealed + Sized {
44    #[doc(hidden)]
45    fn from_dhall(v: &Value) -> crate::Result<Self>;
46}
47
48impl<T> Sealed for T where T: serde::de::DeserializeOwned {}
49
50/// Deserialize a Rust value from a Dhall [`SimpleValue`].
51///
52/// # Example
53///
54/// ```rust
55/// # fn main() -> serde_dhall::Result<()> {
56/// use std::collections::BTreeMap;
57/// use serde::Deserialize;
58///
59/// // We use serde's derive feature
60/// #[derive(Deserialize)]
61/// struct Point {
62///     x: u64,
63///     y: u64,
64/// }
65///
66/// // Some Dhall data
67/// let mut data = BTreeMap::new();
68/// data.insert(
69///     "x".to_string(),
70///     serde_dhall::SimpleValue::Num(serde_dhall::NumKind::Natural(1))
71/// );
72/// data.insert(
73///     "y".to_string(),
74///     serde_dhall::SimpleValue::Num(serde_dhall::NumKind::Natural(2))
75/// );
76/// let data = serde_dhall::SimpleValue::Record(data);
77///
78/// // Parse the Dhall value as a Point.
79/// let point: Point = serde_dhall::from_simple_value(data)?;
80///
81/// assert_eq!(point.x, 1);
82/// assert_eq!(point.y, 2);
83/// # Ok(())
84/// # }
85/// ```
86///
87pub fn from_simple_value<T>(v: SimpleValue) -> crate::Result<T>
88where
89    T: serde::de::DeserializeOwned,
90{
91    T::deserialize(Deserializer(Cow::Owned(v)))
92}
93
94impl<T> FromDhall for T
95where
96    T: serde::de::DeserializeOwned,
97{
98    fn from_dhall(v: &Value) -> crate::Result<Self> {
99        let sval = v.to_simple_value().ok_or_else(|| {
100            Error(ErrorKind::Deserialize(format!(
101                "this cannot be deserialized into the serde data model: {}",
102                v
103            )))
104        })?;
105        from_simple_value(sval)
106    }
107}
108
109struct Deserializer<'a>(Cow<'a, SimpleValue>);
110
111impl<'de: 'a, 'a> serde::de::IntoDeserializer<'de, Error> for Deserializer<'a> {
112    type Deserializer = Deserializer<'a>;
113    fn into_deserializer(self) -> Self::Deserializer {
114        self
115    }
116}
117
118impl<'de: 'a, 'a> serde::Deserializer<'de> for Deserializer<'a> {
119    type Error = Error;
120
121    fn deserialize_any<V>(self, visitor: V) -> crate::Result<V::Value>
122    where
123        V: serde::de::Visitor<'de>,
124    {
125        use NumKind::*;
126        use SimpleValue::*;
127
128        let val = |x| Deserializer(Cow::Borrowed(x));
129        match self.0.as_ref() {
130            Num(Bool(x)) => visitor.visit_bool(*x),
131            Num(Natural(x)) => visitor.visit_u64(*x),
132            Num(Integer(x)) => visitor.visit_i64(*x),
133            Num(Double(x)) => visitor.visit_f64((*x).into()),
134            Text(x) => visitor.visit_str(x),
135            List(xs) => {
136                visitor.visit_seq(SeqDeserializer::new(xs.iter().map(val)))
137            }
138            Optional(None) => visitor.visit_none(),
139            Optional(Some(x)) => visitor.visit_some(val(x)),
140            Record(m) => visitor.visit_map(MapDeserializer::new(
141                m.iter().map(|(k, v)| (k.as_str(), val(v))),
142            )),
143            Union(field_name, Some(x)) => visitor.visit_enum(
144                MapAccessDeserializer::new(MapDeserializer::new(
145                    Some((field_name.as_str(), val(x))).into_iter(),
146                )),
147            ),
148            Union(field_name, None) => visitor.visit_enum(
149                MapAccessDeserializer::new(MapDeserializer::new(
150                    Some((field_name.as_str(), ())).into_iter(),
151                )),
152            ),
153        }
154    }
155
156    fn deserialize_tuple<V>(
157        self,
158        _: usize,
159        visitor: V,
160    ) -> crate::Result<V::Value>
161    where
162        V: serde::de::Visitor<'de>,
163    {
164        let val = |x| Deserializer(Cow::Borrowed(x));
165        match self.0.as_ref() {
166            // Blindly takes keys in sorted order.
167            SimpleValue::Record(m) => visitor
168                .visit_seq(SeqDeserializer::new(m.iter().map(|(_, v)| val(v)))),
169            _ => self.deserialize_any(visitor),
170        }
171    }
172
173    fn deserialize_unit<V>(self, visitor: V) -> crate::Result<V::Value>
174    where
175        V: serde::de::Visitor<'de>,
176    {
177        match self.0.as_ref() {
178            SimpleValue::Record(m) if m.is_empty() => visitor.visit_unit(),
179            _ => self.deserialize_any(visitor),
180        }
181    }
182
183    serde::forward_to_deserialize_any! {
184        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
185        bytes byte_buf option unit_struct newtype_struct seq
186        tuple_struct map struct enum identifier ignored_any
187    }
188}
189
190struct SimpleValueVisitor;
191
192impl<'de> serde::de::Visitor<'de> for SimpleValueVisitor {
193    type Value = SimpleValue;
194
195    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
196        formatter.write_str("any valid Dhall value")
197    }
198
199    fn visit_bool<E>(self, value: bool) -> Result<SimpleValue, E> {
200        Ok(SimpleValue::Num(NumKind::Bool(value)))
201    }
202
203    fn visit_i64<E>(self, value: i64) -> Result<SimpleValue, E> {
204        Ok(SimpleValue::Num(NumKind::Integer(value)))
205    }
206
207    fn visit_u64<E>(self, value: u64) -> Result<SimpleValue, E> {
208        Ok(SimpleValue::Num(NumKind::Natural(value)))
209    }
210
211    fn visit_f64<E>(self, value: f64) -> Result<SimpleValue, E> {
212        Ok(SimpleValue::Num(NumKind::Double(value.into())))
213    }
214
215    fn visit_str<E>(self, value: &str) -> Result<SimpleValue, E> {
216        Ok(SimpleValue::Text(String::from(value)))
217    }
218
219    fn visit_string<E>(self, value: String) -> Result<SimpleValue, E> {
220        Ok(SimpleValue::Text(value))
221    }
222
223    fn visit_none<E>(self) -> Result<SimpleValue, E> {
224        Ok(SimpleValue::Optional(None))
225    }
226
227    fn visit_some<D>(self, val: D) -> Result<SimpleValue, D::Error>
228    where
229        D: serde::Deserializer<'de>,
230    {
231        let val = val.deserialize_any(SimpleValueVisitor)?;
232        Ok(SimpleValue::Optional(Some(Box::new(val))))
233    }
234
235    fn visit_enum<V>(self, visitor: V) -> Result<SimpleValue, V::Error>
236    where
237        V: serde::de::EnumAccess<'de>,
238    {
239        let (name, variant): (String, _) = visitor.variant()?;
240        // Serde does not allow me to check what kind of variant it is. This will work for dhall
241        // values, because there are only two possible kinds of cvariants, but doesn't work in
242        // general. Given that the `serde_value` crate ignores enums, I assume this is not fixable
243        // :(.
244        let val = variant.newtype_variant().ok();
245        Ok(SimpleValue::Union(name, val))
246    }
247
248    fn visit_seq<V>(self, mut visitor: V) -> Result<SimpleValue, V::Error>
249    where
250        V: serde::de::SeqAccess<'de>,
251    {
252        let mut vec = Vec::new();
253        while let Some(elem) = visitor.next_element()? {
254            vec.push(elem);
255        }
256        Ok(SimpleValue::List(vec))
257    }
258
259    fn visit_map<V>(self, mut visitor: V) -> Result<SimpleValue, V::Error>
260    where
261        V: serde::de::MapAccess<'de>,
262    {
263        let mut record = BTreeMap::default();
264        while let Some((key, value)) = visitor.next_entry()? {
265            record.insert(key, value);
266        }
267        Ok(SimpleValue::Record(record))
268    }
269}
270
271impl<'de> serde::de::Deserialize<'de> for SimpleValue {
272    fn deserialize<D>(deserializer: D) -> Result<SimpleValue, D::Error>
273    where
274        D: serde::Deserializer<'de>,
275    {
276        deserializer.deserialize_any(SimpleValueVisitor)
277    }
278}