From ec8d79f3db2fc3a5ab7af048209cc2cc5ab14bd3 Mon Sep 17 00:00:00 2001 From: Florian Klink Date: Thu, 23 May 2024 11:06:30 +0200 Subject: feat(tvix/eval): teach builtins.toXML context XmlEmitter gains a NixContext field, and `write_typed_value` extends it with all context elements present in the passed value. Once all serialization is done, a into_context() function returns the collected context, so we can construct a NixString with context. Tests for this live in tvix-glue, as we use builtins.derivation, which is not present in the tvix-eval crate. Fixes b/398. Change-Id: I85feaaa17b753885f8a017a54e419ec4e602af21 Reviewed-on: https://cl.tvl.fyi/c/depot/+/11704 Tested-by: BuildkiteCI Reviewed-by: flokli Autosubmit: flokli Reviewed-by: Alyssa Ross --- tvix/eval/src/builtins/to_xml.rs | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'tvix/eval/src/builtins/to_xml.rs') diff --git a/tvix/eval/src/builtins/to_xml.rs b/tvix/eval/src/builtins/to_xml.rs index 10a6d8cdb358..093e127fe25e 100644 --- a/tvix/eval/src/builtins/to_xml.rs +++ b/tvix/eval/src/builtins/to_xml.rs @@ -6,11 +6,12 @@ use bstr::ByteSlice; use std::borrow::Cow; use std::{io::Write, rc::Rc}; -use crate::{ErrorKind, Value}; +use crate::{ErrorKind, NixContext, NixContextElement, Value}; /// Recursively serialise a value to XML. The value *must* have been /// deep-forced before being passed to this function. -pub fn value_to_xml(mut writer: W, value: &Value) -> Result<(), ErrorKind> { +/// On success, returns the NixContext. +pub fn value_to_xml(mut writer: W, value: &Value) -> Result { // Write a literal document declaration, using C++-Nix-style // single quotes. writeln!(writer, "")?; @@ -21,7 +22,7 @@ pub fn value_to_xml(mut writer: W, value: &Value) -> Result<(), ErrorK value_variant_to_xml(&mut emitter, value)?; emitter.write_closing_tag("expr")?; - Ok(()) + Ok(emitter.into_context()) } fn write_typed_value( @@ -45,7 +46,12 @@ fn value_variant_to_xml(w: &mut XmlEmitter, value: &Value) -> Resul Value::Bool(b) => return write_typed_value(w, "bool", b), Value::Integer(i) => return write_typed_value(w, "int", i), Value::Float(f) => return write_typed_value(w, "float", f), - Value::String(s) => return write_typed_value(w, "string", s.to_str()?), + Value::String(s) => { + if let Some(context) = s.context() { + w.extend_context(context.iter().cloned()); + } + return write_typed_value(w, "string", s.to_str()?); + } Value::Path(p) => return write_typed_value(w, "path", p.to_string_lossy()), Value::List(list) => { @@ -137,6 +143,7 @@ struct XmlEmitter { /// The current indentation cur_indent: usize, writer: W, + context: NixContext, } impl XmlEmitter { @@ -144,6 +151,7 @@ impl XmlEmitter { XmlEmitter { cur_indent: 0, writer, + context: Default::default(), } } @@ -245,6 +253,19 @@ impl XmlEmitter { _ => None, } } + + /// Extends the existing context with more context elements. + fn extend_context(&mut self, iter: T) + where + T: IntoIterator, + { + self.context.extend(iter) + } + + /// Consumes [Self] and returns the [NixContext] collected. + fn into_context(self) -> NixContext { + self.context + } } #[cfg(test)] -- cgit 1.4.1