From 805219a2fad0edac10d046fc5ad5820edb4482ee Mon Sep 17 00:00:00 2001 From: Ryan Lahfa Date: Sat, 24 Dec 2022 18:18:26 +0100 Subject: feat(tvix/eval): implement serde::Deserialize for Value Co-Authored-By: Vincent Ambo Change-Id: Ib6f7d1f4f4faac36b44f5f75cccc57bf912cf606 Reviewed-on: https://cl.tvl.fyi/c/depot/+/7626 Reviewed-by: tazjin Tested-by: BuildkiteCI --- tvix/eval/src/value/attrs.rs | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'tvix/eval/src/value/attrs.rs') diff --git a/tvix/eval/src/value/attrs.rs b/tvix/eval/src/value/attrs.rs index a41e7ce58a12..c6b274f0b70e 100644 --- a/tvix/eval/src/value/attrs.rs +++ b/tvix/eval/src/value/attrs.rs @@ -8,6 +8,8 @@ use std::iter::FromIterator; use imbl::{ordmap, OrdMap}; +use serde::de::{Deserializer, Error, Visitor}; +use serde::Deserialize; use crate::errors::ErrorKind; use crate::vm::VM; @@ -20,7 +22,7 @@ use super::Value; #[cfg(test)] mod tests; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Deserialize)] enum AttrsRep { Empty, @@ -138,6 +140,39 @@ impl TotalDisplay for NixAttrs { } } +impl<'de> Deserialize<'de> for NixAttrs { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + struct MapVisitor; + + impl<'de> Visitor<'de> for MapVisitor { + type Value = NixAttrs; + + fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_str("a valid Nix attribute set") + } + + fn visit_map(self, mut map: A) -> Result + where + A: serde::de::MapAccess<'de>, + { + let mut stack_array = Vec::with_capacity(map.size_hint().unwrap_or(0) * 2); + + while let Some((key, value)) = map.next_entry()? { + stack_array.push(key); + stack_array.push(value); + } + + NixAttrs::construct(stack_array.len() / 2, stack_array).map_err(A::Error::custom) + } + } + + deserializer.deserialize_map(MapVisitor) + } +} + #[cfg(feature = "arbitrary")] mod arbitrary { use super::*; -- cgit 1.4.1