Coverage Report

Created: 2026-01-13 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/serde_dhall-0.13.0/src/deserialize.rs
Line
Count
Source
1
use std::borrow::Cow;
2
use std::collections::BTreeMap;
3
use std::fmt;
4
5
use serde::de::value::{
6
    MapAccessDeserializer, MapDeserializer, SeqDeserializer,
7
};
8
use serde::de::VariantAccess as _;
9
10
use dhall::syntax::NumKind;
11
12
use crate::value::SimpleValue;
13
use crate::{Error, ErrorKind, Value};
14
15
pub 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
43
pub trait FromDhall: Sealed + Sized {
44
    #[doc(hidden)]
45
    fn from_dhall(v: &Value) -> crate::Result<Self>;
46
}
47
48
impl<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
///
87
0
pub fn from_simple_value<T>(v: SimpleValue) -> crate::Result<T>
88
0
where
89
0
    T: serde::de::DeserializeOwned,
90
{
91
0
    T::deserialize(Deserializer(Cow::Owned(v)))
92
0
}
Unexecuted instantiation: serde_dhall::deserialize::from_simple_value::<anise::structure::location::Location>
Unexecuted instantiation: serde_dhall::deserialize::from_simple_value::<anise::almanac::metaload::metaalmanac::MetaAlmanac>
Unexecuted instantiation: serde_dhall::deserialize::from_simple_value::<anise::structure::dataset::location_dhall::LocationDhallSet>
Unexecuted instantiation: serde_dhall::deserialize::from_simple_value::<_>
93
94
impl<T> FromDhall for T
95
where
96
    T: serde::de::DeserializeOwned,
