From 283323053c098a98bcaa80d413da99d22b8e2e14 Mon Sep 17 00:00:00 2001 From: Matthew Pope Date: Tue, 6 Dec 2022 14:44:04 -0800 Subject: [PATCH] Stop impl Display for Element from panicking on typed nulls --- src/text/text_formatter.rs | 18 +++++++++--------- src/value/owned.rs | 30 +++++++++++++++--------------- tests/element_test_vectors.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/text/text_formatter.rs b/src/text/text_formatter.rs index 415d3a30..7815b8a2 100644 --- a/src/text/text_formatter.rs +++ b/src/text/text_formatter.rs @@ -405,7 +405,7 @@ impl<'a, W: std::fmt::Write> IonValueFormatter<'a, W> { } pub(crate) fn format_struct(&mut self, value: &Struct) -> IonResult<()> { - write!(self.output, "{{ ")?; + write!(self.output, "{{")?; let mut peekable_itr = value.iter().peekable(); while let Some((field_name, field_value)) = peekable_itr.next() { self.format_symbol(field_name.text().unwrap())?; @@ -414,12 +414,12 @@ impl<'a, W: std::fmt::Write> IonValueFormatter<'a, W> { write!(self.output, ", ")?; } } - write!(self.output, " }}")?; + write!(self.output, "}}")?; Ok(()) } pub(crate) fn format_sexp(&mut self, value: &Sequence) -> IonResult<()> { - write!(self.output, "( ")?; + write!(self.output, "(")?; let mut peekable_itr = value.iter().peekable(); while peekable_itr.peek().is_some() { let sexp_value = peekable_itr.next().unwrap(); @@ -428,12 +428,12 @@ impl<'a, W: std::fmt::Write> IonValueFormatter<'a, W> { write!(self.output, " ")?; } } - write!(self.output, " )")?; + write!(self.output, ")")?; Ok(()) } pub(crate) fn format_list(&mut self, value: &Sequence) -> IonResult<()> { - write!(self.output, "[ ")?; + write!(self.output, "[")?; let mut peekable_itr = value.iter().peekable(); while peekable_itr.peek().is_some() { let list_value = peekable_itr.next().unwrap(); @@ -442,7 +442,7 @@ impl<'a, W: std::fmt::Write> IonValueFormatter<'a, W> { write!(self.output, ", ")?; } } - write!(self.output, " ]")?; + write!(self.output, "]")?; Ok(()) } } @@ -555,7 +555,7 @@ mod formatter_test { vec![("greetings", Element::from(Value::String("hello".into())))].into_iter(), )) }, - "{ greetings: \"hello\" }", + "{greetings: \"hello\"}", ); Ok(()) } @@ -568,7 +568,7 @@ mod formatter_test { vec!["hello".to_owned().into(), 5.into(), true.into()].into_iter(), )) }, - "( \"hello\" 5 true )", + "(\"hello\" 5 true)", ); Ok(()) } @@ -581,7 +581,7 @@ mod formatter_test { vec!["hello".to_owned().into(), 5.into(), true.into()].into_iter(), )) }, - "[ \"hello\", 5, true ]", + "[\"hello\", 5, true]", ); Ok(()) } diff --git a/src/value/owned.rs b/src/value/owned.rs index b2cca516..dd97e057 100644 --- a/src/value/owned.rs +++ b/src/value/owned.rs @@ -440,7 +440,7 @@ pub enum Value { Struct(Struct), } -/// An owned implementation of [`Element`] +/// An owned implementation of [`IonElement`] #[derive(Debug, Clone)] pub struct Element { annotations: Vec, @@ -461,20 +461,20 @@ impl Display for Element { ivf.format_annotations(&self.annotations) .map_err(|_| std::fmt::Error)?; - match self.ion_type() { - IonType::Null => ivf.format_null(IonType::Null), - IonType::Boolean => ivf.format_bool(self.as_bool().unwrap()), - IonType::Integer => ivf.format_integer(self.as_integer().unwrap()), - IonType::Float => ivf.format_float(self.as_f64().unwrap()), - IonType::Decimal => ivf.format_decimal(self.as_decimal().unwrap()), - IonType::Timestamp => ivf.format_timestamp(self.as_timestamp().unwrap()), - IonType::Symbol => ivf.format_symbol(self.as_str().unwrap()), - IonType::String => ivf.format_string(self.as_str().unwrap()), - IonType::Clob => ivf.format_clob(self.as_bytes().unwrap()), - IonType::Blob => ivf.format_blob(self.as_bytes().unwrap()), - IonType::Struct => ivf.format_struct(self.as_struct().unwrap()), - IonType::SExpression => ivf.format_sexp(self.as_sequence().unwrap()), - IonType::List => ivf.format_list(self.as_sequence().unwrap()), + match &self.value { + Value::Null(ion_type) => ivf.format_null(*ion_type), + Value::Boolean(bool) => ivf.format_bool(*bool), + Value::Integer(integer) => ivf.format_integer(integer), + Value::Float(float) => ivf.format_float(*float), + Value::Decimal(decimal) => ivf.format_decimal(decimal), + Value::Timestamp(timestamp) => ivf.format_timestamp(timestamp), + Value::Symbol(symbol) => ivf.format_symbol(symbol), + Value::String(string) => ivf.format_string(string), + Value::Clob(clob) => ivf.format_clob(clob), + Value::Blob(blob) => ivf.format_blob(blob), + Value::Struct(struct_) => ivf.format_struct(struct_), + Value::SExpression(sexp) => ivf.format_sexp(sexp), + Value::List(list) => ivf.format_list(list), } .map_err(|_| std::fmt::Error)?; diff --git a/tests/element_test_vectors.rs b/tests/element_test_vectors.rs index ba2e7e02..db4574fc 100644 --- a/tests/element_test_vectors.rs +++ b/tests/element_test_vectors.rs @@ -459,6 +459,34 @@ fn non_equivs(_element_api: E, file_name: &str) { }); } +#[cfg(test)] +mod impl_display_for_element_tests { + use super::*; + use ion_rs::value::native_writer::NativeElementWriter; + use ion_rs::value::reader::element_reader; + use ion_rs::{IonResult, TextWriterBuilder}; + use std::fs::read; + + #[test_resources("ion-tests/iontestdata/good/**/*.ion")] + #[test_resources("ion-tests/iontestdata/good/**/*.10n")] + fn test_to_string(file_name: &str) -> IonResult<()> { + let data = read(file_name)?; + let result = element_reader().read_all(&data)?; + + for element in result { + let mut buffer = Vec::with_capacity(2048); + let mut writer = NativeElementWriter::new(TextWriterBuilder::new().build(&mut buffer)?); + writer.write(&element)?; + writer.finish()?; + + let expected_string = std::str::from_utf8(buffer.as_slice()).unwrap().to_string(); + + assert_eq!(element.to_string(), expected_string); + } + Ok(()) + } +} + #[cfg(test)] mod native_element_tests { use super::*;