ion_binary_rs/
ion_encoder.rs1use crate::binary_encoder::{
2 encode_blob, encode_bool, encode_datetime, encode_decimal, encode_float64, encode_integer,
3 encode_null, encode_uint, encode_varuint, ION_LEN_ON_HEADER_WHEN_EXTRA_LEN_FIELD_REQUIRED,
4};
5use crate::binary_parser_types::{SystemSymbolIds, SYSTEM_SYMBOL_TABLE};
6use crate::symbol_table::SymbolContext;
7use crate::IonValue;
8use num_bigint::{BigInt, BigUint};
9use std::collections::HashMap;
10use std::convert::TryFrom;
11
12#[derive(Debug)]
50pub struct IonEncoder {
51 current_buffer: Vec<IonValue>,
52 symbol_table: SymbolContext,
53}
54
55impl Default for IonEncoder {
56 fn default() -> Self {
57 Self::new()
58 }
59}
60
61impl IonEncoder {
62 pub fn new() -> IonEncoder {
63 IonEncoder {
64 current_buffer: vec![],
65 symbol_table: SymbolContext::new(),
66 }
67 }
68
69 pub fn add(&mut self, value: IonValue) {
70 self.current_buffer.push(value);
71 }
72
73 pub fn encode(&mut self) -> Vec<u8> {
74 let mut values = vec![];
75
76 values.append(&mut self.current_buffer);
77
78 let mut values_buffer: Vec<u8> = values
79 .into_iter()
80 .flat_map(|value| self.encode_value(&value))
81 .collect();
82
83 let mut symbol_table = self.encode_current_symbol_table();
84
85 let mut buffer = IonEncoder::get_ion_1_0_header();
86
87 buffer.append(&mut symbol_table);
88 buffer.append(&mut values_buffer);
89
90 buffer
91 }
92
93 fn get_ion_1_0_header() -> Vec<u8> {
94 vec![0xE0, 0x01, 0x00, 0xEA]
95 }
96
97 pub(crate) fn encode_value(&mut self, value: &IonValue) -> Vec<u8> {
98 match value {
99 IonValue::Null(value) => encode_null(value),
100 IonValue::Bool(value) => encode_bool(value),
101 IonValue::Integer(value) => encode_integer(&BigInt::from(*value)),
102 IonValue::BigInteger(value) => encode_integer(value),
103 IonValue::Float(value) => encode_float64(value),
104 IonValue::Decimal(value) => encode_decimal(value),
105 IonValue::String(value) => encode_blob(8, value.as_bytes()),
106 IonValue::Clob(value) => encode_blob(9, value),
107 IonValue::Blob(value) => encode_blob(10, value),
108 IonValue::DateTime(value) => encode_datetime(value),
109 IonValue::List(value) => self.encode_list(value, false),
110 IonValue::SExpr(value) => self.encode_list(value, true),
111 IonValue::Symbol(symbol) => self.encode_symbol(symbol),
112 IonValue::Struct(value) => self.encode_struct(value),
113 IonValue::Annotation(annotations, value) => self.encode_annotation(annotations, value),
114 }
115 }
116
117 pub(crate) fn encode_symbol(&mut self, symbol: &str) -> Vec<u8> {
118 let mut buffer: Vec<u8> = vec![];
119
120 let mut header: u8 = 0x70;
121
122 let id = self.symbol_table.insert_symbol(symbol);
123
124 let mut id_bytes = encode_uint(&BigUint::from(id));
125 let id_bytes_len = id_bytes.len();
126 let has_len_field = id_bytes_len >= ION_LEN_ON_HEADER_WHEN_EXTRA_LEN_FIELD_REQUIRED.into();
127
128 if has_len_field {
129 header += ION_LEN_ON_HEADER_WHEN_EXTRA_LEN_FIELD_REQUIRED;
130 buffer.push(header);
131 let mut id_bytes_len_bytes = encode_varuint(&id_bytes_len.to_be_bytes());
132 buffer.append(&mut id_bytes_len_bytes);
133 } else {
134 header += u8::try_from(id_bytes_len).unwrap();
135 buffer.push(header);
136 };
137
138 buffer.append(&mut id_bytes);
139
140 buffer
141 }
142
143 pub(crate) fn encode_list(&mut self, values: &[IonValue], is_sexp: bool) -> Vec<u8> {
144 let mut buffer: Vec<u8> = vec![];
145
146 for value in values {
147 let mut bytes = self.encode_value(value);
148
149 buffer.append(&mut bytes);
150 }
151
152 let buffer_len = buffer.len();
153 let has_len_field = buffer_len >= ION_LEN_ON_HEADER_WHEN_EXTRA_LEN_FIELD_REQUIRED.into();
154
155 let mut header: u8 = if is_sexp { 0xC0 } else { 0xB0 };
156
157 if has_len_field {
158 header += ION_LEN_ON_HEADER_WHEN_EXTRA_LEN_FIELD_REQUIRED;
159 } else {
160 header += u8::try_from(buffer_len).unwrap();
161 }
162
163 let mut buffer = if has_len_field {
164 let mut buffer_len_bytes = encode_varuint(&buffer_len.to_be_bytes());
165 buffer_len_bytes.append(&mut buffer);
166 buffer_len_bytes
167 } else {
168 buffer
169 };
170
171 buffer.insert(0, header);
172
173 buffer
174 }
175
176 pub(crate) fn encode_annotation(
177 &mut self,
178 annotations: &[String],
179 value: &IonValue,
180 ) -> Vec<u8> {
181 let mut annot_buffer: Vec<u8> = vec![];
182
183 for annot in annotations {
184 let annot_symbol = self.symbol_table.insert_symbol(annot);
185 let mut annot_symbol_bytes = encode_varuint(&annot_symbol.to_be_bytes());
186 annot_buffer.append(&mut annot_symbol_bytes);
187 }
188
189 let mut annot_len_bytes = encode_varuint(&annot_buffer.len().to_be_bytes());
190
191 let mut value_bytes = self.encode_value(value);
192
193 annot_len_bytes.append(&mut annot_buffer);
194
195 let mut buffer = annot_len_bytes;
196
197 buffer.append(&mut value_bytes);
198
199 let len = buffer.len();
200 let has_len_field = len >= ION_LEN_ON_HEADER_WHEN_EXTRA_LEN_FIELD_REQUIRED.into();
201
202 let mut header = 0xE0;
203
204 let mut final_buffer: Vec<u8> = vec![];
205
206 if has_len_field {
207 header += ION_LEN_ON_HEADER_WHEN_EXTRA_LEN_FIELD_REQUIRED;
208 final_buffer.push(header);
209 let mut len_bytes = encode_varuint(&len.to_be_bytes());
210 final_buffer.append(&mut len_bytes);
211 } else {
212 header += u8::try_from(len).unwrap();
213 final_buffer.push(header);
214 }
215
216 final_buffer.append(&mut buffer);
217
218 final_buffer
219 }
220
221 pub(crate) fn encode_struct(&mut self, value: &HashMap<String, IonValue>) -> Vec<u8> {
222 let mut content_buffer: Vec<u8> = vec![];
223
224 for (key, value) in value {
225 let symbol = self.symbol_table.insert_symbol(key);
226 let mut symbol_bytes = encode_varuint(&symbol.to_be_bytes());
227 let mut value_bytes = self.encode_value(value);
228 content_buffer.append(&mut symbol_bytes);
229 content_buffer.append(&mut value_bytes);
230 }
231
232 let content_len = content_buffer.len();
233 let has_len_field = content_len >= ION_LEN_ON_HEADER_WHEN_EXTRA_LEN_FIELD_REQUIRED.into();
234
235 let mut header = 0xD0;
236
237 let mut buffer: Vec<u8> = vec![];
238
239 if has_len_field {
240 header += ION_LEN_ON_HEADER_WHEN_EXTRA_LEN_FIELD_REQUIRED;
241 buffer.push(header);
242 let mut content_len_bytes = encode_varuint(&content_len.to_be_bytes());
243 buffer.append(&mut content_len_bytes);
244 } else {
245 header += u8::try_from(content_len).unwrap();
246 buffer.push(header);
247 }
248
249 buffer.append(&mut content_buffer);
250
251 buffer
252 }
253
254 pub(crate) fn encode_current_symbol_table(&mut self) -> Vec<u8> {
255 let symbols = self.symbol_table.dump_all_local_symbols();
256
257 let symbols = IonValue::List(symbols.into_iter().map(IonValue::String).collect());
258
259 let mut annotation_struct = HashMap::new();
260
261 let symbols_symbol = SYSTEM_SYMBOL_TABLE[SystemSymbolIds::Symbols as usize].to_string();
262 let local_table_annotation_symbol =
263 SYSTEM_SYMBOL_TABLE[SystemSymbolIds::IonSymbolTable as usize].to_string();
264
265 annotation_struct.insert(symbols_symbol, symbols);
266
267 let annotation_struct = IonValue::Struct(annotation_struct);
268
269 let annotation = IonValue::Annotation(
270 vec![local_table_annotation_symbol],
271 Box::new(annotation_struct),
272 );
273
274 self.encode_value(&annotation)
275 }
276}