1use crate::binary_parser::IonBinaryParser;
2use crate::binary_parser_types::*;
3use crate::ion_parser_types::*;
4use crate::symbol_table::*;
5use bigdecimal::BigDecimal;
6use chrono::{naive::NaiveDate, DateTime, FixedOffset, Utc};
7use log::trace;
8use num_bigint::{BigInt, BigUint};
9use num_traits::ops::checked::CheckedSub;
10use std::convert::{TryFrom, TryInto};
11use std::{collections::HashMap, io::Read};
12
13#[derive(Debug)]
31pub struct IonParser<T: Read> {
32 parser: IonBinaryParser<T>,
33 context: SymbolContext,
34 temp_buffer: Vec<u8>,
35}
36
37pub type ConsumerResult = Result<(IonValue, usize), IonParserError>;
38
39impl<T: Read> IonParser<T> {
40 #[inline]
43 pub fn new(reader: T) -> IonParser<T> {
44 IonParser {
45 parser: IonBinaryParser::new(reader),
46 context: SymbolContext::new(),
47 temp_buffer: Vec::with_capacity(256),
48 }
49 }
50
51 #[inline]
55 pub fn with_shared_table(
56 &mut self,
57 name: String,
58 version: u32,
59 symbols: &[String],
60 ) -> Result<(), SymbolContextError> {
61 let symbols: Vec<Symbol> = symbols
62 .iter()
63 .map(|s| Symbol::Symbol(s.to_string()))
64 .collect();
65
66 self.context.add_shared_table(name, version, &symbols)
67 }
68
69 #[inline]
71 pub fn consume_all(&mut self) -> Result<Vec<IonValue>, IonParserError> {
72 let mut values = Vec::with_capacity(1);
73
74 loop {
75 match self.consume_value() {
76 Err(IonParserError::BinaryError(ParsingError::NoDataToRead)) => break,
77 Ok((value, _)) => values.push(value),
78 Err(e) => return Err(e),
79 }
80 }
81
82 Ok(values)
83 }
84
85 #[inline]
89 pub fn consume_value(&mut self) -> ConsumerResult {
90 let value_header = self.parser.consume_value_header(0)?;
91
92 let mut value = self.consume_value_body(&value_header, 0)?;
93
94 let already_consumed_value_header = 1;
95 value.1 += already_consumed_value_header;
96
97 Ok(value)
98 }
99
100 #[inline]
101 fn consume_value_body(
102 &mut self,
103 value_header: &ValueHeader,
104 nested_level: u64,
105 ) -> ConsumerResult {
106 if value_header.is_nop() {
107 let consumed_bytes = self.consume_nop(value_header)?;
108 let value = self.consume_value()?;
109 return Ok((value.0, value.1 + consumed_bytes));
110 }
111
112 match value_header.get_type() {
113 ValueType::Bool => Ok(self.consume_bool(value_header)?),
114 ValueType::Annotation => match self.consume_annotation(value_header)? {
115 (Some(annotation), consumed_bytes) => Ok((annotation, consumed_bytes)),
116 (None, consumed_bytes) => {
117 let value = self.consume_value()?;
118 Ok((value.0, value.1 + consumed_bytes))
119 }
120 },
121 ValueType::Struct => Ok(self.consume_struct(value_header, nested_level)?),
122 ValueType::List => Ok(self.consume_list(value_header, nested_level)?),
123 ValueType::Symbol => Ok(self.consume_symbol(value_header)?),
124 ValueType::PositiveInt => Ok(self.consume_int(value_header, false)?),
125 ValueType::NegativeInt => Ok(self.consume_int(value_header, true)?),
126 ValueType::String => Ok(self.consume_string(value_header)?),
127 ValueType::Timestamp => Ok(self.consume_timestamp(value_header)?),
128 ValueType::Null => Ok((IonValue::Null(NullIonValue::Null), 0)),
129 ValueType::Float => Ok(self.consume_float(value_header)?),
130 ValueType::Decimal => Ok(self.consume_decimal(value_header)?),
131 ValueType::Clob => Ok(self.consume_clob(value_header)?),
132 ValueType::Blob => Ok(self.consume_blob(value_header)?),
133 ValueType::SExpr => Ok(self.consume_sexpr(value_header, nested_level)?),
134 ValueType::Reserved => Err(IonParserError::InvalidReservedTypeDescriptor),
135 }
136 }
137
138 #[inline]
139 fn consume_nop(&mut self, header: &ValueHeader) -> Result<usize, IonParserError> {
140 trace!("Consuming Nop Padding");
141 let (length, _, total) = self.consume_value_len(header)?;
142
143 trace!("Nop Padding with length {}", length);
144
145 if length > 0 {
146 self.temp_buffer.resize(length, 0);
147 self.parser.read_bytes(&mut self.temp_buffer)?;
148 }
149
150 Ok(total)
151 }
152
153 #[inline]
154 fn consume_bool(&mut self, header: &ValueHeader) -> ConsumerResult {
155 if header.is_len_null_value() {
156 return Ok((IonValue::Null(NullIonValue::Bool), 0));
157 }
158
159 let len = header.get_len();
160
161 if len == 1 {
162 return Ok((IonValue::Bool(true), 0));
163 }
164
165 if len == 0 {
166 return Ok((IonValue::Bool(false), 0));
167 }
168
169 Err(IonParserError::InvalidBoolLength(len))
170 }
171
172 #[inline]
173 fn consume_string(&mut self, header: &ValueHeader) -> ConsumerResult {
174 trace!("Consuming String");
175
176 if self.is_value_null(header) {
177 return Ok((IonValue::Null(NullIonValue::String), 0));
178 }
179
180 if header.get_len() == 0 {
181 return Ok((IonValue::String("".into()), 0));
182 }
183
184 let (length, _, total) = self.consume_value_len(header)?;
185 let mut buffer = vec![0; length];
189 self.parser.read_bytes(&mut buffer)?;
190
191 let text = match String::from_utf8(buffer) {
192 Ok(text) => text,
193 Err(_) => return Err(IonParserError::NonUtf8String),
194 };
195
196 Ok((IonValue::String(text), total))
197 }
198
199 #[inline]
200 fn consume_int(&mut self, header: &ValueHeader, negative: bool) -> ConsumerResult {
201 trace!("Consuming Integer");
202
203 if self.is_value_null(header) {
204 return Ok((IonValue::Null(NullIonValue::Integer), 0));
205 }
206
207 if header.get_len() == 0 {
208 if negative {
209 return Err(IonParserError::InvalidNegativeInt);
210 } else {
211 return Ok((IonValue::Integer(0), 0));
212 }
213 }
214
215 let (length, _, total) = self.consume_value_len(header)?;
216 let value = self.parser.consume_uint(length)?;
217
218 if negative && value == BigUint::from(i64::MIN as u64) {
223 return Ok((IonValue::Integer(i64::MIN), total));
224 }
225
226 let value = match i64::try_from(&value) {
227 Ok(mut value) => {
228 if negative {
229 if value == 0 {
230 return Err(IonParserError::InvalidNegativeInt);
231 } else {
232 value = -value;
233 }
234 }
235
236 IonValue::Integer(value)
237 }
238 Err(_) => {
239 let mut value = BigInt::from(value);
240
241 if negative {
242 value = -value;
243 }
244
245 IonValue::BigInteger(value)
246 }
247 };
248
249 Ok((value, total))
250 }
251
252 #[inline]
253 fn consume_struct(&mut self, header: &ValueHeader, nested_level: u64) -> ConsumerResult {
254 trace!("Consuming Struct");
255
256 if self.is_value_null(header) {
257 return Ok((IonValue::Null(NullIonValue::Struct), 0));
258 }
259
260 let (length, _, total) = self.consume_value_len_for_struct(header)?;
261 let mut consumed_bytes = 0;
262 let mut values: HashMap<String, IonValue> = HashMap::new();
263
264 while length - consumed_bytes > 0 {
265 let key = self.parser.consume_varuint()?;
266 consumed_bytes += key.1;
267
268 let key = match self.context.get_symbol_by_id(
269 key.0
270 .try_into()
271 .map_err(|_| IonParserError::SymbolIdTooBig)?,
272 ) {
273 Some(Symbol::Symbol(text)) => text.clone(),
274 _ => return Err(IonParserError::SymbolNotFoundInTable),
275 };
276
277 trace!("Struct key field: {:?}", key);
278
279 let value_header = self
280 .parser
281 .consume_value_header(nested_level.saturating_add(1))?;
282
283 consumed_bytes += 1;
284
285 if value_header.is_nop() {
286 let consumed = self.consume_nop(&value_header)?;
287 trace!("Found NOP Padding in Struct of {:} bytes", consumed + 1);
288 consumed_bytes += consumed;
289 continue;
290 }
291
292 let value = self.consume_value_body(&value_header, nested_level.saturating_add(1))?;
293
294 consumed_bytes += value.1;
295
296 trace!("Struct field -> Key: {:?}, Value: {:?}", key, value.0);
297
298 values.insert(key, value.0);
299 }
300
301 if length.checked_sub(consumed_bytes).is_none() {
302 return Err(IonParserError::ListLengthWasTooShort);
303 }
304
305 trace!("End consuming struct");
306
307 Ok((IonValue::Struct(values), total))
308 }
309
310 #[inline]
311 fn consume_list(&mut self, header: &ValueHeader, nested_level: u64) -> ConsumerResult {
312 trace!("Consuming List");
313
314 if self.is_value_null(header) {
315 return Ok((IonValue::Null(NullIonValue::List), 0));
316 }
317
318 let (length, _, total) = self.consume_value_len(header)?;
319 let mut consumed_bytes = 0;
320 let mut values = vec![];
321
322 while length - consumed_bytes > 0 {
323 let value_header = self
324 .parser
325 .consume_value_header(nested_level.saturating_add(1))?;
326
327 consumed_bytes += 1;
328
329 if value_header.is_nop() {
330 let consumed = self.consume_nop(&value_header)?;
331 trace!("Found NOP Padding in List of {:} bytes", consumed + 1);
332 consumed_bytes += consumed;
333 continue;
334 }
335
336 let value = self.consume_value_body(&value_header, nested_level.saturating_add(1))?;
337
338 consumed_bytes += value.1;
339 values.push(value.0);
340
341 if consumed_bytes > length {
342 return Err(IonParserError::ListLengthWasTooShort);
343 }
344 }
345
346 trace!("End consuming list with {:}", values.len());
347
348 Ok((IonValue::List(values), total))
349 }
350
351 #[inline]
352 fn consume_sexpr(&mut self, header: &ValueHeader, nested_level: u64) -> ConsumerResult {
353 trace!("Consuming SExpr");
354
355 if self.is_value_null(header) {
356 return Ok((IonValue::Null(NullIonValue::SExpr), 0));
357 }
358
359 let list_value = self.consume_list(header, nested_level.saturating_add(1))?;
360
361 if let (IonValue::List(list), len) = list_value {
362 Ok((IonValue::SExpr(list), len))
363 } else {
364 Err(IonParserError::DidNotGetAListConsumingAListThisIsABug)
365 }
366 }
367
368 #[inline]
369 fn consume_symbol(&mut self, header: &ValueHeader) -> ConsumerResult {
370 trace!("Consuming Symbol");
371
372 if self.is_value_null(header) {
373 return Ok((IonValue::Null(NullIonValue::Symbol), 0));
374 }
375
376 let (length, _, total_consumed_bytes) = self.consume_value_len(header)?;
377
378 let symbol_id = if length == 0 {
379 BigUint::from(SystemSymbolIds::Zero as u8)
380 } else {
381 self.parser.consume_uint(length)?
382 };
383
384 let symbol = self.context.get_symbol_by_id(
385 symbol_id
386 .try_into()
387 .map_err(|_| IonParserError::SymbolIdTooBig)?,
388 );
389
390 let text = match symbol {
391 Some(Symbol::Symbol(text)) => text.clone(),
392 _ => return Err(IonParserError::SymbolNotFoundInTable),
393 };
394
395 Ok((IonValue::Symbol(text), total_consumed_bytes))
396 }
397
398 #[inline]
399 fn consume_timestamp(&mut self, header: &ValueHeader) -> ConsumerResult {
400 trace!("Consuming Timestamp");
401
402 if self.is_value_null(header) {
403 return Ok((IonValue::Null(NullIonValue::DateTime), 0));
404 }
405
406 let (length, mut consumed_bytes, _) = self.consume_value_len(header)?;
407
408 let (offset, consumed) = self.parser.consume_varint()?;
409 consumed_bytes += consumed;
410 let (year, consumed) = self.parser.consume_varuint()?;
411 consumed_bytes += consumed;
412
413 let year: i32 = year
414 .try_into()
415 .map_err(|_| IonParserError::DateValueTooBig)?;
416
417 let mut components = [1u32, 1, 0, 0, 0];
418 let mut component_counter = 0;
419
420 for component in &mut components {
421 if consumed_bytes >= length {
422 break;
423 }
424
425 let (value, consumed) = self.parser.consume_varuint()?;
426 consumed_bytes += consumed;
427 *component = value
428 .try_into()
429 .map_err(|_| IonParserError::DateValueTooBig)?;
430 component_counter += 1;
431 }
432
433 if component_counter == 3 {
434 return Err(IonParserError::DateWithHourButNoMinutes);
435 }
436
437 let [month, day, hour, minute, second] = components;
438
439 let fraction_exponent: i32 = if consumed_bytes < length {
440 let value = self.parser.consume_varint()?;
441 consumed_bytes += value.1;
442 value
443 .0
444 .try_into()
445 .map_err(|_| IonParserError::DateValueTooBig)?
446 } else {
447 0
448 };
449
450 let fraction_coefficient: i64 = if (consumed_bytes) < length {
451 let remaining_bytes = length - consumed_bytes;
452 let value = self.parser.consume_int(remaining_bytes)?;
453 consumed_bytes += remaining_bytes;
454 value
455 .try_into()
456 .map_err(|_| IonParserError::DateValueTooBig)?
457 } else {
458 0
459 };
460
461 let second_fraction: f64 =
462 ((10f64.powi(fraction_exponent)) * fraction_coefficient as f64) * 1e9;
463
464 if second_fraction < 0.0 {
465 return Err(IonParserError::DateNegativeSecondFraction);
466 }
467
468 let second_fraction =
469 u32::try_from(second_fraction as i64).map_err(|_| IonParserError::DateValueTooBig)?;
470
471 let upper_fraction_limit = 1_000_000_000;
472 if second_fraction >= upper_fraction_limit {
473 return Err(IonParserError::DateSecondFractionOverflow);
474 }
475
476 let datetime = NaiveDate::from_ymd_opt(year, month, day)
477 .ok_or(IonParserError::InvalidDate(
478 year,
479 month,
480 day,
481 hour,
482 minute,
483 second,
484 second_fraction,
485 ))?
486 .and_hms_nano_opt(hour, minute, second, second_fraction)
487 .ok_or(IonParserError::InvalidDate(
488 year,
489 month,
490 day,
491 hour,
492 minute,
493 second,
494 second_fraction,
495 ))?;
496
497 let offset: i32 = offset
498 .try_into()
499 .map_err(|_| IonParserError::DateValueTooBig)?;
500
501 let offset = FixedOffset::east_opt(offset * 60).ok_or({
502 IonParserError::InvalidDate(year, month, day, hour, minute, second, second_fraction)
503 })?;
504
505 let datetime = DateTime::<Utc>::from_utc(datetime, Utc);
506
507 let datetime = datetime.with_timezone(&offset);
508
509 Ok((IonValue::DateTime(datetime), consumed_bytes))
510 }
511
512 #[inline]
513 fn consume_float(&mut self, header: &ValueHeader) -> ConsumerResult {
514 trace!("Consuming float");
515
516 if self.is_value_null(header) {
517 return Ok((IonValue::Null(NullIonValue::Float), 0));
518 }
519
520 const FOUR_BYTES: usize = 4;
521 const EIGHT_BYTES: usize = 8;
522
523 if header.is_len_null_value() {
524 return Ok((IonValue::Null(NullIonValue::Float), 1));
525 }
526
527 if header.is_len_long_len() {
528 return Err(IonParserError::NotValidLengthFloat);
529 }
530
531 let len = header.get_len();
532
533 Ok(match len {
534 0 => (IonValue::Float(0f64), 0),
535 4 => {
536 let mut buffer = [0u8; FOUR_BYTES];
537 self.parser.read_bytes(&mut buffer)?;
538 (
539 IonValue::Float(f32::from_be_bytes(buffer).into()),
540 FOUR_BYTES,
541 )
542 }
543 8 => {
544 let mut buffer = [0u8; EIGHT_BYTES];
545 self.parser.read_bytes(&mut buffer)?;
546 (IonValue::Float(f64::from_be_bytes(buffer)), EIGHT_BYTES)
547 }
548 _ => return Err(IonParserError::NotValidLengthFloat),
549 })
550 }
551
552 #[inline]
553 fn consume_decimal(&mut self, header: &ValueHeader) -> ConsumerResult {
554 trace!("Consuming decimal");
555
556 if self.is_value_null(header) {
557 return Ok((IonValue::Null(NullIonValue::Decimal), 0));
558 }
559
560 if header.get_len() == 0 {
561 return Ok((IonValue::Decimal(BigDecimal::from(0u8)), 0));
562 }
563
564 let (length, _, total) = self.consume_value_len(header)?;
565
566 let (exponent, consumed_bytes) = self.parser.consume_varint()?;
567 let coefficient_size = length
568 .checked_sub(consumed_bytes)
569 .ok_or(IonParserError::DecimalExponentTooBig)?;
570
571 let coefficient = if coefficient_size > 0 {
572 self.parser.consume_int(coefficient_size)?
573 } else {
574 BigInt::from(0u8)
575 };
576
577 let exponent: i64 = exponent
578 .try_into()
579 .map_err(|_| IonParserError::DecimalExponentTooBig)?;
580
581 let coefficient = BigInt::from_signed_bytes_le(&coefficient.to_signed_bytes_le());
582
583 Ok((
584 IonValue::Decimal(BigDecimal::new(coefficient, -exponent)),
585 total,
586 ))
587 }
588
589 #[inline]
590 fn consume_clob(&mut self, header: &ValueHeader) -> ConsumerResult {
591 trace!("Consuming clob");
592
593 if self.is_value_null(header) {
594 return Ok((IonValue::Null(NullIonValue::Clob), 0));
595 }
596
597 if header.get_len() == 0 {
598 return Ok((IonValue::Clob(Vec::new()), 0));
599 }
600
601 let (length, _, total) = self.consume_value_len(header)?;
602 let mut buffer = vec![0; length];
603 self.parser.read_bytes(&mut buffer)?;
604
605 Ok((IonValue::Clob(buffer), total))
606 }
607
608 #[inline]
609 fn consume_blob(&mut self, header: &ValueHeader) -> ConsumerResult {
610 trace!("Consuming blob");
611
612 if self.is_value_null(header) {
613 return Ok((IonValue::Null(NullIonValue::Blob), 0));
614 }
615
616 if header.get_len() == 0 {
617 return Ok((IonValue::Blob(Vec::new()), 0));
618 }
619
620 let (length, _, total) = self.consume_value_len(header)?;
621 let mut buffer = vec![0; length];
622 self.parser.read_bytes(&mut buffer)?;
623
624 Ok((IonValue::Blob(buffer), total))
625 }
626
627 #[inline]
628 fn consume_annotation(
629 &mut self,
630 header: &ValueHeader,
631 ) -> Result<(Option<IonValue>, usize), IonParserError> {
632 trace!("Consuming Annotation");
633
634 if self.is_value_null(header) {
635 return Err(IonParserError::NullAnnotationFound);
636 }
637
638 let (length, _, total_consumed_bytes) = self.consume_value_len(header)?;
639 let (mut remaining_annot_bytes, mut consumed_bytes) = self.parser.consume_varuint()?;
640
641 if remaining_annot_bytes == BigUint::from(0u8) {
642 return Err(IonParserError::NullAnnotationFound);
643 }
644
645 let mut symbols: Vec<usize> = Vec::new();
646
647 while remaining_annot_bytes > BigUint::from(0u8) {
648 let (annot, last_consumed_bytes) = self.parser.consume_varuint()?;
649 consumed_bytes += last_consumed_bytes;
650
651 let id_u64 = annot
652 .try_into()
653 .map_err(|_| IonParserError::SymbolIdTooBig)?;
654
655 symbols.push(id_u64);
656
657 remaining_annot_bytes = match BigUint::checked_sub(
658 &remaining_annot_bytes,
659 &BigUint::from(last_consumed_bytes),
660 ) {
661 Some(result) => result,
662 None => return Err(IonParserError::BadAnnotationLength),
663 }
664 }
665
666 trace!("Annotations found: {:?}", symbols);
667
668 let is_shared_table_declaration =
669 self.contains_system_symbol(&symbols, SystemSymbolIds::IonSharedSymbolTable);
670
671 let is_local_table_declaration =
672 self.contains_system_symbol(&symbols, SystemSymbolIds::IonSymbolTable);
673
674 let value = self.consume_value()?;
675 if let IonValue::Annotation(_, _) = value.0 {
676 return Err(IonParserError::NestedAnnotations);
677 }
678
679 consumed_bytes += value.1;
680 if consumed_bytes != length {
681 return Err(IonParserError::BadAnnotationLength);
682 }
683
684 match (is_shared_table_declaration, is_local_table_declaration) {
685 (true, true) => {
686 Err(IonParserError::SharedTableAndLocalTableDeclarationIntTheSameAnnotation)
687 }
688 (true, false) => {
689 self.load_shared_table(value.0)?;
690 Ok((None, total_consumed_bytes))
691 }
692 (false, true) => {
693 self.load_local_table(value.0)?;
694 Ok((None, total_consumed_bytes))
695 }
696 (false, false) => Ok((
697 Some(self.construct_raw_annotation(&symbols, value.0)?),
698 total_consumed_bytes,
699 )),
700 }
701 }
702
703 #[inline]
704 fn is_value_null(&self, header: &ValueHeader) -> bool {
705 header.is_len_null_value()
706 }
707
708 #[inline]
709 fn consume_value_len(
710 &mut self,
711 header: &ValueHeader,
712 ) -> Result<(usize, usize, usize), IonParserError> {
713 let mut consumed_bytes: usize = 0;
714 let null_length = 15;
715
716 let length: usize = if header.is_len_long_len() {
717 let len = self.parser.consume_varuint()?;
718 consumed_bytes += len.1;
719 usize::try_from(len.0).map_err(|_| IonParserError::ValueLenTooBig)?
720 } else if header.is_len_null_value() {
721 null_length
722 } else {
723 header.get_len().into()
724 };
725
726 let total = consumed_bytes + length;
727
728 Ok((length, consumed_bytes, total))
729 }
730
731 #[inline]
732 fn consume_value_len_for_struct(
733 &mut self,
734 header: &ValueHeader,
735 ) -> Result<(usize, usize, usize), IonParserError> {
736 let mut consumed_bytes: usize = 0;
737 let null_length = 15;
738
739 let header_len = header.get_len();
740
741 let length: usize = if header.is_len_long_len() || header_len == 1 {
742 let len = self.parser.consume_varuint()?;
743 if header_len == 1 && len.0 == BigUint::from(0u8) {
744 return Err(IonParserError::EmptyOrderedStruct);
745 }
746 consumed_bytes += len.1;
747 usize::try_from(len.0).map_err(|_| IonParserError::ValueLenTooBig)?
748 } else if header.is_len_null_value() {
749 null_length
750 } else {
751 header.get_len().into()
752 };
753
754 let total = consumed_bytes + length;
755
756 Ok((length, consumed_bytes, total))
757 }
758
759 #[inline]
760 fn get_parsed_struct_hashmap<'a>(
761 &self,
762 table: &'a IonValue,
763 ) -> Result<&'a HashMap<String, IonValue>, IonParserError> {
764 if let IonValue::Struct(table) = table {
765 Ok(table)
766 } else {
767 Err(IonParserError::LocalTableWithoutInternalStruct)
768 }
769 }
770
771 #[inline]
772 fn get_symbols_string(&self, table: &HashMap<String, IonValue>) -> Vec<Symbol> {
773 let symbols = table.get(self.get_symbol_name_by_type(SystemSymbolIds::Symbols));
774
775 if let Some(IonValue::List(symbols)) = symbols {
776 let mut symbols_string = Vec::new();
777
778 for symbol in symbols {
779 if let IonValue::String(text) = symbol {
780 symbols_string.push(Symbol::Symbol(text.clone()));
781 } else {
782 symbols_string.push(Symbol::Dummy);
783 }
784 }
785
786 symbols_string
787 } else {
788 Vec::new()
789 }
790 }
791
792 #[inline]
793 fn load_local_table(&mut self, table: IonValue) -> Result<(), IonParserError> {
794 trace!("Loading Local Table");
795
796 let table = self.get_parsed_struct_hashmap(&table)?;
797
798 let symbols = self.get_symbols_string(table);
799
800 let imports = table.get(self.get_symbol_name_by_type(SystemSymbolIds::Imports));
801
802 let imports = match imports {
803 None => Vec::new(),
804 Some(IonValue::Symbol(symbol))
805 if symbol == self.get_symbol_name_by_type(SystemSymbolIds::IonSymbolTable) =>
806 {
807 self.context.set_new_table_from_current(symbols);
808 return Ok(());
809 }
810 Some(IonValue::List(list)) => self.decode_imports(list)?,
811 _ => return Err(IonParserError::LocalSymbolTableWithoutValidImport),
812 };
813
814 self.context
815 .set_new_table(&imports, &symbols)
816 .map_err(IonParserError::ErrorAddingCreatingLocal)?;
817
818 Ok(())
819 }
820
821 #[inline]
822 fn decode_imports(&self, values: &[IonValue]) -> Result<Vec<Import>, IonParserError> {
823 let mut imports = Vec::new();
824
825 for value in values {
826 let value = match value {
827 IonValue::Struct(value) => value,
828 _ => continue,
829 };
830
831 let name = match value.get(self.get_symbol_name_by_type(SystemSymbolIds::Name)) {
832 Some(IonValue::String(name)) => name.clone(),
833 _ => continue,
834 };
835
836 let version: u32 =
837 match value.get(self.get_symbol_name_by_type(SystemSymbolIds::Version)) {
838 Some(IonValue::Integer(version)) => (*version)
839 .try_into()
840 .map_err(|_| IonParserError::TableVersionTooBig)?,
841 _ => 1,
842 };
843
844 let max_len: Option<usize> =
845 match value.get(self.get_symbol_name_by_type(SystemSymbolIds::MaxId)) {
846 Some(IonValue::Integer(version)) => Some(
847 (*version)
848 .try_into()
849 .map_err(|_| IonParserError::TableVersionTooBig)?,
850 ),
851 _ => None,
852 };
853
854 imports.push(Import {
855 name,
856 version: Some(version),
857 max_len,
858 })
859 }
860
861 Ok(imports)
862 }
863
864 #[inline]
865 fn load_shared_table(&mut self, table: IonValue) -> Result<(), IonParserError> {
866 trace!("Loading Shared Table");
867
868 let table = self.get_parsed_struct_hashmap(&table)?;
869
870 let name = table
871 .get(self.get_symbol_name_by_type(SystemSymbolIds::Name))
872 .ok_or(IonParserError::SharedTableDefinitionWithoutName)?;
873
874 let version = table.get(self.get_symbol_name_by_type(SystemSymbolIds::Version));
875
876 let version: u32 = if let Some(IonValue::Integer(version)) = version {
877 (*version)
878 .try_into()
879 .map_err(|_| IonParserError::TableVersionTooBig)?
880 } else {
881 1
882 };
883
884 let name: String = if let IonValue::String(name) = name {
885 name.clone()
886 } else {
887 return Err(IonParserError::SharedTableDefinitionWithoutName);
888 };
889
890 let symbols = self.get_symbols_string(table);
891
892 self.context
893 .add_shared_table(name, version, &symbols)
894 .map_err(IonParserError::ErrorAddingSharedTableToContext)?;
895
896 Ok(())
897 }
898
899 #[inline]
900 fn get_symbol_name_by_type(&self, symbol: SystemSymbolIds) -> &'static str {
901 SYSTEM_SYMBOL_TABLE[symbol as usize]
902 }
903
904 #[inline]
905 fn construct_raw_annotation(
906 &self,
907 symbols: &[usize],
908 value: IonValue,
909 ) -> Result<IonValue, IonParserError> {
910 let mut symbols_names = Vec::new();
911
912 for symbol in symbols.iter() {
913 let name = self.get_symbol_name(*symbol)?;
914 symbols_names.push(name);
915 }
916
917 Ok(IonValue::Annotation(symbols_names, Box::new(value)))
918 }
919
920 #[inline]
921 fn contains_system_symbol(&self, symbols: &[usize], symbol: SystemSymbolIds) -> bool {
922 symbols.iter().any(|&s| s == symbol as usize)
923 }
924
925 #[inline]
926 fn get_symbol_name(&self, symbol_id: usize) -> Result<String, IonParserError> {
927 match self.context.get_symbol_by_id(symbol_id) {
928 Some(Symbol::Symbol(name)) => Ok(name.clone()),
929 Some(Symbol::Dummy) | None => Err(IonParserError::SymbolIdNotDefined),
930 }
931 }
932}