#![allow(non_camel_case_types)]
use std::fmt::{Debug, Formatter};
use std::ops::Range;
use std::{fmt, mem};
use crate::binary::int::DecodedInt;
use crate::binary::uint::DecodedUInt;
use crate::lazy::binary::binary_buffer::BinaryBuffer;
use crate::lazy::binary::encoded_value::EncodedBinaryValue;
use crate::lazy::binary::raw::annotations_iterator::RawBinaryAnnotationsIterator;
use crate::lazy::binary::raw::r#struct::LazyRawBinaryStruct_1_0;
use crate::lazy::binary::raw::sequence::{
LazyRawBinaryList_1_0, LazyRawBinarySExp_1_0, LazyRawBinarySequence_1_0,
};
use crate::lazy::binary::raw::type_descriptor::Header;
use crate::lazy::decoder::{HasRange, HasSpan, LazyRawValue, RawVersionMarker};
use crate::lazy::encoding::BinaryEncoding_1_0;
use crate::lazy::expanded::EncodingContextRef;
use crate::lazy::raw_value_ref::RawValueRef;
use crate::lazy::span::Span;
use crate::lazy::str_ref::StrRef;
use crate::result::IonFailure;
use crate::types::SymbolId;
use crate::{
Decimal, Decoder, Int, IonEncoding, IonError, IonResult, IonType, RawSymbolRef, Timestamp,
};
#[derive(Debug, Copy, Clone)]
pub struct LazyRawBinaryVersionMarker_1_0<'top> {
major: u8,
minor: u8,
input: BinaryBuffer<'top>,
}
impl<'top> LazyRawBinaryVersionMarker_1_0<'top> {
pub fn new(input: BinaryBuffer<'top>, major: u8, minor: u8) -> Self {
Self {
major,
minor,
input,
}
}
}
impl<'top> HasSpan<'top> for LazyRawBinaryVersionMarker_1_0<'top> {
fn span(&self) -> Span<'top> {
Span::with_offset(self.input.offset(), self.input.bytes())
}
}
impl HasRange for LazyRawBinaryVersionMarker_1_0<'_> {
fn range(&self) -> Range<usize> {
self.input.range()
}
}
impl<'top> RawVersionMarker<'top> for LazyRawBinaryVersionMarker_1_0<'top> {
fn major_minor(&self) -> (u8, u8) {
(self.major, self.minor)
}
fn stream_encoding_before_marker(&self) -> IonEncoding {
IonEncoding::Binary_1_0
}
}
#[derive(Clone, Copy)]
pub struct LazyRawBinaryValue_1_0<'top> {
pub(crate) encoded_value: EncodedBinaryValue<Header>,
pub(crate) input: BinaryBuffer<'top>,
}
impl Debug for LazyRawBinaryValue_1_0<'_> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"LazyRawBinaryValue_1_0 {{\n val={:?},\n buf={:?}\n}}\n",
self.encoded_value, self.input
)
}
}
pub type ValueParseResult<'top, F> = IonResult<RawValueRef<'top, F>>;
impl<'top> HasSpan<'top> for &'top LazyRawBinaryValue_1_0<'top> {
fn span(&self) -> Span<'top> {
let range = self.range();
let local_range = (range.start - self.input.offset())..(range.end - self.input.offset());
Span::with_offset(range.start, &self.input.bytes()[local_range])
}
}
impl HasRange for &'_ LazyRawBinaryValue_1_0<'_> {
fn range(&self) -> Range<usize> {
self.encoded_value.annotated_value_range()
}
}
impl<'top> LazyRawValue<'top, BinaryEncoding_1_0> for &'top LazyRawBinaryValue_1_0<'top> {
fn ion_type(&self) -> IonType {
(*self).ion_type()
}
fn is_null(&self) -> bool {
(*self).is_null()
}
fn is_delimited(&self) -> bool {
false
}
fn has_annotations(&self) -> bool {
(*self).has_annotations()
}
fn annotations(&self) -> RawBinaryAnnotationsIterator<'top> {
(*self).annotations()
}
fn read(&self) -> IonResult<RawValueRef<'top, BinaryEncoding_1_0>> {
(*self).read()
}
fn annotations_span(&self) -> Span<'top> {
let Some(range) = self.encoded_value.annotations_range() else {
return Span::with_offset(self.encoded_value.header_offset, &[]);
};
let local_range = (range.start - self.input.offset())..(range.end - self.input.offset());
Span::with_offset(range.start, &self.input.bytes()[local_range])
}
fn value_span(&self) -> Span<'top> {
let range = self.encoded_value.unannotated_value_range();
let local_range = (range.start - self.input.offset())..(range.end - self.input.offset());
Span::with_offset(range.start, &self.input.bytes()[local_range])
}
fn with_backing_data(&self, span: Span<'top>) -> Self {
let buffer = BinaryBuffer::new_with_offset(self.context(), span.bytes(), span.offset());
let allocator = self.context().allocator();
allocator.alloc_with(move || LazyRawBinaryValue_1_0 {
input: buffer,
..**self
})
}
fn encoding(&self) -> IonEncoding {
IonEncoding::Binary_1_0
}
}
#[cfg_attr(not(feature = "experimental-tooling-apis"), allow(dead_code))]
pub trait BinaryValueLiteral<'top, D: Decoder>: LazyRawValue<'top, D> {
fn opcode_length(&self) -> usize;
fn length_length(&self) -> usize;
fn body_length(&self) -> usize;
fn annotations_sequence_length(&self) -> usize;
fn annotations_opcode_span(&self) -> Span<'top> {
let annotations_span = self.annotations_span();
if annotations_span.is_empty() {
return annotations_span;
}
Span::with_offset(
annotations_span.range().start,
&annotations_span.bytes()[0..1],
)
}
fn annotations_sequence_length_span(&self) -> Span<'top>;
fn annotations_wrapper_length_span(&self) -> Span<'top>;
fn annotations_header_span(&self) -> Span<'top> {
let annotations_span = self.annotations_span();
let sequence_length = self.annotations_sequence_length();
let local_end = annotations_span.len() - sequence_length;
let bytes = &annotations_span.bytes()[..local_end];
Span::with_offset(annotations_span.range().start, bytes)
}
fn annotations_sequence_span(&self) -> Span<'top> {
let annotations_span = self.annotations_span();
let sequence_length = self.annotations_sequence_length();
let local_sequence_offset = annotations_span.len() - sequence_length;
let bytes = &annotations_span.bytes()[local_sequence_offset..];
Span::with_offset(
annotations_span.range().start + local_sequence_offset,
bytes,
)
}
fn value_opcode_span(&self) -> Span<'top> {
let value_span = self.value_span();
Span::with_offset(
value_span.range().start,
&value_span.bytes()[0..self.opcode_length()],
)
}
fn value_length_span(&self) -> Span<'top> {
let value_span = self.value_span();
let value_range = value_span.range();
let opcode_length = self.opcode_length();
let length_length = self.length_length();
let length_bytes = &value_span.bytes()[opcode_length..opcode_length + length_length];
Span::with_offset(value_range.start + opcode_length, length_bytes)
}
fn value_header_span(&self) -> Span<'top> {
let value_span = self.value_span();
let opcode_length = self.opcode_length();
let length_length = self.length_length();
let header_bytes = &value_span.bytes()[..opcode_length + length_length];
Span::with_offset(value_span.range().start, header_bytes)
}
fn value_body_span(&self) -> Span<'top> {
let value_span = self.value_span();
let body_length = self.body_length();
let body_bytes = &value_span.bytes()[value_span.len() - body_length..];
Span::with_offset(value_span.range().end - body_length, body_bytes)
}
fn delimited_end_span(&self) -> Span<'top> {
let bytes = self.span().bytes();
let end = bytes.len();
let range = if !self.is_delimited() {
end..end
} else {
debug_assert!(bytes[end - 1] == 0xF0);
end - 1..end
};
let end_bytes = bytes.get(range).unwrap();
Span::with_offset(self.range().end - end_bytes.len(), end_bytes)
}
}
impl<'top> BinaryValueLiteral<'top, BinaryEncoding_1_0> for &'top LazyRawBinaryValue_1_0<'top> {
fn opcode_length(&self) -> usize {
self.encoded_value.opcode_length()
}
fn length_length(&self) -> usize {
self.encoded_value.length_length as usize
}
fn body_length(&self) -> usize {
self.encoded_value.value_body_length
}
fn annotations_sequence_length(&self) -> usize {
self.encoded_value.annotations_sequence_length()
}
fn annotations_sequence_length_span(&self) -> Span<'top> {
let header_span = self.annotations_header_span();
let wrapper_length_span = self.annotations_wrapper_length_span();
let sequence_length_offset = wrapper_length_span.range().end;
let sequence_length_bytes = &header_span.bytes()[sequence_length_offset..];
Span::with_offset(sequence_length_offset, sequence_length_bytes)
}
fn annotations_wrapper_length_span(&self) -> Span<'top> {
let annotations_span = self.annotations_span();
let wrapper_length_input = &annotations_span.bytes()[1..];
let mut num_varuint_bytes = 1;
for &byte in wrapper_length_input {
if byte >= 0b1000_0000 {
break;
}
num_varuint_bytes += 1;
}
let sequence_length_bytes = &wrapper_length_input[..num_varuint_bytes];
Span::with_offset(annotations_span.range().start + 1, sequence_length_bytes)
}
}
#[derive(Copy, Clone)]
pub struct EncodedBinaryAnnotations_1_0<'a, 'top> {
value: &'a LazyRawBinaryValue_1_0<'top>,
}
#[cfg_attr(not(feature = "experimental-tooling-apis"), allow(dead_code))]
impl<'top> EncodedBinaryAnnotations_1_0<'_, 'top> {
pub fn range(&self) -> Range<usize> {
self.value.encoded_value.annotations_range().unwrap()
}
pub fn span(&self) -> Span<'top> {
let range = self.range();
let start = range.start - self.value.input.offset();
let end = start + range.len();
let bytes = &self.value.input.bytes()[start..end];
Span::with_offset(range.start, bytes)
}
pub fn opcode_range(&self) -> Range<usize> {
let stream_start = self.range().start;
stream_start..stream_start + 1
}
pub fn opcode_span(&self) -> Span<'top> {
let stream_range = self.opcode_range();
let local_range = 0..1;
let bytes = &self.span().bytes()[local_range];
Span::with_offset(stream_range.start, bytes)
}
pub fn header_span(&self) -> Span<'top> {
let range = self.range();
let sequence_length = self.value.encoded_value.annotations_sequence_length as usize;
let local_end = range.len() - sequence_length;
let bytes = &self.span().bytes()[..local_end];
Span::with_offset(range.start, bytes)
}
pub fn sequence_span(&self) -> Span<'top> {
let range = self.range();
let sequence_length = self.value.encoded_value.annotations_sequence_length as usize;
let local_start = range.len() - sequence_length;
let bytes = &self.span().bytes()[local_start..];
let stream_start = range.start + local_start;
Span::with_offset(stream_start, bytes)
}
}
#[derive(Copy, Clone)]
pub struct EncodedBinaryValueData_1_0<'a, 'top> {
value: &'a LazyRawBinaryValue_1_0<'top>,
}
#[cfg_attr(not(feature = "experimental-tooling-apis"), allow(dead_code))]
impl<'top> EncodedBinaryValueData_1_0<'_, 'top> {
pub fn range(&self) -> Range<usize> {
let encoded = &self.value.encoded_value;
encoded.unannotated_value_range()
}
pub fn span(&self) -> Span<'top> {
let stream_range = self.range();
let offset = self.value.input.offset();
let local_range = stream_range.start - offset..stream_range.end - offset;
let bytes = &self.value.input.bytes()[local_range];
Span::with_offset(stream_range.start, bytes)
}
fn opcode_range(&self) -> Range<usize> {
let offset = self.range().start;
offset..offset + 1
}
pub fn opcode_span(&self) -> Span<'top> {
let stream_range = self.opcode_range();
let bytes = &self.span().bytes()[0..1];
Span::with_offset(stream_range.start, bytes)
}
pub fn trailing_length_range(&self) -> Range<usize> {
let range = self.range();
range.start + 1..range.start + 1 + self.value.encoded_value.length_length as usize
}
pub fn trailing_length_span(&self) -> Span<'top> {
let stream_range = self.trailing_length_range();
let offset = self.value.input.offset();
let local_range = stream_range.start - offset..stream_range.end - offset;
let bytes = &self.value.input.bytes()[local_range];
Span::with_offset(stream_range.start, bytes)
}
pub fn body_range(&self) -> Range<usize> {
let encoded = &self.value.encoded_value;
let body_offset = encoded.header_length();
let body_length = encoded.value_body_length();
let start = self.range().start + body_offset;
let end = start + body_length;
start..end
}
pub fn body_span(&self) -> Span<'top> {
let body_range = self.body_range();
let body_length = body_range.len();
let value_bytes = self.span().bytes();
let body_bytes = &value_bytes[value_bytes.len() - body_length..];
Span::with_offset(body_range.start, body_bytes)
}
}
impl<'top> LazyRawBinaryValue_1_0<'top> {
pub fn context(&self) -> EncodingContextRef<'top> {
self.input.context()
}
#[cfg(feature = "experimental-tooling-apis")]
pub fn encoded_annotations(&self) -> Option<EncodedBinaryAnnotations_1_0<'_, 'top>> {
if self.has_annotations() {
Some(EncodedBinaryAnnotations_1_0 { value: self })
} else {
None
}
}
#[cfg(feature = "experimental-tooling-apis")]
pub fn encoded_data(&self) -> EncodedBinaryValueData_1_0<'_, 'top> {
EncodedBinaryValueData_1_0 { value: self }
}
pub fn ion_type(&self) -> IonType {
self.encoded_value.ion_type()
}
pub fn is_null(&self) -> bool {
self.encoded_value.header().is_null()
}
fn has_annotations(&self) -> bool {
self.encoded_value.has_annotations()
}
fn annotations_sequence(&self) -> BinaryBuffer<'top> {
let offset_and_length = self
.encoded_value
.annotations_sequence_offset()
.map(|offset| (offset, self.encoded_value.annotations_sequence_length()));
let (sequence_offset, sequence_length) = match offset_and_length {
None => {
return self.input.slice(0, 0);
}
Some(offset_and_length) => offset_and_length,
};
let local_sequence_offset = sequence_offset - self.input.offset();
self.input.slice(local_sequence_offset, sequence_length)
}
pub fn annotations(&self) -> RawBinaryAnnotationsIterator<'top> {
RawBinaryAnnotationsIterator::new(self.annotations_sequence())
}
pub fn read(&self) -> ValueParseResult<'top, BinaryEncoding_1_0> {
if self.is_null() {
let raw_value_ref = RawValueRef::Null(self.ion_type());
return Ok(raw_value_ref);
}
match self.ion_type() {
IonType::Null => unreachable!("all null types handled above"),
IonType::Bool => self.read_bool(),
IonType::Int => self.read_int(),
IonType::Float => self.read_float(),
IonType::Decimal => self.read_decimal(),
IonType::Timestamp => self.read_timestamp(),
IonType::Symbol => self.read_symbol(),
IonType::String => self.read_string(),
IonType::Clob => self.read_clob(),
IonType::Blob => self.read_blob(),
IonType::List => self.read_list(),
IonType::SExp => self.read_sexp(),
IonType::Struct => self.read_struct(),
}
}
pub fn value_body(&self) -> &'top [u8] {
let value_total_length = self.encoded_value.total_length();
debug_assert!(self.input.len() >= value_total_length);
let value_body_length = self.encoded_value.value_body_length();
let value_offset = value_total_length - value_body_length;
self.input.bytes_range(value_offset, value_body_length)
}
pub(crate) fn available_body(&self) -> BinaryBuffer<'top> {
let value_total_length = self.encoded_value.total_length();
let value_body_length = self.encoded_value.value_body_length();
let value_offset = value_total_length - value_body_length;
let bytes_needed = std::cmp::min(self.input.len() - value_offset, value_body_length);
let buffer_slice = self.input.slice(value_offset, bytes_needed);
buffer_slice
}
fn read_bool(&self) -> ValueParseResult<'top, BinaryEncoding_1_0> {
debug_assert!(self.encoded_value.ion_type() == IonType::Bool);
let representation = self.encoded_value.header().length_code;
let value = match representation {
0 => false,
1 => true,
invalid => {
return IonResult::decoding_error(format!(
"found a boolean value with an illegal representation (must be 0 or 1): {invalid}",
))
}
};
Ok(RawValueRef::Bool(value))
}
fn read_int(&self) -> ValueParseResult<'top, BinaryEncoding_1_0> {
debug_assert!(self.encoded_value.ion_type() == IonType::Int);
let uint_bytes = self.value_body();
let magnitude: Int = DecodedUInt::uint_from_slice(uint_bytes).into();
use crate::binary::type_code::IonTypeCode::*;
let value = match (self.encoded_value.header.ion_type_code, magnitude) {
(PositiveInteger, integer) => integer,
(NegativeInteger, integer) if integer.is_zero() => {
return IonResult::decoding_error(
"found a negative integer (typecode=3) with a value of 0",
);
}
(NegativeInteger, integer) => integer.neg(),
_itc => return IonResult::decoding_error("unexpected ion type code"),
};
Ok(RawValueRef::Int(value))
}
fn read_float(&self) -> ValueParseResult<'top, BinaryEncoding_1_0> {
debug_assert!(self.encoded_value.ion_type() == IonType::Float);
let ieee_bytes = self.value_body();
let number_of_bytes = self.encoded_value.value_body_length();
let value = match number_of_bytes {
0 => 0f64,
4 => f64::from(f32::from_be_bytes(
ieee_bytes.try_into().expect("already confirmed length"),
)),
8 => f64::from_be_bytes(ieee_bytes.try_into().expect("already confirmed length")),
_ => return IonResult::decoding_error("encountered a float with an illegal length"),
};
Ok(RawValueRef::Float(value))
}
fn read_decimal(&self) -> ValueParseResult<'top, BinaryEncoding_1_0> {
debug_assert!(self.encoded_value.ion_type() == IonType::Decimal);
if self.encoded_value.value_body_length() == 0 {
return Ok(RawValueRef::Decimal(Decimal::new(0i32, 0i64)));
}
let input = BinaryBuffer::new(self.context(), self.value_body());
let (exponent_var_int, remaining) = input.read_var_int()?;
let coefficient_size_in_bytes =
self.encoded_value.value_body_length() - exponent_var_int.size_in_bytes();
let exponent = exponent_var_int.value();
let (coefficient, _remaining) = remaining.read_int(coefficient_size_in_bytes)?;
if coefficient.is_negative_zero() {
return Ok(RawValueRef::Decimal(Decimal::negative_zero_with_exponent(
exponent,
)));
}
Ok(RawValueRef::Decimal(Decimal::new(coefficient, exponent)))
}
fn read_timestamp(&self) -> ValueParseResult<'top, BinaryEncoding_1_0> {
debug_assert!(self.encoded_value.ion_type() == IonType::Timestamp);
let input = BinaryBuffer::new(self.context(), self.value_body());
let (offset, input) = input.read_var_int()?;
let is_known_offset = !offset.is_negative_zero();
let offset_minutes = offset.value() as i32;
let (year_var_uint, input) = input.read_var_uint()?;
let year = year_var_uint.value() as u32;
let builder = Timestamp::with_year(year);
if input.is_empty() {
let timestamp = builder.build()?;
return Ok(RawValueRef::Timestamp(timestamp));
}
let (month_var_uint, input) = input.read_var_uint()?;
let month = month_var_uint.value() as u32;
let builder = builder.with_month(month);
if input.is_empty() {
let timestamp = builder.build()?;
return Ok(RawValueRef::Timestamp(timestamp));
}
let (day_var_uint, input) = input.read_var_uint()?;
let day = day_var_uint.value() as u32;
let builder = builder.with_day(day);
if input.is_empty() {
let timestamp = builder.build()?;
return Ok(RawValueRef::Timestamp(timestamp));
}
let (hour_var_uint, input) = input.read_var_uint()?;
let hour = hour_var_uint.value() as u32;
if input.is_empty() {
return IonResult::decoding_error("timestamps with an hour must also specify a minute");
}
let (minute_var_uint, input) = input.read_var_uint()?;
let minute = minute_var_uint.value() as u32;
let builder = builder.with_hour_and_minute(hour, minute);
if input.is_empty() {
let timestamp = if is_known_offset {
builder.build_utc_fields_at_offset(offset_minutes)
} else {
builder.build()
}?;
return Ok(RawValueRef::Timestamp(timestamp));
}
let (second_var_uint, input) = input.read_var_uint()?;
let second = second_var_uint.value() as u32;
let builder = builder.with_second(second);
if input.is_empty() {
let timestamp = if is_known_offset {
builder.build_utc_fields_at_offset(offset_minutes)
} else {
builder.build()
}?;
return Ok(RawValueRef::Timestamp(timestamp));
}
let (subsecond_exponent_var_uint, input) = input.read_var_int()?;
let subsecond_exponent = subsecond_exponent_var_uint.value();
let coefficient_size_in_bytes = self.encoded_value.value_body_length() - input.offset();
let (subsecond_coefficient, _input) = if coefficient_size_in_bytes == 0 {
(DecodedInt::zero(), input)
} else {
input.read_int(coefficient_size_in_bytes)?
};
let builder = builder
.with_fractional_seconds(Decimal::new(subsecond_coefficient, subsecond_exponent));
let timestamp = if is_known_offset {
builder.build_utc_fields_at_offset(offset_minutes)
} else {
builder.build()
}?;
Ok(RawValueRef::Timestamp(timestamp))
}
fn read_symbol_id(&self) -> IonResult<SymbolId> {
debug_assert!(self.encoded_value.ion_type() == IonType::Symbol);
let uint_bytes = self.value_body();
if uint_bytes.len() > mem::size_of::<usize>() {
return IonResult::decoding_error(
"found a symbol ID that was too large to fit in a usize",
);
}
let mut buffer = [0u8; size_of::<usize>()];
buffer[size_of::<usize>() - uint_bytes.len()..].copy_from_slice(uint_bytes);
let magnitude = usize::from_be_bytes(buffer);
Ok(magnitude)
}
fn read_symbol(&self) -> ValueParseResult<'top, BinaryEncoding_1_0> {
debug_assert!(self.encoded_value.ion_type() == IonType::Symbol);
self.read_symbol_id()
.map(|sid| RawValueRef::Symbol(RawSymbolRef::SymbolId(sid)))
}
fn read_string(&self) -> ValueParseResult<'top, BinaryEncoding_1_0> {
debug_assert!(self.encoded_value.ion_type() == IonType::String);
let raw_bytes = self.value_body();
let text = std::str::from_utf8(raw_bytes)
.map_err(|_| IonError::decoding_error("found a string with invalid utf-8 data"))?;
Ok(RawValueRef::String(StrRef::from(text)))
}
fn read_blob(&self) -> ValueParseResult<'top, BinaryEncoding_1_0> {
debug_assert!(self.encoded_value.ion_type() == IonType::Blob);
let bytes = self.value_body();
Ok(RawValueRef::Blob(bytes.into()))
}
fn read_clob(&self) -> ValueParseResult<'top, BinaryEncoding_1_0> {
debug_assert!(self.encoded_value.ion_type() == IonType::Clob);
let bytes = self.value_body();
Ok(RawValueRef::Clob(bytes.into()))
}
fn read_sexp(&self) -> ValueParseResult<'top, BinaryEncoding_1_0> {
debug_assert!(self.encoded_value.ion_type() == IonType::SExp);
let lazy_value = LazyRawBinaryValue_1_0 {
encoded_value: self.encoded_value,
input: self.input,
};
let allocator = self.context().allocator();
let value_ref = allocator.alloc_with(|| lazy_value);
let lazy_sequence = LazyRawBinarySequence_1_0 { value: value_ref };
let lazy_sexp = LazyRawBinarySExp_1_0 {
sequence: lazy_sequence,
};
Ok(RawValueRef::SExp(lazy_sexp))
}
fn read_list(&self) -> ValueParseResult<'top, BinaryEncoding_1_0> {
debug_assert!(self.encoded_value.ion_type() == IonType::List);
let lazy_value = LazyRawBinaryValue_1_0 {
encoded_value: self.encoded_value,
input: self.input,
};
let allocator = self.context().allocator();
let value_ref = allocator.alloc_with(|| lazy_value);
let lazy_sequence = LazyRawBinarySequence_1_0 { value: value_ref };
let lazy_list = LazyRawBinaryList_1_0 {
sequence: lazy_sequence,
};
Ok(RawValueRef::List(lazy_list))
}
fn read_struct(&self) -> ValueParseResult<'top, BinaryEncoding_1_0> {
debug_assert!(self.encoded_value.ion_type() == IonType::Struct);
let lazy_value = LazyRawBinaryValue_1_0 {
encoded_value: self.encoded_value,
input: self.input,
};
let allocator = self.context().allocator();
let value_ref = allocator.alloc_with(|| lazy_value);
let lazy_struct = LazyRawBinaryStruct_1_0 { value: value_ref };
Ok(RawValueRef::Struct(lazy_struct))
}
}
#[cfg(test)]
mod tests {
use crate::lazy::binary::raw::reader::LazyRawBinaryReader_1_0;
use crate::lazy::binary::test_utilities::to_binary_ion;
use crate::{EncodingContext, IonResult};
#[test]
fn annotations_sequence() -> IonResult<()> {
let data = &to_binary_ion(
r#"
$ion_symbol_table::{symbols: ["foo"]}
foo // binary writer will omit the symtab if we don't use a symbol
"#,
)?;
let context = EncodingContext::empty();
let mut reader = LazyRawBinaryReader_1_0::new(context.get_ref(), data);
let _ivm = reader.next()?.expect_ivm()?;
let value = reader.next()?.expect_value()?;
let annotations_sequence = value.annotations_sequence();
assert_eq!(annotations_sequence.len(), 1);
assert_eq!(annotations_sequence.offset(), 6);
assert_eq!(annotations_sequence.bytes()[0], 0x83u8); Ok(())
}
}