From e27cad9bbdd1b39d3d0d81b2e3015213f13160cb Mon Sep 17 00:00:00 2001 From: Matthew Pope Date: Tue, 27 Jun 2023 23:31:04 -0700 Subject: [PATCH] Adds write_value to ElementWriter --- src/element/writer.rs | 60 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/src/element/writer.rs b/src/element/writer.rs index 6cea9072..b994412d 100644 --- a/src/element/writer.rs +++ b/src/element/writer.rs @@ -12,10 +12,17 @@ pub use TextKind::*; /// Serializes [`Element`] instances into some kind of output sink. pub trait ElementWriter { - /// Serializes a single [`Element`] as a top-level value. + /// Serializes a single [`Element`] at the current depth of the writer. fn write_element(&mut self, element: &Element) -> IonResult<()>; - /// Serializes a collection of [`Element`] as a series of top-level values. + /// Serializes a single [`Value`] at the current depth of the writer. + // TODO: consider extracting this to a ValueWriter trait. + fn write_value(&mut self, value: &Value) -> IonResult<()>; + + /// Serializes a collection of [`Element`]. + /// + /// Most commonly used to serialize a series of top-level values, but can be used to write + /// [`Element`]s to an Ion `list` or `sexp` as well. /// /// This will return [`Err`] if writing any element causes a failure. fn write_elements<'a, I: IntoIterator>( @@ -35,8 +42,11 @@ where { fn write_element(&mut self, element: &Element) -> IonResult<()> { self.set_annotations(element.annotations()); + self.write_value(element.value()) + } - match element.value() { + fn write_value(&mut self, value: &Value) -> IonResult<()> { + match value { Value::Null(ion_type) => self.write_null(*ion_type), Value::Int(i) => self.write_int(i), Value::Float(f) => { @@ -96,11 +106,11 @@ pub enum Format { #[cfg(test)] mod tests { use crate::element::writer::ElementWriter; - use crate::element::Element; + use crate::element::{Element, List}; use crate::ion_data::IonEq; use crate::text::text_writer::TextWriterBuilder; - use crate::{IonResult, IonWriter}; + use crate::{IonResult, IonType, IonWriter}; use nom::AsBytes; #[test] @@ -109,7 +119,7 @@ mod tests { let mut writer = TextWriterBuilder::default().build(&mut buffer)?; let ion = r#" - null true 0 1e0 2.0 2022T foo "bar" (foo bar baz) [foo, bar, baz] {foo: true, bar: false} + null true 0 1e0 2.0 2022T foo "bar" (foo bar baz) [foo, bar, baz] {foo: true, bar: false} annotated::value "#; let expected_elements = Element::read_all(ion.as_bytes())?; writer.write_elements(&expected_elements)?; @@ -118,4 +128,42 @@ mod tests { assert!(expected_elements.ion_eq(&actual_elements)); Ok(()) } + + #[test] + fn write_nested_element() -> IonResult<()> { + let mut buffer = Vec::new(); + let mut writer = TextWriterBuilder::default().build(&mut buffer)?; + + let ion = r#" + null true 0 1e0 2.0 2022T foo "bar" (foo bar baz) [foo, bar, baz] {foo: true, bar: false} annotated::value + "#; + let expected_list_elements = Element::read_all(ion.as_bytes())?; + writer.step_in(IonType::List)?; + writer.write_elements(&expected_list_elements)?; + writer.step_out()?; + writer.flush()?; + // This should be an Ion List containing all of the above elements. + let actual_list = Element::read_one(writer.output().as_bytes())?; + let expected_list: Element = List::from(expected_list_elements).into(); + assert!(expected_list.ion_eq(&actual_list)); + Ok(()) + } + + #[test] + fn write_value() -> IonResult<()> { + let mut buffer = Vec::new(); + let mut writer = TextWriterBuilder::default().build(&mut buffer)?; + + let ion = r#" + null true 0 1e0 2.0 2022T foo "bar" (foo bar baz) [foo, bar, baz] {foo: true, bar: false} + "#; + let expected_elements = Element::read_all(ion.as_bytes())?; + for e in &expected_elements { + writer.write_value(e.value())?; + } + writer.flush()?; + let actual_elements = Element::read_all(writer.output().as_bytes())?; + assert!(expected_elements.ion_eq(&actual_elements)); + Ok(()) + } }