diff options
author | Vincent Ambo <mail@tazj.in> | 2023-01-01T12·32+0300 |
---|---|---|
committer | tazjin <tazjin@tvl.su> | 2023-01-03T13·37+0000 |
commit | 4350be34d1a826312b799f6d509aed02e363de14 (patch) | |
tree | 8714b5bcad14e17e8fd620470fa812c1b300391f | |
parent | 7b88e4fa9b58b7c395433ed831e4f072e1b0c6d2 (diff) |
feat(tvix/serde): handle nested data structures r/5575
Change-Id: I543fc05d31bbb9ad2edb887bce4510e9a1cdb102 Reviewed-on: https://cl.tvl.fyi/c/depot/+/7714 Tested-by: BuildkiteCI Autosubmit: tazjin <tazjin@tvl.su> Reviewed-by: flokli <flokli@flokli.de>
-rw-r--r-- | tvix/serde/src/de.rs | 67 |
1 files changed, 55 insertions, 12 deletions
diff --git a/tvix/serde/src/de.rs b/tvix/serde/src/de.rs index 55313fd9a7a2..0999e8a60368 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<T, Error> 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<I: TryFrom<i64>>(v: &Value) -> Result<I, Error> { } } -impl<'de> de::Deserializer<'de> for Deserializer { +impl<'de> de::Deserializer<'de> for NixDeserializer { type Error = Error; fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> @@ -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<V>(self, visitor: V) -> Result<V::Value, Self::Error> 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<V>(self, visitor: V) -> Result<V::Value, Self::Error> @@ -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<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error> @@ -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<V>( self, - name: &'static str, - fields: &'static [&'static str], + _name: &'static str, + _fields: &'static [&'static str], visitor: V, ) -> Result<V::Value, Self::Error> where V: de::Visitor<'de>, { - todo!() + self.deserialize_map(visitor) } fn deserialize_enum<V>( @@ -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<V>(self, visitor: V) -> Result<V::Value, Self::Error> |