ion_rs/binary/
header.rs

1use std::convert::TryFrom;
2
3use crate::binary::constants::v1_0::length_codes;
4use crate::binary::nibbles::nibbles_from_byte;
5use crate::binary::IonTypeCode;
6use crate::result::IonResult;
7use crate::types::IonType;
8
9/// Contains all of the information that can be extracted from the one-octet type descriptor
10/// found at the beginning of each value in a binary Ion stream.
11/// For more information, consult the
12/// [Typed Value Formats](https://amazon-ion.github.io/ion-docs/docs/binary.html#typed-value-formats)
13/// section of the binary Ion spec.
14#[derive(Copy, Clone, Debug)]
15pub(crate) struct Header {
16    pub ion_type_code: IonTypeCode,
17    pub ion_type: Option<IonType>,
18    pub length_code: u8,
19}
20
21impl Header {
22    /// Attempts to parse the provided byte. If the type code is unrecognized or the
23    /// type code + length code combination is illegal, an error will be returned.
24    pub fn from_byte(byte: u8) -> IonResult<Header> {
25        let (type_code, length_code) = nibbles_from_byte(byte);
26        let ion_type_code = IonTypeCode::try_from(type_code)?;
27        let ion_type = IonType::try_from(ion_type_code).ok();
28        Ok(Header {
29            ion_type,
30            ion_type_code,
31            length_code,
32        })
33    }
34
35    pub fn is_nop(&self) -> bool {
36        self.ion_type_code == IonTypeCode::NullOrNop && self.length_code != length_codes::NULL
37    }
38}
39
40/// Parses all possible values of a single byte and stores them in a newly allocated Vec.
41/// This Vec may be used as a jump table to avoid re-calculating the meaning of the same byte
42/// value repeatedly.
43/// It is expected that the jump table will be referenced when a reader attempts to begin reading
44/// the next value from its input data. This calling code must handle the end-of-file case,
45/// IO errors, and decoding errors. Each value in the table is stored as an
46/// [`IonResult<Option<IonValueHeader>>`] so that in the even that another value is available and
47/// no IO errors occur, the value from the jump table can be returned as-is with no transformations
48/// required.
49/// All values stored in the table are either an `Err(IonError::DecodingError)` or an
50/// `Ok(Some(IonValueHeader))`.
51// TODO: Define the jump table as a static constant at compile time to avoid recalculating it.
52// https://github.com/amazon-ion/ion-rust/issues/4
53pub(crate) fn create_header_byte_jump_table() -> Vec<IonResult<Option<Header>>> {
54    let mut header_jump_table = Vec::with_capacity(256);
55    for byte_value in 0..=255 {
56        let entry = match Header::from_byte(byte_value) {
57            Ok(header) => Ok(Some(header)),
58            Err(error) => Err(error),
59        };
60        header_jump_table.push(entry);
61    }
62    header_jump_table
63}