Skip to content

Fix to support finding an IVM after a NOP in binary v1.0 #706

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Feb 2, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 31 additions & 2 deletions src/binary/non_blocking/raw_binary_reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1207,9 +1207,11 @@ impl<'a, A: AsRef<[u8]>> TxReader<'a, A> {
}
}

/// Looks for zero or more NOP pads followed by either:
/// Looks for zero or more NOP pads followed by any of these:
/// * an annotated value
/// * a value
/// * the end of the stream
/// * (at the top level) an Ion version marker starting a new stream
#[inline]
fn read_sequence_item(
&mut self,
Expand All @@ -1218,7 +1220,8 @@ impl<'a, A: AsRef<[u8]>> TxReader<'a, A> {
if type_descriptor.is_nop() {
if let Some(item) = self.consume_nop_padding(&mut type_descriptor)? {
// We may encounter the end of the file or container while reading NOP padding,
// in which case `item` will be RawStreamItem::Nothing.
// in which case `item` will be RawStreamItem::Nothing. At the top level, it is
// possible to encounter an IVM at the end of the NOP pad.
return Ok(item);
}
// Note that if `consume_nop_padding` reads NOP bytes but doesn't hit EOF, it will
Expand Down Expand Up @@ -1361,6 +1364,9 @@ impl<'a, A: AsRef<[u8]>> TxReader<'a, A> {
return Ok(Some(RawStreamItem::Nothing));
}
*type_descriptor = self.tx_buffer.peek_type_descriptor()?;
if type_descriptor.is_ivm_start() {
return self.read_ivm().map(Some);
}
}
Ok(None)
}
Expand Down Expand Up @@ -1947,6 +1953,29 @@ mod tests {
Ok(())
}

#[test]
fn ivm_after_nop() -> IonResult<()> {
let data = &[
0xE0, 0x01, 0x00, 0xEA, // IVM
0x00, // 1-byte NOP
0x01, 0xff, // 2-byte NOP
0xE0, 0x01, 0x00, 0xEA, // IVM
0x83, 0x66, 0x6f, 0x6f, // "foo"
0x02, 0xff, 0xff, // 3-byte NOP
]; // Empty string
let mut reader = RawBinaryReader::new(data);
let item = reader.next()?;
assert_eq!(item, RawStreamItem::VersionMarker(1, 0));
let item = reader.next()?;
assert_eq!(item, RawStreamItem::VersionMarker(1, 0));
let item = reader.next()?;
assert_eq!(item, RawStreamItem::Value(IonType::String));
assert_eq!(reader.read_str()?, "foo");
let item = reader.next()?;
assert_eq!(item, RawStreamItem::Nothing);
Ok(())
}

#[test]
fn debug() -> IonResult<()> {
let data = &[
Expand Down