From 4350be34d1a826312b799f6d509aed02e363de14 Mon Sep 17 00:00:00 2001 From: Vincent Ambo Date: Sun, 1 Jan 2023 15:32:14 +0300 Subject: feat(tvix/serde): handle nested data structures Change-Id: I543fc05d31bbb9ad2edb887bce4510e9a1cdb102 Reviewed-on: https://cl.tvl.fyi/c/depot/+/7714 Tested-by: BuildkiteCI Autosubmit: tazjin Reviewed-by: flokli --- tvix/serde/src/de.rs | 67 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 55 insertions(+), 12 deletions(-) (limited to 'tvix/serde') diff --git a/tvix/serde/src/de.rs b/tvix/serde/src/de.rs index 55313fd9a7..0999e8a603 100644 --- a/tvix/serde/src/de.rs +++ b/tvix/serde/src/de.rs @@ -1,14 +1,33 @@ //! Deserialisation from Nix to Rust values. use serde::de; +use serde::de::value::{MapDeserializer, SeqDeserializer}; use tvix_eval::Value; use crate::error::Error; -struct Deserializer { +struct NixDeserializer { value: tvix_eval::Value, } +impl NixDeserializer { + fn new(value: Value) -> Self { + if let Value::Thunk(thunk) = value { + Self::new(thunk.value().clone()) + } else { + Self { value } + } + } +} + +impl de::IntoDeserializer<'_, Error> for NixDeserializer { + type Deserializer = Self; + + fn into_deserializer(self) -> Self::Deserializer { + self + } +} + pub fn from_str<'code, T>(src: &'code str) -> Result where T: serde::Deserialize<'code>, @@ -25,9 +44,7 @@ where }); } - let de = Deserializer { - value: result.value.expect("value should be present on success"), - }; + let de = NixDeserializer::new(result.value.expect("value should be present on success")); T::deserialize(de) } @@ -50,7 +67,7 @@ fn visit_integer>(v: &Value) -> Result { } } -impl<'de> de::Deserializer<'de> for Deserializer { +impl<'de> de::Deserializer<'de> for NixDeserializer { type Error = Error; fn deserialize_any(self, visitor: V) -> Result @@ -218,11 +235,17 @@ impl<'de> de::Deserializer<'de> for Deserializer { todo!("how to represent this?"); } + // Note that this can not distinguish between a serialisation of + // `Some(())` and `None`. fn deserialize_option(self, visitor: V) -> Result where V: de::Visitor<'de>, { - todo!("how to represent this?"); + if let Value::Null = self.value { + visitor.visit_none() + } else { + visitor.visit_some(self) + } } fn deserialize_unit(self, visitor: V) -> Result @@ -262,7 +285,15 @@ impl<'de> de::Deserializer<'de> for Deserializer { where V: de::Visitor<'de>, { - todo!() + if let Value::List(list) = self.value { + let mut seq = + SeqDeserializer::new(list.into_iter().map(|value| NixDeserializer::new(value))); + let result = visitor.visit_seq(&mut seq)?; + seq.end()?; + return Ok(result); + } + + Err(unexpected("list", &self.value)) } fn deserialize_tuple(self, len: usize, visitor: V) -> Result @@ -288,19 +319,31 @@ impl<'de> de::Deserializer<'de> for Deserializer { where V: de::Visitor<'de>, { - todo!() + if let Value::Attrs(attrs) = self.value { + let mut map = MapDeserializer::new(attrs.into_iter().map(|(k, v)| { + ( + NixDeserializer::new(Value::String(k)), + NixDeserializer::new(v), + ) + })); + let result = visitor.visit_map(&mut map)?; + map.end()?; + return Ok(result); + } + + Err(unexpected("map", &self.value)) } fn deserialize_struct( self, - name: &'static str, - fields: &'static [&'static str], + _name: &'static str, + _fields: &'static [&'static str], visitor: V, ) -> Result where V: de::Visitor<'de>, { - todo!() + self.deserialize_map(visitor) } fn deserialize_enum( @@ -319,7 +362,7 @@ impl<'de> de::Deserializer<'de> for Deserializer { where V: de::Visitor<'de>, { - todo!() + self.deserialize_str(visitor) } fn deserialize_ignored_any(self, visitor: V) -> Result -- cgit 1.4.1