Skip to main content

snix_serde/
de.rs

1//! Deserialisation from Nix to Rust values.
2
3use bstr::ByteSlice;
4use serde::de::value::{MapDeserializer, SeqDeserializer};
5use serde::de::{self, EnumAccess, VariantAccess};
6use snix_eval::{EvalIO, EvalMode, EvaluationBuilder, Value};
7
8use crate::error::Error;
9
10struct NixDeserializer {
11    value: snix_eval::Value,
12}
13
14impl NixDeserializer {
15    fn new(value: Value) -> Self {
16        if let Value::Thunk(thunk) = value {
17            Self::new(thunk.value().clone())
18        } else {
19            Self { value }
20        }
21    }
22}
23
24impl de::IntoDeserializer<'_, Error> for NixDeserializer {
25    type Deserializer = Self;
26
27    fn into_deserializer(self) -> Self::Deserializer {
28        self
29    }
30}
31
32/// Deserialise a [`snix_eval::Value`] directly into a `T` without going
33/// through Nix evaluation. This is the inverse of [`crate::to_value`].
34pub fn from_value<T>(value: snix_eval::Value) -> Result<T, Error>
35where
36    T: serde::de::DeserializeOwned,
37{
38    T::deserialize(NixDeserializer::new(value))
39}
40
41/// Evaluate the Nix code in `src` and attempt to deserialise the
42/// value it returns to `T`.
43pub fn from_str<'code, T>(src: &'code str) -> Result<T, Error>
44where
45    T: serde::Deserialize<'code>,
46{
47    from_str_with_config(src, |b| /* no extra config */ b)
48}
49
50/// Evaluate the Nix code in `src`, with extra configuration for the
51/// `snix_eval::Evaluation` provided by the given closure.
52pub fn from_str_with_config<'code, T, F>(src: &'code str, config: F) -> Result<T, Error>
53where
54    T: serde::Deserialize<'code>,
55    F: for<'co, 'ro, 'env> FnOnce(
56        EvaluationBuilder<'co, 'ro, 'env, Box<dyn EvalIO>>,
57    ) -> EvaluationBuilder<'co, 'ro, 'env, Box<dyn EvalIO>>,
58{
59    // First step is to evaluate the Nix code ...
60    let eval = config(EvaluationBuilder::new_pure().mode(EvalMode::Strict)).build();
61    let result = eval.evaluate(src, None);
62
63    if !result.errors.is_empty() {
64        return Err(Error::NixErrors {
65            errors: result.errors,
66        });
67    }
68
69    let de = NixDeserializer::new(result.value.expect("value should be present on success"));
70
71    T::deserialize(de)
72}
73
74fn unexpected(expected: &'static str, got: &Value) -> Error {
75    Error::UnexpectedType {
76        expected,
77        got: got.type_of(),
78    }
79}
80
81fn visit_integer<I: TryFrom<i64>>(v: &Value) -> Result<I, Error> {
82    match v {
83        Value::Integer(i) => I::try_from(*i).map_err(|_| Error::IntegerConversion {
84            got: *i,
85            need: std::any::type_name::<I>(),
86        }),
87
88        _ => Err(unexpected("integer", v)),
89    }
90}
91
92impl<'de> de::Deserializer<'de> for NixDeserializer {
93    type Error = Error;
94
95    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
96    where
97        V: de::Visitor<'de>,
98    {
99        match self.value {
100            Value::Null => visitor.visit_unit(),
101            Value::Bool(b) => visitor.visit_bool(b),
102            Value::Integer(i) => visitor.visit_i64(i),
103            Value::Float(f) => visitor.visit_f64(f),
104            Value::String(s) => visitor.visit_string(s.to_string()),
105            Value::Path(p) => visitor.visit_string(p.to_string_lossy().into()), // TODO: hmm
106            Value::Attrs(_) => self.deserialize_map(visitor),
107            Value::List(_) => self.deserialize_seq(visitor),
108
109            // snix-eval types that can not be deserialized through serde.
110            Value::Closure(_)
111            | Value::Builtin(_)
112            | Value::Thunk(_)
113            | Value::AttrNotFound
114            | Value::Blueprint(_)
115            | Value::DeferredUpvalue(_)
116            | Value::UnresolvedPath(_)
117            | Value::Catchable(_)
118            | Value::FinaliseRequest(_) => Err(Error::Unserializable {
119                value_type: self.value.type_of(),
120            }),
121        }
122    }
123
124    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
125    where
126        V: de::Visitor<'de>,
127    {
128        match self.value {
129            Value::Bool(b) => visitor.visit_bool(b),
130            _ => Err(unexpected("bool", &self.value)),
131        }
132    }
133
134    fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
135    where
136        V: de::Visitor<'de>,
137    {
138        visitor.visit_i8(visit_integer(&self.value)?)
139    }
140
141    fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
142    where
143        V: de::Visitor<'de>,
144    {
145        visitor.visit_i16(visit_integer(&self.value)?)
146    }
147
148    fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
149    where
150        V: de::Visitor<'de>,
151    {
152        visitor.visit_i32(visit_integer(&self.value)?)
153    }
154
155    fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
156    where
157        V: de::Visitor<'de>,
158    {
159        visitor.visit_i64(visit_integer(&self.value)?)
160    }
161
162    fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
163    where
164        V: de::Visitor<'de>,
165    {
166        visitor.visit_u8(visit_integer(&self.value)?)
167    }
168
169    fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
170    where
171        V: de::Visitor<'de>,
172    {
173        visitor.visit_u16(visit_integer(&self.value)?)
174    }
175
176    fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
177    where
178        V: de::Visitor<'de>,
179    {
180        visitor.visit_u32(visit_integer(&self.value)?)
181    }
182
183    fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
184    where
185        V: de::Visitor<'de>,
186    {
187        visitor.visit_u64(visit_integer(&self.value)?)
188    }
189
190    fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
191    where
192        V: de::Visitor<'de>,
193    {
194        if let Value::Float(f) = self.value {
195            return visitor.visit_f32(f as f32);
196        }
197
198        Err(unexpected("float", &self.value))
199    }
200
201    fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
202    where
203        V: de::Visitor<'de>,
204    {
205        if let Value::Float(f) = self.value {
206            return visitor.visit_f64(f);
207        }
208
209        Err(unexpected("float", &self.value))
210    }
211
212    fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
213    where
214        V: de::Visitor<'de>,
215    {
216        if let Value::String(s) = &self.value {
217            let chars = s.chars().collect::<Vec<_>>();
218            if chars.len() == 1 {
219                return visitor.visit_char(chars[0]);
220            }
221        }
222
223        Err(unexpected("char", &self.value))
224    }
225
226    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
227    where
228        V: de::Visitor<'de>,
229    {
230        if let Value::String(s) = &self.value
231            && let Ok(s) = s.to_str()
232        {
233            return visitor.visit_str(s);
234        }
235
236        Err(unexpected("string", &self.value))
237    }
238
239    fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
240    where
241        V: de::Visitor<'de>,
242    {
243        if let Value::String(s) = &self.value
244            && let Ok(s) = s.to_str()
245        {
246            return visitor.visit_str(s);
247        }
248
249        Err(unexpected("string", &self.value))
250    }
251
252    fn deserialize_bytes<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
253    where
254        V: de::Visitor<'de>,
255    {
256        Err(Error::Unsupported { wanted: "bytes" })
257    }
258
259    fn deserialize_byte_buf<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
260    where
261        V: de::Visitor<'de>,
262    {
263        Err(Error::Unsupported { wanted: "byte_buf" })
264    }
265
266    // Note that this can not distinguish between a serialisation of
267    // `Some(())` and `None`.
268    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
269    where
270        V: de::Visitor<'de>,
271    {
272        if let Value::Null = self.value {
273            visitor.visit_none()
274        } else {
275            visitor.visit_some(self)
276        }
277    }
278
279    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
280    where
281        V: de::Visitor<'de>,
282    {
283        if let Value::Null = self.value {
284            return visitor.visit_unit();
285        }
286
287        Err(unexpected("null", &self.value))
288    }
289
290    fn deserialize_unit_struct<V>(
291        self,
292        _name: &'static str,
293        visitor: V,
294    ) -> Result<V::Value, Self::Error>
295    where
296        V: de::Visitor<'de>,
297    {
298        self.deserialize_unit(visitor)
299    }
300
301    fn deserialize_newtype_struct<V>(
302        self,
303        _name: &'static str,
304        visitor: V,
305    ) -> Result<V::Value, Self::Error>
306    where
307        V: de::Visitor<'de>,
308    {
309        visitor.visit_newtype_struct(self)
310    }
311
312    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
313    where
314        V: de::Visitor<'de>,
315    {
316        if let Value::List(list) = self.value {
317            let mut seq = SeqDeserializer::new(list.into_iter().map(NixDeserializer::new));
318            let result = visitor.visit_seq(&mut seq)?;
319            seq.end()?;
320            return Ok(result);
321        }
322
323        Err(unexpected("list", &self.value))
324    }
325
326    fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
327    where
328        V: de::Visitor<'de>,
329    {
330        // just represent tuples as lists ...
331        self.deserialize_seq(visitor)
332    }
333
334    fn deserialize_tuple_struct<V>(
335        self,
336        _name: &'static str,
337        _len: usize,
338        visitor: V,
339    ) -> Result<V::Value, Self::Error>
340    where
341        V: de::Visitor<'de>,
342    {
343        // same as above
344        self.deserialize_seq(visitor)
345    }
346
347    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
348    where
349        V: de::Visitor<'de>,
350    {
351        if let Value::Attrs(attrs) = self.value {
352            let mut map = MapDeserializer::new(attrs.into_iter().map(|(k, v)| {
353                (
354                    NixDeserializer::new(Value::from(k)),
355                    NixDeserializer::new(v),
356                )
357            }));
358            let result = visitor.visit_map(&mut map)?;
359            map.end()?;
360            return Ok(result);
361        }
362
363        Err(unexpected("map", &self.value))
364    }
365
366    fn deserialize_struct<V>(
367        self,
368        _name: &'static str,
369        _fields: &'static [&'static str],
370        visitor: V,
371    ) -> Result<V::Value, Self::Error>
372    where
373        V: de::Visitor<'de>,
374    {
375        self.deserialize_map(visitor)
376    }
377
378    // This method is responsible for deserializing the externally
379    // tagged enum variant serialisation.
380    fn deserialize_enum<V>(
381        self,
382        name: &'static str,
383        _variants: &'static [&'static str],
384        visitor: V,
385    ) -> Result<V::Value, Self::Error>
386    where
387        V: de::Visitor<'de>,
388    {
389        match self.value {
390            // a string represents a unit variant
391            Value::String(ref s) => {
392                if let Ok(s) = s.to_str() {
393                    visitor.visit_enum(de::value::StrDeserializer::new(s))
394                } else {
395                    Err(unexpected(name, &self.value))
396                }
397            }
398
399            // an attribute set however represents an externally
400            // tagged enum with content
401            Value::Attrs(attrs) => visitor.visit_enum(Enum(attrs)),
402
403            _ => Err(unexpected(name, &self.value)),
404        }
405    }
406
407    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
408    where
409        V: de::Visitor<'de>,
410    {
411        self.deserialize_str(visitor)
412    }
413
414    fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
415    where
416        V: de::Visitor<'de>,
417    {
418        visitor.visit_unit()
419    }
420}
421
422struct Enum(snix_eval::NixAttrs);
423
424impl<'de> EnumAccess<'de> for Enum {
425    type Error = Error;
426    type Variant = NixDeserializer;
427
428    // TODO: pass the known variants down here and check against them
429    fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
430    where
431        V: de::DeserializeSeed<'de>,
432    {
433        if self.0.len() != 1 {
434            return Err(Error::AmbiguousEnum);
435        }
436
437        let (key, value) = self.0.into_iter().next().expect("length asserted above");
438        if let Ok(k) = key.to_str() {
439            let val = seed.deserialize(de::value::StrDeserializer::<Error>::new(k))?;
440            Ok((val, NixDeserializer::new(value)))
441        } else {
442            Err(unexpected("string", &key.clone().into()))
443        }
444    }
445}
446
447impl<'de> VariantAccess<'de> for NixDeserializer {
448    type Error = Error;
449
450    fn unit_variant(self) -> Result<(), Self::Error> {
451        // If this case is hit, a user specified the name of a unit
452        // enum variant but gave it content. Unit enum deserialisation
453        // is handled in `deserialize_enum` above.
454        Err(Error::UnitEnumContent)
455    }
456
457    fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
458    where
459        T: de::DeserializeSeed<'de>,
460    {
461        seed.deserialize(self)
462    }
463
464    fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
465    where
466        V: de::Visitor<'de>,
467    {
468        de::Deserializer::deserialize_seq(self, visitor)
469    }
470
471    fn struct_variant<V>(
472        self,
473        _fields: &'static [&'static str],
474        visitor: V,
475    ) -> Result<V::Value, Self::Error>
476    where
477        V: de::Visitor<'de>,
478    {
479        de::Deserializer::deserialize_map(self, visitor)
480    }
481}