1use crate::result::IonResult;
7
8use crate::element::{Element, Value};
9use crate::{IonType, IonWriter};
10pub use Format::*;
11pub use TextKind::*;
12
13pub trait ElementWriter {
15 fn write_element(&mut self, element: &Element) -> IonResult<()>;
17
18 fn write_elements<'a, I: IntoIterator<Item = &'a Element>>(
22 &'a mut self,
23 elements: I,
24 ) -> IonResult<()> {
25 for element in elements.into_iter() {
26 self.write_element(element)?;
27 }
28 Ok(())
29 }
30}
31
32impl<W> ElementWriter for W
33where
34 W: IonWriter,
35{
36 fn write_element(&mut self, element: &Element) -> IonResult<()> {
37 self.set_annotations(element.annotations());
38
39 match element.value() {
40 Value::Null(ion_type) => self.write_null(*ion_type),
41 Value::Int(i) => self.write_int(i),
42 Value::Float(f) => {
43 let f = *f;
44 let small_float = f as f32;
45 if (small_float as f64) == f {
46 self.write_f32(small_float)
47 } else {
48 self.write_f64(f)
49 }
50 }
51 Value::Decimal(d) => self.write_decimal(d),
52 Value::Timestamp(t) => self.write_timestamp(t),
53 Value::String(s) => self.write_string(s),
54 Value::Symbol(s) => self.write_symbol(s),
55 Value::Bool(b) => self.write_bool(*b),
56 Value::Blob(b) => self.write_blob(b),
57 Value::Clob(c) => self.write_clob(c),
58 Value::SExp(s) => {
59 self.step_in(IonType::SExp)?;
60 self.write_elements(s.elements())?;
61 self.step_out()
62 }
63 Value::List(l) => {
64 self.step_in(IonType::List)?;
65 self.write_elements(l.elements())?;
66 self.step_out()
67 }
68 Value::Struct(s) => {
69 self.step_in(IonType::Struct)?;
70 for (name, value) in s.fields() {
71 self.set_field_name(name);
72 self.write_element(value)?;
73 }
74 self.step_out()
75 }
76 }
77 }
78}
79
80#[derive(Copy, Clone, Debug, Eq, PartialEq)]
82pub enum TextKind {
83 Compact,
84 Lines,
85 Pretty,
86}
87
88#[derive(Copy, Clone, Debug, Eq, PartialEq)]
90pub enum Format {
91 Text(TextKind),
92 Binary,
93 }
95
96#[cfg(test)]
97mod tests {
98 use crate::element::writer::ElementWriter;
99 use crate::element::Element;
100 use crate::ion_data::IonEq;
101 use crate::text::text_writer::TextWriterBuilder;
102
103 use crate::{IonResult, IonWriter};
104 use nom::AsBytes;
105
106 #[test]
107 fn element_roundtrip() -> IonResult<()> {
108 let mut buffer = Vec::new();
109 let mut writer = TextWriterBuilder::default().build(&mut buffer)?;
110
111 let ion = r#"
112 null true 0 1e0 2.0 2022T foo "bar" (foo bar baz) [foo, bar, baz] {foo: true, bar: false}
113 "#;
114 let expected_elements = Element::read_all(ion.as_bytes())?;
115 writer.write_elements(&expected_elements)?;
116 writer.flush()?;
117 let actual_elements = Element::read_all(writer.output().as_bytes())?;
118 assert!(expected_elements.ion_eq(&actual_elements));
119 Ok(())
120 }
121}