97
{
98
0
    fn from_dhall(v: &Value) -> crate::Result<Self> {
99
0
        let sval = v.to_simple_value().ok_or_else(|| {
100
0
            Error(ErrorKind::Deserialize(format!(
101
0
                "this cannot be deserialized into the serde data model: {}",
102
0
                v
103
0
            )))
104
0
        })?;
Unexecuted instantiation: <anise::structure::location::Location as serde_dhall::deserialize::FromDhall>::from_dhall::{closure#0}
Unexecuted instantiation: <anise::almanac::metaload::metaalmanac::MetaAlmanac as serde_dhall::deserialize::FromDhall>::from_dhall::{closure#0}
Unexecuted instantiation: <anise::structure::dataset::location_dhall::LocationDhallSet as serde_dhall::deserialize::FromDhall>::from_dhall::{closure#0}
Unexecuted instantiation: <_ as serde_dhall::deserialize::FromDhall>::from_dhall::{closure#0}
105
0
        from_simple_value(sval)
106
0
    }
Unexecuted instantiation: <anise::structure::location::Location as serde_dhall::deserialize::FromDhall>::from_dhall
Unexecuted instantiation: <anise::almanac::metaload::metaalmanac::MetaAlmanac as serde_dhall::deserialize::FromDhall>::from_dhall
Unexecuted instantiation: <anise::structure::dataset::location_dhall::LocationDhallSet as serde_dhall::deserialize::FromDhall>::from_dhall
Unexecuted instantiation: <_ as serde_dhall::deserialize::FromDhall>::from_dhall
107
}
108
109
struct Deserializer<'a>(Cow<'a, SimpleValue>);
110
111
impl<'de: 'a, 'a> serde::de::IntoDeserializer<'de, Error> for Deserializer<'a> {
112
    type Deserializer = Deserializer<'a>;
113
0
    fn into_deserializer(self) -> Self::Deserializer {
114
0
        self
115
0
    }
116
}
117
118
impl<'de: 'a, 'a> serde::Deserializer<'de> for Deserializer<'a> {
119
    type Error = Error;
120
121
0
    fn deserialize_any<V>(self, visitor: V) -> crate::Result<V::Value>
122
0
    where
123
0
        V: serde::de::Visitor<'de>,
124
    {
125
        use NumKind::*;
126
        use SimpleValue::*;
127
128
0
        let val = |x| Deserializer(Cow::Borrowed(x));
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<serde_core::de::impls::OptionVisitor<alloc::string::String>>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<serde_core::de::impls::OptionVisitor<i32>>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<serde_core::de::impls::OptionVisitor<u32>>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<alloc::vec::Vec<_> as serde_core::de::Deserialize>::deserialize::VecVisitor<anise::structure::location::TerrainMask>>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<alloc::vec::Vec<_> as serde_core::de::Deserialize>::deserialize::VecVisitor<anise::almanac::metaload::metafile::MetaFile>>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<alloc::vec::Vec<_> as serde_core::de::Deserialize>::deserialize::VecVisitor<anise::structure::dataset::location_dhall::LocationDhallSetEntry>>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<serde_core::de::ignored_any::IgnoredAny>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<serde_core::de::impls::BoolVisitor>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<serde_core::de::impls::StringVisitor>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::frames::frameuid::FrameUid as serde_core::de::Deserialize>::deserialize::__Visitor>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::structure::location::TerrainMask as serde_core::de::Deserialize>::deserialize::__Visitor>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::structure::location::Location as serde_core::de::Deserialize>::deserialize::__Visitor>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::almanac::metaload::metaalmanac::MetaAlmanac as serde_core::de::Deserialize>::deserialize::__Visitor>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::almanac::metaload::metafile::MetaFile as serde_core::de::Deserialize>::deserialize::__Visitor>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::structure::dataset::location_dhall::LocationDhallSet as serde_core::de::Deserialize>::deserialize::__Visitor>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::structure::dataset::location_dhall::LocationDhallSetEntry as serde_core::de::Deserialize>::deserialize::__Visitor>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<u32 as serde_core::de::Deserialize>::deserialize::PrimitiveVisitor>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<f64 as serde_core::de::Deserialize>::deserialize::PrimitiveVisitor>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<i32 as serde_core::de::Deserialize>::deserialize::PrimitiveVisitor>::{closure#0}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<_>::{closure#0}
129
0
        match self.0.as_ref() {
130
0
            Num(Bool(x)) => visitor.visit_bool(*x),
131
0
            Num(Natural(x)) => visitor.visit_u64(*x),
132
0
            Num(Integer(x)) => visitor.visit_i64(*x),
133
0
            Num(Double(x)) => visitor.visit_f64((*x).into()),
134
0
            Text(x) => visitor.visit_str(x),
135
0
            List(xs) => {
136
0
                visitor.visit_seq(SeqDeserializer::new(xs.iter().map(val)))
137
            }
138
0
            Optional(None) => visitor.visit_none(),
139
0
            Optional(Some(x)) => visitor.visit_some(val(x)),
140
0
            Record(m) => visitor.visit_map(MapDeserializer::new(
141
0
                m.iter().map(|(k, v)| (k.as_str(), val(v))),
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<serde_core::de::ignored_any::IgnoredAny>::{closure#1}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::frames::frameuid::FrameUid as serde_core::de::Deserialize>::deserialize::__Visitor>::{closure#1}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::structure::location::TerrainMask as serde_core::de::Deserialize>::deserialize::__Visitor>::{closure#1}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::structure::location::Location as serde_core::de::Deserialize>::deserialize::__Visitor>::{closure#1}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::almanac::metaload::metaalmanac::MetaAlmanac as serde_core::de::Deserialize>::deserialize::__Visitor>::{closure#1}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::almanac::metaload::metafile::MetaFile as serde_core::de::Deserialize>::deserialize::__Visitor>::{closure#1}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::structure::dataset::location_dhall::LocationDhallSet as serde_core::de::Deserialize>::deserialize::__Visitor>::{closure#1}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::structure::dataset::location_dhall::LocationDhallSetEntry as serde_core::de::Deserialize>::deserialize::__Visitor>::{closure#1}
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<_>::{closure#1}
142
            )),
143
0
            Union(field_name, Some(x)) => visitor.visit_enum(
144
0
                MapAccessDeserializer::new(MapDeserializer::new(
145
0
                    Some((field_name.as_str(), val(x))).into_iter(),
146
                )),
147
            ),
148
0
            Union(field_name, None) => visitor.visit_enum(
149
0
                MapAccessDeserializer::new(MapDeserializer::new(
150
0
                    Some((field_name.as_str(), ())).into_iter(),
151
                )),
152
            ),
153
        }
154
0
    }
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<serde_core::de::impls::OptionVisitor<alloc::string::String>>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<serde_core::de::impls::OptionVisitor<i32>>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<serde_core::de::impls::OptionVisitor<u32>>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<alloc::vec::Vec<_> as serde_core::de::Deserialize>::deserialize::VecVisitor<anise::structure::location::TerrainMask>>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<alloc::vec::Vec<_> as serde_core::de::Deserialize>::deserialize::VecVisitor<anise::almanac::metaload::metafile::MetaFile>>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<alloc::vec::Vec<_> as serde_core::de::Deserialize>::deserialize::VecVisitor<anise::structure::dataset::location_dhall::LocationDhallSetEntry>>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<serde_core::de::ignored_any::IgnoredAny>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<serde_core::de::impls::BoolVisitor>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<serde_core::de::impls::StringVisitor>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::frames::frameuid::FrameUid as serde_core::de::Deserialize>::deserialize::__Visitor>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::structure::location::TerrainMask as serde_core::de::Deserialize>::deserialize::__Visitor>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::structure::location::Location as serde_core::de::Deserialize>::deserialize::__Visitor>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::almanac::metaload::metaalmanac::MetaAlmanac as serde_core::de::Deserialize>::deserialize::__Visitor>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::almanac::metaload::metafile::MetaFile as serde_core::de::Deserialize>::deserialize::__Visitor>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::structure::dataset::location_dhall::LocationDhallSet as serde_core::de::Deserialize>::deserialize::__Visitor>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<anise::structure::dataset::location_dhall::LocationDhallSetEntry as serde_core::de::Deserialize>::deserialize::__Visitor>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<u32 as serde_core::de::Deserialize>::deserialize::PrimitiveVisitor>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<f64 as serde_core::de::Deserialize>::deserialize::PrimitiveVisitor>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<<i32 as serde_core::de::Deserialize>::deserialize::PrimitiveVisitor>
Unexecuted instantiation: <serde_dhall::deserialize::Deserializer as serde_core::de::Deserializer>::deserialize_any::<_>
155
156
0
    fn deserialize_tuple<V>(
157
0
        self,
158
0
        _: usize,
159
0
        visitor: V,
160
0
    ) -> crate::Result<V::Value>
161
0
    where
162
0
        V: serde::de::Visitor<'de>,
163
    {
164
0
        let val = |x| Deserializer(Cow::Borrowed(x));
165
0
        match self.0.as_ref() {
166
            // Blindly takes keys in sorted order.
167
0
            SimpleValue::Record(m) => visitor
168
0
                .visit_seq(SeqDeserializer::new(m.iter().map(|(_, v)| val(v)))),
169
0
            _ => self.deserialize_any(visitor),
170
        }
171
0
    }
172
173
0
    fn deserialize_unit<V>(self, visitor: V) -> crate::Result<V::Value>
174
0
    where
175
0
        V: serde::de::Visitor<'de>,
176
    {
177
0
        match self.0.as_ref() {
178
0
            SimpleValue::Record(m) if m.is_empty() => visitor.visit_unit(),
179
0
            _ => self.deserialize_any(visitor),
180
        }
181
0
    }
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
190
struct SimpleValueVisitor;
191
192
impl<'de> serde::de::Visitor<'de> for SimpleValueVisitor {
193
    type Value = SimpleValue;
194
195
0
    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
196
0
        formatter.write_str("any valid Dhall value")
197
0
    }
198
199
0
    fn visit_bool<E>(self, value: bool) -> Result<SimpleValue, E> {
200
0
        Ok(SimpleValue::Num(NumKind::Bool(value)))
201
0
    }
202
203
0
    fn visit_i64<E>(self, value: i64) -> Result<SimpleValue, E> {
204
0
        Ok(SimpleValue::Num(NumKind::Integer(value)))
205
0
    }
206
207
0
    fn visit_u64<E>(self, value: u64) -> Result<SimpleValue, E> {
208
0
        Ok(SimpleValue::Num(NumKind::Natural(value)))
209
0
    }
210
211
0
    fn visit_f64<E>(self, value: f64) -> Result<SimpleValue, E> {
212
0
        Ok(SimpleValue::Num(NumKind::Double(value.into())))
213
0
    }
214
215
0
    fn visit_str<E>(self, value: &str) -> Result<SimpleValue, E> {
216
0
        Ok(SimpleValue::Text(String::from(value)))
217
0
    }
218
219
0
    fn visit_string<E>(self, value: String) -> Result<SimpleValue, E> {
220
0
        Ok(SimpleValue::Text(value))
221
0
    }
222
223
0
    fn visit_none<E>(self) -> Result<SimpleValue, E> {
224
0
        Ok(SimpleValue::Optional(None))
225
0
    }
226
227
0
    fn visit_some<D>(self, val: D) -> Result<SimpleValue, D::Error>
228
0
    where
229
0
        D: serde::Deserializer<'de>,
230
    {
231
0
        let val = val.deserialize_any(SimpleValueVisitor)?;
232
0
        Ok(SimpleValue::Optional(Some(Box::new(val))))
233
0
    }
234
235
0
    fn visit_enum<V>(self, visitor: V) -> Result<SimpleValue, V::Error>
236
0
    where
237
0
        V: serde::de::EnumAccess<'de>,
238
    {
239
0
        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
0
        let val = variant.newtype_variant().ok();
245
0
        Ok(SimpleValue::Union(name, val))
246
0
    }
247
248
0
    fn visit_seq<V>(self, mut visitor: V) -> Result<SimpleValue, V::Error>
249
0
    where
250
0
        V: serde::de::SeqAccess<'de>,
251
    {
252
0
        let mut vec = Vec::new();
253
0
        while let Some(elem) = visitor.next_element()? {
254
0
            vec.push(elem);
255
0
        }
256
0
        Ok(SimpleValue::List(vec))
257
0
    }
258
259
0
    fn visit_map<V>(self, mut visitor: V) -> Result<SimpleValue, V::Error>
260
0
    where
261
0
        V: serde::de::MapAccess<'de>,
262
    {
263
0
        let mut record = BTreeMap::default();
264
0
        while let Some((key, value)) = visitor.next_entry()? {
265
0
            record.insert(key, value);
266
0
        }
267
0
        Ok(SimpleValue::Record(record))
268
0
    }
269
}
270
271
impl<'de> serde::de::Deserialize<'de> for SimpleValue {
272
0
    fn deserialize<D>(deserializer: D) -> Result<SimpleValue, D::Error>
273
0
    where
274
0
        D: serde::Deserializer<'de>,
275
    {
276
0
        deserializer.deserialize_any(SimpleValueVisitor)
277
0
    }
278
}