Skip to content

Commit

Permalink
Add 1.1 binary reader support for typed nulls
Browse files Browse the repository at this point in the history
  • Loading branch information
nirosys committed May 28, 2024
1 parent cd4f20f commit 0c5f70a
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 3 deletions.
26 changes: 26 additions & 0 deletions src/lazy/binary/raw/v1_1/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -755,4 +755,30 @@ mod tests {

Ok(())
}

#[test]
fn nulls() -> IonResult<()> {
#[rustfmt::skip]
let data: Vec<([u8; 2], IonType)> = vec![
([0xEB, 0x00], IonType::Bool), // null.bool
([0xEB, 0x01], IonType::Int), // null.int
([0xEB, 0x02], IonType::Float), // null.float
([0xEB, 0x03], IonType::Decimal), // null.decimal
([0xEB, 0x04], IonType::Timestamp), // null.timestamp
([0xEB, 0x05], IonType::String), // null.string
([0xEB, 0x06], IonType::Symbol), // null.symbol
([0xEB, 0x07], IonType::Blob), // null.blob
([0xEB, 0x08], IonType::Clob), // null.clob
([0xEB, 0x09], IonType::List), // null.list
([0xEB, 0x0A], IonType::SExp), // null.sexp
([0xEB, 0x0B], IonType::Struct), // null.struct
];

for (data, expected_type) in data {
let mut reader = LazyRawBinaryReader_1_1::new(&data);
let actual_type = reader.next()?.expect_value()?.read()?.expect_null()?;
assert_eq!(actual_type, expected_type);
}
Ok(())
}
}
16 changes: 16 additions & 0 deletions src/lazy/binary/raw/v1_1/type_descriptor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,20 @@ pub struct Opcode {
/// A statically defined array of TypeDescriptor that allows a binary reader to map a given
/// byte (`u8`) to a `TypeDescriptor` without having to perform any masking or bitshift operations.
pub(crate) static ION_1_1_OPCODES: &[Opcode; 256] = &init_opcode_cache();
pub(crate) static ION_1_1_TYPED_NULL_TYPES: &[IonType; 12] = &[
IonType::Bool,
IonType::Int,
IonType::Float,
IonType::Decimal,
IonType::Timestamp,
IonType::String,
IonType::Symbol,
IonType::Blob,
IonType::Clob,
IonType::List,
IonType::SExp,
IonType::Struct,
];

static ION_1_1_TIMESTAMP_SHORT_SIZE: [u8; 13] = [1, 2, 2, 4, 5, 6, 7, 8, 5, 5, 7, 8, 9];

Expand Down Expand Up @@ -54,6 +68,7 @@ impl Opcode {
(0xE, 0x0) => (IonVersionMarker, low_nibble, None),
(0xE, 0x1..=0x3) => (SymbolAddress, low_nibble, Some(IonType::Symbol)),
(0xE, 0xA) => (NullNull, low_nibble, Some(IonType::Null)),
(0xE, 0xB) => (TypedNull, low_nibble, Some(IonType::Null)),
(0xE, 0xC..=0xD) => (Nop, low_nibble, None),
(0xF, 0x5) => (LargeInteger, low_nibble, Some(IonType::Int)),
(0xF, 0x6) => (Decimal, 0xFF, Some(IonType::Decimal)),
Expand Down Expand Up @@ -139,6 +154,7 @@ impl Header {
(OpcodeType::TimestampShort, 0..=12) => {
InOpcode(ION_1_1_TIMESTAMP_SHORT_SIZE[self.length_code as usize])
}
(OpcodeType::TypedNull, _) => InOpcode(1),
_ => FlexUIntFollows,
}
}
Expand Down
12 changes: 9 additions & 3 deletions src/lazy/binary/raw/v1_1/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ use crate::{
raw::{
v1_1::{
annotations_iterator::RawBinaryAnnotationsIterator_1_1,
immutable_buffer::ImmutableBuffer, Header, OpcodeType,
immutable_buffer::ImmutableBuffer, type_descriptor::ION_1_1_TYPED_NULL_TYPES,
Header, OpcodeType,
},
value::ValueParseResult,
},
Expand Down Expand Up @@ -169,8 +170,13 @@ impl<'top> LazyRawBinaryValue_1_1<'top> {
/// or [`LazyStruct`](crate::lazy::struct::LazyStruct) that can be traversed to access the container's contents.
pub fn read(&self) -> ValueParseResult<'top, BinaryEncoding_1_1> {
if self.is_null() {
let raw_value_ref = RawValueRef::Null(self.ion_type());
return Ok(raw_value_ref);
let ion_type = if self.encoded_value.header.ion_type_code == OpcodeType::TypedNull {
let body = self.value_body()?;
ION_1_1_TYPED_NULL_TYPES[body[0] as usize]
} else {
self.ion_type()
};
return Ok(RawValueRef::Null(ion_type));
}

match self.ion_type() {
Expand Down

0 comments on commit 0c5f70a

Please sign in to comment.