ion_binary_rs/
ion_parser.rs

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/// In order to use it call the new method and then the "consume_all" method.
14///
15/// ### Example
16///
17/// ```rust,no_run
18///
19/// use ion_binary_rs::IonParser;
20///
21/// // This is the response from Amazon's QLDB introduction example using Rusoto
22/// let ion_test = b"\xe0\x01\0\xea\xee\xa6\x81\x83\xde\xa2\x87\xbe\x9f\x83VIN\x84Type\x84Year\x84Make\x85Model\x85Color\xde\xb9\x8a\x8e\x911C4RJFAG0FC625797\x8b\x85Sedan\x8c\"\x07\xe3\x8d\x88Mercedes\x8e\x87CLK 350\x8f\x85White";
23///
24/// let mut parser = IonParser::new(&ion_test[..]);
25///
26/// println!("Decoded Ion: {:?}", parser.consume_all().unwrap())
27/// // Decoded Ion: [Struct({"Color": String("White"), "Year": Integer(2019), "VIN": String("1C4RJFAG0FC625797"), "Make": String("Mercedes"), "Model": String("CLK 350"), "Type": String("Sedan")})]
28///
29/// ```
30#[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    /// Creates a new parser. It accepts anything that implements the trait
41    /// [Read Trait](https://doc.rust-lang.org/stable/std/io/trait.Read.html)
42    #[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    /// Allows to set up shared tables in order to define symbols that are not in the
52    /// binary blob. This is useful when decoding binaries that depend of huge tables
53    /// that are expected to exist in the client and not to be sent in the ion binary.
54    #[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    /// Consumes all the IonValues in the binary blob and returns an array with them.
70    #[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    /// Consumes **one** IonValue and stops. This function will automatically process
86    /// NOP Padding, Shared Tables and Local Tables, automatically continuing in case
87    /// that any of them are found.
88    #[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        // Not using the temp buffer because from_utf8 consumes the
186        // arguments and it would require a clone of a buffer that
187        // might be bigger than required.
188        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        // i64::MIN as u64 is not a "correct" transformation. It just binary cast
219        // the value to a u64, so the most negative number in i64 becomes a huge
220        // positive one un u64. We do this here knowingly as it is exactly what we
221        // want in order to avoid a .clone().
222        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}