ion_rs/binary/
binary_writer.rs1use crate::binary::raw_binary_writer::{RawBinaryWriter, RawBinaryWriterBuilder};
2use crate::constants::v1_0::system_symbol_ids;
3use crate::raw_symbol_token_ref::{AsRawSymbolTokenRef, RawSymbolTokenRef};
4use crate::result::{illegal_operation, IonResult};
5use crate::types::{Decimal, Int, IonType, SymbolId, Timestamp};
6use crate::writer::IonWriter;
7use crate::SymbolTable;
8use delegate::delegate;
9use std::io::Write;
10
11pub struct BinaryWriterBuilder {
12 }
14
15impl BinaryWriterBuilder {
16 pub fn new() -> Self {
17 BinaryWriterBuilder {}
18 }
19
20 pub fn build<W: Write>(self, sink: W) -> IonResult<BinaryWriter<W>> {
21 let mut raw_writer = RawBinaryWriterBuilder::new().build(sink)?;
22 let symbol_table_writer = RawBinaryWriterBuilder::new().build(Vec::new())?;
23 raw_writer.write_ion_version_marker(1, 0)?;
25 let binary_writer = BinaryWriter {
26 raw_writer,
27 symbol_table: Default::default(),
28 num_pending_symbols: 0,
29 symbol_table_writer,
30 };
31 Ok(binary_writer)
32 }
33}
34
35impl Default for BinaryWriterBuilder {
36 fn default() -> Self {
37 BinaryWriterBuilder::new()
38 }
39}
40
41pub struct BinaryWriter<W: Write> {
46 raw_writer: RawBinaryWriter<W>,
47 symbol_table: SymbolTable,
48 num_pending_symbols: usize,
51 symbol_table_writer: RawBinaryWriter<Vec<u8>>,
56}
57
58impl<W: Write> BinaryWriter<W> {
59 fn get_or_create_symbol_id(&mut self, text: &str) -> SymbolId {
60 if let Some(symbol_id) = self.symbol_table.sid_for(&text) {
61 symbol_id
63 } else {
64 self.num_pending_symbols += 1;
66 self.symbol_table.intern(text)
67 }
68 }
69
70 fn write_symbol_table_for_pending_symbols(&mut self) -> IonResult<()> {
71 let pending_symbols_starting_index = self.symbol_table.len() - self.num_pending_symbols;
72 let pending_symbols = self
73 .symbol_table
74 .symbols_tail(pending_symbols_starting_index);
75
76 self.symbol_table_writer
77 .add_annotation(system_symbol_ids::ION_SYMBOL_TABLE);
78 self.symbol_table_writer.step_in(IonType::Struct)?;
79
80 self.symbol_table_writer
81 .set_field_name(system_symbol_ids::IMPORTS);
82 self.symbol_table_writer
83 .write_symbol(system_symbol_ids::ION_SYMBOL_TABLE)?;
84
85 self.symbol_table_writer
86 .set_field_name(system_symbol_ids::SYMBOLS);
87 self.symbol_table_writer.step_in(IonType::List)?;
88 for symbol in pending_symbols {
89 match symbol.text() {
90 Some(text) => self.symbol_table_writer.write_string(text),
91 None => self.symbol_table_writer.write_null(IonType::Null),
92 }?;
93 }
94 self.symbol_table_writer.step_out()?; self.symbol_table_writer.step_out()?; self.symbol_table_writer.flush()?;
98
99 let bytes = &self.symbol_table_writer.output()[..];
101 self.raw_writer.output_mut().write_all(bytes)?;
102 self.symbol_table_writer.output_mut().clear();
103
104 Ok(())
105 }
106}
107
108impl<W: Write> IonWriter for BinaryWriter<W> {
109 type Output = W;
110
111 fn supports_text_symbol_tokens(&self) -> bool {
112 true
115 }
116
117 fn set_annotations<I, A>(&mut self, annotations: I)
118 where
119 A: AsRawSymbolTokenRef,
120 I: IntoIterator<Item = A>,
121 {
122 for annotation in annotations {
123 let symbol_id = match annotation.as_raw_symbol_token_ref() {
124 RawSymbolTokenRef::SymbolId(symbol_id) => {
125 if self.symbol_table.sid_is_valid(symbol_id) {
126 symbol_id
127 } else {
128 panic!("Cannot set symbol ID ${symbol_id} as annotation. It is undefined.");
129 }
130 }
131 RawSymbolTokenRef::Text(text) => self.get_or_create_symbol_id(text),
132 };
133 self.raw_writer.add_annotation(symbol_id);
134 }
135 }
136
137 fn write_symbol<A: AsRawSymbolTokenRef>(&mut self, value: A) -> IonResult<()> {
138 let symbol_id = match value.as_raw_symbol_token_ref() {
139 RawSymbolTokenRef::SymbolId(symbol_id) => {
140 if self.symbol_table.sid_is_valid(symbol_id) {
141 symbol_id
142 } else {
143 return illegal_operation(format!(
144 "Cannot write symbol ID ${symbol_id} as a symbol value. It is undefined."
145 ));
146 }
147 }
148 RawSymbolTokenRef::Text(text) => self.get_or_create_symbol_id(text),
149 };
150 self.raw_writer.write_symbol(symbol_id)
151 }
152
153 fn set_field_name<A: AsRawSymbolTokenRef>(&mut self, name: A) {
154 let text = match name.as_raw_symbol_token_ref() {
155 RawSymbolTokenRef::SymbolId(symbol_id) => {
156 if self.symbol_table.sid_is_valid(symbol_id) {
157 symbol_id
158 } else {
159 panic!("Cannot set symbol ID ${symbol_id} as field name. It is undefined.");
160 }
161 }
162 RawSymbolTokenRef::Text(text) => self.get_or_create_symbol_id(text),
163 };
164 self.raw_writer.set_field_name(text);
165 }
166
167 fn flush(&mut self) -> IonResult<()> {
168 if self.num_pending_symbols > 0 {
170 self.write_symbol_table_for_pending_symbols()?;
171 self.num_pending_symbols = 0;
172 }
173 self.raw_writer.flush()
174 }
175
176 delegate! {
177 to self.raw_writer {
178 fn ion_version(&self) -> (u8, u8);
179 fn write_ion_version_marker(&mut self, major: u8, minor: u8) -> IonResult<()>;
180 fn write_null(&mut self, ion_type: IonType) -> IonResult<()>;
181 fn write_bool(&mut self, value: bool) -> IonResult<()>;
182 fn write_i64(&mut self, value: i64) -> IonResult<()>;
183 fn write_int(&mut self, value: &Int) -> IonResult<()>;
184 fn write_f32(&mut self, value: f32) -> IonResult<()>;
185 fn write_f64(&mut self, value: f64) -> IonResult<()>;
186 fn write_decimal(&mut self, value: &Decimal) -> IonResult<()>;
187 fn write_timestamp(&mut self, value: &Timestamp) -> IonResult<()>;
188 fn write_string<A: AsRef<str>>(&mut self, value: A) -> IonResult<()>;
189 fn write_clob<A: AsRef<[u8]>>(&mut self, value: A) -> IonResult<()>;
190 fn write_blob<A: AsRef<[u8]>>(&mut self, value: A) -> IonResult<()>;
191 fn step_in(&mut self, container_type: IonType) -> IonResult<()>;
192 fn parent_type(&self) -> Option<IonType>;
193 fn depth(&self) -> usize;
194 fn step_out(&mut self) -> IonResult<()>;
195 fn output(&self) -> &Self::Output;
196 fn output_mut(&mut self) -> &mut Self::Output;
197 }
198 }
199}
200
201#[cfg(test)]
202mod tests {
203 use super::*;
204 use crate::reader::ReaderBuilder;
205 use crate::stream_reader::IonReader;
206
207 use crate::StreamItem::Value;
208
209 #[test]
210 fn intern_field_names() -> IonResult<()> {
211 let mut buffer = Vec::new();
212 let mut binary_writer = BinaryWriterBuilder::new().build(&mut buffer)?;
213 binary_writer.step_in(IonType::Struct)?;
214 binary_writer.set_field_name("foo");
215 binary_writer.write_symbol("bar")?;
216 binary_writer.step_out()?;
217 binary_writer.flush()?;
218
219 let mut reader = ReaderBuilder::new().build(buffer)?;
220 assert_eq!(Value(IonType::Struct), reader.next()?);
221 reader.step_in()?;
222 assert_eq!(Value(IonType::Symbol), reader.next()?);
223 assert_eq!("foo", reader.field_name()?);
224 assert_eq!("bar", reader.read_symbol()?.text_or_error()?);
225
226 Ok(())
227 }
228
229 #[test]
230 fn intern_annotations() -> IonResult<()> {
231 let mut buffer = Vec::new();
232 let mut binary_writer = BinaryWriterBuilder::new().build(&mut buffer)?;
233 binary_writer.set_annotations(["foo", "bar"]);
234 binary_writer.write_i64(5)?;
235 binary_writer.flush()?;
236
237 let mut reader = ReaderBuilder::new().build(buffer)?;
238 assert_eq!(Value(IonType::Int), reader.next()?);
239 let mut annotations = reader.annotations();
240 assert_eq!("foo", annotations.next().unwrap()?);
241 assert_eq!("bar", annotations.next().unwrap()?);
242
243 Ok(())
244 }
245
246 #[test]
247 fn intern_symbols() -> IonResult<()> {
248 let mut buffer = Vec::new();
249 let mut binary_writer = BinaryWriterBuilder::new().build(&mut buffer)?;
250 binary_writer.write_symbol("foo")?;
251 binary_writer.write_symbol("bar")?;
252 binary_writer.write_symbol("baz")?;
253 binary_writer.flush()?;
254
255 let mut reader = ReaderBuilder::new().build(buffer)?;
256 assert_eq!(Value(IonType::Symbol), reader.next()?);
257 assert_eq!("foo", reader.read_symbol()?);
258 assert_eq!(Value(IonType::Symbol), reader.next()?);
259 assert_eq!("bar", reader.read_symbol()?);
260 assert_eq!(Value(IonType::Symbol), reader.next()?);
261 assert_eq!("baz", reader.read_symbol()?);
262
263 Ok(())
264 }
265}