Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds write_value to ElementWriter #579

Merged
merged 1 commit into from
Jun 28, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 54 additions & 6 deletions src/element/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<()>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes me wonder if we need/want a write_values(iter) sibling method, but I'm happy to punt on that.


/// 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<Item = &'a Element>>(
Expand All @@ -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) => {
Expand Down Expand Up @@ -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]
Expand All @@ -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)?;
Expand All @@ -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(())
}
}