diff --git a/rust/flexbuffers/Cargo.toml b/rust/flexbuffers/Cargo.toml index 3981376dd3e..30217ffe209 100644 --- a/rust/flexbuffers/Cargo.toml +++ b/rust/flexbuffers/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "flexbuffers" -version = "0.2.2" +version = "0.3.0" authors = ["Casper Neo ", "FlatBuffers Maintainers"] edition = "2018" license = "Apache-2.0" @@ -20,7 +20,6 @@ serialize_human_readable = [] # You basically never need this to be true unless reading data from old binaries. deserialize_human_readable = [] - [dependencies] serde = "1.0.119" serde_derive = "1.0.119" diff --git a/rust/flexbuffers/src/buffer.rs b/rust/flexbuffers/src/buffer.rs new file mode 100644 index 00000000000..b562249398a --- /dev/null +++ b/rust/flexbuffers/src/buffer.rs @@ -0,0 +1,81 @@ +use std::ops::{Deref, Range}; + +/// The underlying buffer that is used by a flexbuffer Reader. +/// +/// This allows for custom buffer implementations as long as they can be viewed as a &[u8]. +pub trait Buffer: Deref + Sized { + // The `BufferString` allows for a buffer to return a custom string which will have the + // lifetime of the underlying buffer. A simple `std::str::from_utf8` wouldn't work since that + // returns a &str, which is then owned by the callee (cannot be returned from a function). + // + // Example: During deserialization a `BufferString` is returned, allowing the deserializer + // to "borrow" the given str - b/c there is a "lifetime" guarantee, so to speak, from the + // underlying buffer. + /// A BufferString which will live at least as long as the Buffer itself. + /// + /// Deref's to UTF-8 `str`, and only generated from the `buffer_str` function Result. + type BufferString: Deref + Sized; + + /// This method returns an instance of type Self. This allows for lifetimes to be tracked + /// in cases of deserialization. + /// + /// It also lets custom buffers manage reference counts. + /// + /// Returns None if: + /// - range start is greater than end + /// - range end is out of bounds + /// + /// This operation should be fast -> O(1), ideally with no heap allocations. + fn slice(&self, range: Range) -> Option; + + /// Creates a shallow copy of the given buffer, similar to `slice`. + /// + /// This operation should be fast -> O(1), ideally with no heap allocations. + #[inline] + fn shallow_copy(&self) -> Self { + self.slice(0..self.len()).unwrap() + } + + /// Creates an empty instance of a `Buffer`. This is different than `Default` b/c it + /// guarantees that the buffer instance will have length zero. + /// + /// Most impls shold be able to implement this via `Default`. + fn empty() -> Self; + + /// Based off of the `empty` function, allows override for optimization purposes. + #[inline] + fn empty_str() -> Self::BufferString { + Self::empty().buffer_str().unwrap() + } + + /// Attempts to convert the given buffer to a custom string type. + /// + /// This should fail if the type does not have valid UTF-8 bytes, and must be zero copy. + fn buffer_str(&self) -> Result; +} + +impl<'de> Buffer for &'de [u8] { + type BufferString = &'de str; + + #[inline] + fn slice(&self, range: Range) -> Option { + self.get(range) + } + + #[inline] + fn empty() -> Self { + &[] + } + + /// Based off of the `empty` function, allows override for optimization purposes. + #[inline] + fn empty_str() -> Self::BufferString { + &"" + } + + #[inline] + fn buffer_str(&self) -> Result { + std::str::from_utf8(self) + } +} + diff --git a/rust/flexbuffers/src/builder/push.rs b/rust/flexbuffers/src/builder/push.rs index d22b47f1080..5cb584d6021 100644 --- a/rust/flexbuffers/src/builder/push.rs +++ b/rust/flexbuffers/src/builder/push.rs @@ -14,9 +14,9 @@ use crate::builder::Builder; use crate::private::Sealed; -use crate::{Blob, IndirectFloat, IndirectInt, IndirectUInt}; +use crate::{Blob, Buffer, IndirectFloat, IndirectInt, IndirectUInt}; -impl<'a> Sealed for Blob<'a> {} +impl Sealed for Blob {} impl Sealed for () {} // TODO: String interning @@ -44,9 +44,10 @@ impl Pushable for () { builder.push_null(); } } -impl<'a> Pushable for Blob<'a> { + +impl Pushable for Blob { fn push_to_builder(self, builder: &mut Builder) { - builder.push_blob(self.0); + builder.push_blob(&self.0); } } diff --git a/rust/flexbuffers/src/lib.rs b/rust/flexbuffers/src/lib.rs index 5e98702b9d4..614b2b36890 100644 --- a/rust/flexbuffers/src/lib.rs +++ b/rust/flexbuffers/src/lib.rs @@ -44,12 +44,15 @@ mod bitwidth; mod builder; mod flexbuffer_type; mod reader; +mod buffer; + pub use bitwidth::BitWidth; pub use builder::Error as SerializationError; pub use builder::{ singleton, Builder, BuilderOptions, FlexbufferSerializer, MapBuilder, Pushable, VectorBuilder, }; pub use flexbuffer_type::FlexBufferType; +pub use buffer::Buffer; pub use reader::Error as ReaderError; pub use reader::{DeserializationError, MapReader, Reader, ReaderIterator, VectorReader}; use serde::{Deserialize, Serialize}; @@ -64,17 +67,32 @@ pub fn to_vec(x: T) -> Result, SerializationError> { x.serialize(&mut s)?; Ok(s.take_buffer()) } + /// Deserialize a type from a flexbuffer. pub fn from_slice<'de, T: Deserialize<'de>>(buf: &'de [u8]) -> Result { let r = Reader::get_root(buf)?; T::deserialize(r) } +/// Deserialize a type from a flexbuffer. +pub fn from_buffer<'de, T: Deserialize<'de>, B: Buffer>( + buf: &'de B +) -> Result { + let r = Reader::get_root(buf as &'de [u8])?; + T::deserialize(r) +} + /// This struct, when pushed will be serialized as a `FlexBufferType::Blob`. /// /// A `Blob` is a variable width `length` followed by that many bytes of data. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub struct Blob<'a>(pub &'a [u8]); +#[derive(Debug, PartialEq, Eq)] +pub struct Blob(pub B); + +impl Clone for Blob { + fn clone(&self) -> Self { + Blob(self.0.shallow_copy()) + } +} /// This struct, when pushed, will be serialized as a `FlexBufferType::IndirectUInt`. /// diff --git a/rust/flexbuffers/src/reader/de.rs b/rust/flexbuffers/src/reader/de.rs index 8cc3b6ed4d6..ed2b8158e79 100644 --- a/rust/flexbuffers/src/reader/de.rs +++ b/rust/flexbuffers/src/reader/de.rs @@ -35,6 +35,7 @@ impl std::fmt::Display for DeserializationError { } } } + impl serde::de::Error for DeserializationError { fn custom(msg: T) -> Self where @@ -43,14 +44,16 @@ impl serde::de::Error for DeserializationError { Self::Serde(format!("{}", msg)) } } + impl std::convert::From for DeserializationError { fn from(e: super::Error) -> Self { Self::Reader(e) } } -impl<'de> SeqAccess<'de> for ReaderIterator<'de> { +impl<'de> SeqAccess<'de> for ReaderIterator<&'de [u8]> { type Error = DeserializationError; + fn next_element_seed( &mut self, seed: T, @@ -64,6 +67,7 @@ impl<'de> SeqAccess<'de> for ReaderIterator<'de> { Ok(None) } } + fn size_hint(&self) -> Option { Some(self.len()) } @@ -71,12 +75,13 @@ impl<'de> SeqAccess<'de> for ReaderIterator<'de> { struct EnumReader<'de> { variant: &'de str, - value: Option>, + value: Option>, } impl<'de> EnumAccess<'de> for EnumReader<'de> { type Error = DeserializationError; - type Variant = Reader<'de>; + type Variant = Reader<&'de [u8]>; + fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> where V: DeserializeSeed<'de>, @@ -87,9 +92,10 @@ impl<'de> EnumAccess<'de> for EnumReader<'de> { } struct MapAccessor<'de> { - keys: ReaderIterator<'de>, - vals: ReaderIterator<'de>, + keys: ReaderIterator<&'de [u8]>, + vals: ReaderIterator<&'de [u8]>, } + impl<'de> MapAccess<'de> for MapAccessor<'de> { type Error = DeserializationError; @@ -103,6 +109,7 @@ impl<'de> MapAccess<'de> for MapAccessor<'de> { Ok(None) } } + fn next_value_seed(&mut self, seed: V) -> Result where V: DeserializeSeed<'de>, @@ -112,17 +119,20 @@ impl<'de> MapAccess<'de> for MapAccessor<'de> { } } -impl<'de> VariantAccess<'de> for Reader<'de> { +impl<'de> VariantAccess<'de> for Reader<&'de [u8]> { type Error = DeserializationError; + fn unit_variant(self) -> Result<(), Self::Error> { Ok(()) } + fn newtype_variant_seed(self, seed: T) -> Result where T: DeserializeSeed<'de>, { seed.deserialize(self) } + // Tuple variants have an internally tagged representation. They are vectors where Index 0 is // the discriminant and index N is field N-1. fn tuple_variant(self, _len: usize, visitor: V) -> Result @@ -131,6 +141,7 @@ impl<'de> VariantAccess<'de> for Reader<'de> { { visitor.visit_seq(self.as_vector().iter()) } + // Struct variants have an internally tagged representation. They are vectors where Index 0 is // the discriminant and index N is field N-1. fn struct_variant( @@ -149,7 +160,7 @@ impl<'de> VariantAccess<'de> for Reader<'de> { } } -impl<'de> Deserializer<'de> for crate::Reader<'de> { +impl<'de> Deserializer<'de> for Reader<&'de [u8]> { type Error = DeserializationError; fn is_human_readable(&self) -> bool { cfg!(deserialize_human_readable) @@ -188,22 +199,26 @@ impl<'de> Deserializer<'de> for crate::Reader<'de> { (ty, bw) => unreachable!("TODO deserialize_any {:?} {:?}.", ty, bw), } } + serde::forward_to_deserialize_any! { bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 str unit unit_struct bytes ignored_any map identifier struct tuple tuple_struct seq string } + fn deserialize_char(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_char(self.as_u8() as char) } + fn deserialize_byte_buf(self, visitor: V) -> Result where V: Visitor<'de>, { visitor.visit_byte_buf(self.get_blob()?.0.to_vec()) } + fn deserialize_option(self, visitor: V) -> Result where V: Visitor<'de>, @@ -214,6 +229,7 @@ impl<'de> Deserializer<'de> for crate::Reader<'de> { visitor.visit_some(self) } } + fn deserialize_newtype_struct( self, _name: &'static str, @@ -224,6 +240,7 @@ impl<'de> Deserializer<'de> for crate::Reader<'de> { { visitor.visit_newtype_struct(self) } + fn deserialize_enum( self, _name: &'static str, diff --git a/rust/flexbuffers/src/reader/iter.rs b/rust/flexbuffers/src/reader/iter.rs index 8e06171cc02..267a01f1cc8 100644 --- a/rust/flexbuffers/src/reader/iter.rs +++ b/rust/flexbuffers/src/reader/iter.rs @@ -12,19 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -use super::{Reader, VectorReader}; +use crate::{Buffer, Reader, VectorReader}; use std::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator}; /// Iterates over a flexbuffer vector, typed vector, or map. Yields [Readers](struct.Reader.html). /// /// If any error occurs, the Reader is defaulted to a Null flexbuffer Reader. -pub struct ReaderIterator<'de> { - pub(super) reader: VectorReader<'de>, +pub struct ReaderIterator { + pub(super) reader: VectorReader, pub(super) front: usize, end: usize, } -impl<'de> ReaderIterator<'de> { - pub(super) fn new(reader: VectorReader<'de>) -> Self { + +impl ReaderIterator { + pub(super) fn new(reader: VectorReader) -> Self { let end = reader.len(); ReaderIterator { reader, @@ -33,8 +34,9 @@ impl<'de> ReaderIterator<'de> { } } } -impl<'de> Iterator for ReaderIterator<'de> { - type Item = Reader<'de>; + +impl Iterator for ReaderIterator { + type Item = Reader; fn next(&mut self) -> Option { if self.front < self.end { let r = self.reader.idx(self.front); @@ -49,7 +51,8 @@ impl<'de> Iterator for ReaderIterator<'de> { (remaining, Some(remaining)) } } -impl<'de> DoubleEndedIterator for ReaderIterator<'de> { + +impl DoubleEndedIterator for ReaderIterator { fn next_back(&mut self) -> Option { if self.front < self.end { self.end -= 1; @@ -59,5 +62,6 @@ impl<'de> DoubleEndedIterator for ReaderIterator<'de> { } } } -impl<'de> ExactSizeIterator for ReaderIterator<'de> {} -impl<'de> FusedIterator for ReaderIterator<'de> {} + +impl ExactSizeIterator for ReaderIterator {} +impl FusedIterator for ReaderIterator {} diff --git a/rust/flexbuffers/src/reader/map.rs b/rust/flexbuffers/src/reader/map.rs index cdf59e083d2..b0accacc86f 100644 --- a/rust/flexbuffers/src/reader/map.rs +++ b/rust/flexbuffers/src/reader/map.rs @@ -14,6 +14,7 @@ use super::{deref_offset, unpack_type, Error, Reader, ReaderIterator, VectorReader}; use crate::BitWidth; +use crate::Buffer; use std::cmp::Ordering; use std::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator}; @@ -22,9 +23,8 @@ use std::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator} /// MapReaders may be indexed with strings or usizes. `index` returns a result type, /// which may indicate failure due to a missing key or bad data, `idx` returns an Null Reader in /// cases of error. -#[derive(Default, Clone)] -pub struct MapReader<'de> { - pub(super) buffer: &'de [u8], +pub struct MapReader { + pub(super) buffer: B, pub(super) values_address: usize, pub(super) keys_address: usize, pub(super) values_width: BitWidth, @@ -32,8 +32,30 @@ pub struct MapReader<'de> { pub(super) length: usize, } +impl Clone for MapReader { + fn clone(&self) -> Self { + MapReader { + buffer: self.buffer.shallow_copy(), + ..*self + } + } +} + +impl Default for MapReader { + fn default() -> Self { + MapReader { + buffer: B::empty(), + values_address: usize::default(), + keys_address: usize::default(), + values_width: BitWidth::default(), + keys_width: BitWidth::default(), + length: usize::default(), + } + } +} + // manual implementation of Debug because buffer slice can't be automatically displayed -impl<'de> std::fmt::Debug for MapReader<'de> { +impl std::fmt::Debug for MapReader { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // skips buffer field f.debug_struct("MapReader") @@ -46,15 +68,19 @@ impl<'de> std::fmt::Debug for MapReader<'de> { } } -impl<'de> MapReader<'de> { +impl MapReader { /// Returns the number of key/value pairs are in the map. pub fn len(&self) -> usize { + let thing = self.clone(); + println!("{:?}", &thing); self.length } + /// Returns true if the map has zero key/value pairs. pub fn is_empty(&self) -> bool { self.length == 0 } + // Using &CStr will eagerly compute the length of the key. &str needs length info AND utf8 // validation. This version is faster than both. fn lazy_strcmp(&self, key_addr: usize, key: &str) -> Ordering { @@ -62,6 +88,7 @@ impl<'de> MapReader<'de> { let k = self.buffer[key_addr..].iter().take_while(|&&b| b != b'\0'); k.cmp(key.as_bytes().iter()) } + /// Returns the index of a given key in the map. pub fn index_key(&self, key: &str) -> Option { let (mut low, mut high) = (0, self.length); @@ -69,7 +96,7 @@ impl<'de> MapReader<'de> { let i = (low + high) / 2; let key_offset_address = self.keys_address + i * self.keys_width.n_bytes(); let key_address = - deref_offset(self.buffer, key_offset_address, self.keys_width).ok()?; + deref_offset(&self.buffer, key_offset_address, self.keys_width).ok()?; match self.lazy_strcmp(key_address, key) { Ordering::Equal => return Some(i), Ordering::Less => low = if i == low { i + 1 } else { i }, @@ -78,15 +105,18 @@ impl<'de> MapReader<'de> { } None } + /// Index into a map with a key or usize. - pub fn index(&self, i: I) -> Result, Error> { + pub fn index(&self, i: I) -> Result, Error> { i.index_map_reader(self) } + /// Index into a map with a key or usize. If any errors occur a Null reader is returned. - pub fn idx(&self, i: I) -> Reader<'de> { + pub fn idx(&self, i: I) -> Reader { i.index_map_reader(self).unwrap_or_default() } - fn usize_index(&self, i: usize) -> Result, Error> { + + fn usize_index(&self, i: usize) -> Result, Error> { if i >= self.length { return Err(Error::IndexOutOfBounds); } @@ -98,22 +128,24 @@ impl<'de> MapReader<'de> { .ok_or(Error::FlexbufferOutOfBounds) .and_then(|&b| unpack_type(b))?; Reader::new( - &self.buffer, + self.buffer.shallow_copy(), data_address, fxb_type, width, self.values_width, ) } - fn key_index(&self, k: &str) -> Result, Error> { + + fn key_index(&self, k: &str) -> Result, Error> { let i = self.index_key(k).ok_or(Error::KeyNotFound)?; self.usize_index(i) } + /// Iterate over the values of the map. - pub fn iter_values(&self) -> ReaderIterator<'de> { + pub fn iter_values(&self) -> ReaderIterator { ReaderIterator::new(VectorReader { reader: Reader { - buffer: self.buffer, + buffer: self.buffer.shallow_copy(), fxb_type: crate::FlexBufferType::Map, width: self.values_width, address: self.values_address, @@ -121,17 +153,19 @@ impl<'de> MapReader<'de> { length: self.length, }) } + /// Iterate over the keys of the map. pub fn iter_keys( &self, - ) -> impl Iterator + DoubleEndedIterator + ExactSizeIterator + FusedIterator + ) -> impl Iterator + DoubleEndedIterator + ExactSizeIterator + FusedIterator { self.keys_vector().iter().map(|k| k.as_str()) } - pub fn keys_vector(&self) -> VectorReader<'de> { + + pub fn keys_vector(&self) -> VectorReader { VectorReader { reader: Reader { - buffer: self.buffer, + buffer: self.buffer.shallow_copy(), fxb_type: crate::FlexBufferType::VectorKey, width: self.keys_width, address: self.keys_address, @@ -140,18 +174,21 @@ impl<'de> MapReader<'de> { } } } + pub trait MapReaderIndexer { - fn index_map_reader<'de>(self, r: &MapReader<'de>) -> Result, Error>; + fn index_map_reader(self, r: &MapReader) -> Result, Error>; } + impl MapReaderIndexer for usize { #[inline] - fn index_map_reader<'de>(self, r: &MapReader<'de>) -> Result, Error> { + fn index_map_reader(self, r: &MapReader) -> Result, Error> { r.usize_index(self) } } + impl MapReaderIndexer for &str { #[inline] - fn index_map_reader<'de>(self, r: &MapReader<'de>) -> Result, Error> { + fn index_map_reader(self, r: &MapReader) -> Result, Error> { r.key_index(self) } } diff --git a/rust/flexbuffers/src/reader/mod.rs b/rust/flexbuffers/src/reader/mod.rs index 4a3f472d23f..cac46341e66 100644 --- a/rust/flexbuffers/src/reader/mod.rs +++ b/rust/flexbuffers/src/reader/mod.rs @@ -14,7 +14,7 @@ use crate::bitwidth::BitWidth; use crate::flexbuffer_type::FlexBufferType; -use crate::Blob; +use crate::{Buffer, Blob}; use std::convert::{TryFrom, TryInto}; use std::fmt; use std::ops::Rem; @@ -143,16 +143,37 @@ macro_rules! as_default { /// - The `as_T` methods will try their best to return to a value of type `T` /// (by casting or even parsing a string if necessary) but ultimately returns `T::default` if it /// fails. This behavior is analogous to that of flexbuffers C++. -#[derive(Default, Clone)] -pub struct Reader<'de> { +pub struct Reader { fxb_type: FlexBufferType, width: BitWidth, address: usize, - buffer: &'de [u8], + buffer: B, +} + +impl Clone for Reader { + fn clone(&self) -> Self { + Reader { + fxb_type: self.fxb_type, + width: self.width, + address: self.address, + buffer: self.buffer.shallow_copy(), + } + } +} + +impl Default for Reader { + fn default() -> Self { + Reader { + fxb_type: FlexBufferType::default(), + width: BitWidth::default(), + address: usize::default(), + buffer: B::empty(), + } + } } // manual implementation of Debug because buffer slice can't be automatically displayed -impl<'de> std::fmt::Debug for Reader<'de> { +impl std::fmt::Debug for Reader { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { // skips buffer field f.debug_struct("Reader") @@ -181,16 +202,16 @@ fn deref_offset(buffer: &[u8], address: usize, width: BitWidth) -> Result Reader<'de> { +impl Reader { fn new( - buffer: &'de [u8], + buffer: B, mut address: usize, mut fxb_type: FlexBufferType, width: BitWidth, parent_width: BitWidth, ) -> Result { if fxb_type.is_reference() { - address = deref_offset(buffer, address, parent_width)?; + address = deref_offset(&buffer, address, parent_width)?; // Indirects were dereferenced. if let Some(t) = fxb_type.to_direct() { fxb_type = t; @@ -203,9 +224,10 @@ impl<'de> Reader<'de> { buffer, }) } + /// Parses the flexbuffer from the given buffer. Assumes the flexbuffer root is the last byte /// of the buffer. - pub fn get_root(buffer: &'de [u8]) -> Result { + pub fn get_root(buffer: B) -> Result { let end = buffer.len(); if end < 3 { return Err(Error::FlexbufferOutOfBounds); @@ -218,21 +240,30 @@ impl<'de> Reader<'de> { let address = safe_sub(end - 2, root_width.n_bytes())?; Self::new(buffer, address, fxb_type, width, root_width) } + + /// Convenience function to get the underlying buffer. By using `shallow_copy`, this preserves + /// the lifetime that the underlying buffer has. + pub fn buffer(&self) -> B { + self.buffer.shallow_copy() + } + /// Returns the FlexBufferType of this Reader. pub fn flexbuffer_type(&self) -> FlexBufferType { self.fxb_type } + /// Returns the bitwidth of this Reader. pub fn bitwidth(&self) -> BitWidth { self.width } + /// Returns the length of the Flexbuffer. If the type has no length, or if an error occurs, /// 0 is returned. pub fn length(&self) -> usize { if let Some(len) = self.fxb_type.fixed_length_vector_length() { len } else if self.fxb_type.has_length_slot() && self.address >= self.width.n_bytes() { - read_usize(self.buffer, self.address - self.width.n_bytes(), self.width) + read_usize(&self.buffer, self.address - self.width.n_bytes(), self.width) } else { 0 } @@ -240,11 +271,13 @@ impl<'de> Reader<'de> { /// Returns true if the flexbuffer is aligned to 8 bytes. This guarantees, for valid /// flexbuffers, that the data is correctly aligned in memory and slices can be read directly /// e.g. with `get_f64s` or `get_i16s`. + #[inline] pub fn is_aligned(&self) -> bool { (self.buffer.as_ptr() as usize).rem(8) == 0 } - as_default!(as_vector, get_vector, VectorReader<'de>); - as_default!(as_map, get_map, MapReader<'de>); + + as_default!(as_vector, get_vector, VectorReader); + as_default!(as_map, get_map, MapReader); fn expect_type(&self, ty: FlexBufferType) -> Result<(), Error> { if self.fxb_type == ty { @@ -266,11 +299,16 @@ impl<'de> Reader<'de> { }) } } - /// Directly reads a slice of type `T`where `T` is one of `u8,u16,u32,u64,i8,i16,i32,i64,f32,f64`. + + /// Directly reads a slice of type `T` where `T` is one of `u8,u16,u32,u64,i8,i16,i32,i64,f32,f64`. /// Returns Err if the type, bitwidth, or memory alignment does not match. Since the bitwidth is /// dynamic, its better to use a VectorReader unless you know your data and performance is critical. #[cfg(target_endian = "little")] - pub fn get_slice(&self) -> Result<&'de [T], Error> { + #[deprecated( + since = "0.3.0", + note = "This function is unsafe - if this functionality is needed it can be added separately via the `buffer` function." + )] + pub fn get_slice(&self) -> Result<&[T], Error> { if self.flexbuffer_type().typed_vector_type() != T::VECTOR_TYPE.typed_vector_type() { self.expect_type(T::VECTOR_TYPE)?; } @@ -278,10 +316,11 @@ impl<'de> Reader<'de> { self.expect_bw(T::WIDTH)?; } let end = self.address + self.length() * std::mem::size_of::(); - let slice = &self + let slice: &[u8] = self .buffer .get(self.address..end) .ok_or(Error::FlexbufferOutOfBounds)?; + // `align_to` is required because the point of this function is to directly hand back a // slice of scalars. This can fail because Rust's default allocator is not 16byte aligned // (though in practice this only happens for small buffers). @@ -293,6 +332,8 @@ impl<'de> Reader<'de> { } } + /// Returns the value of the reader if it is a boolean. + /// Otherwise Returns error. pub fn get_bool(&self) -> Result { self.expect_type(FlexBufferType::Bool)?; Ok( @@ -301,30 +342,50 @@ impl<'de> Reader<'de> { .any(|&b| b != 0), ) } - pub fn get_key(&self) -> Result<&'de str, Error> { + + /// Gets the length of the key if this type is a key. + /// + /// Otherwise, returns an error. + #[inline] + fn get_key_len(&self) -> Result { self.expect_type(FlexBufferType::Key)?; let (length, _) = self.buffer[self.address..] .iter() .enumerate() .find(|(_, &b)| b == b'\0') .unwrap_or((0, &0)); - let bytes = &self.buffer[self.address..self.address + length]; - Ok(std::str::from_utf8(bytes)?) + Ok(length) } - pub fn get_blob(&self) -> Result, Error> { + + /// Retrieves the string value up until the first `\0` character. + pub fn get_key(&self) -> Result { + let bytes = self.buffer + .slice(self.address..self.address + self.get_key_len()?) + .ok_or(Error::IndexOutOfBounds)?; + Ok(bytes.buffer_str()?) + } + + pub fn get_blob(&self) -> Result, Error> { self.expect_type(FlexBufferType::Blob)?; Ok(Blob( - &self.buffer[self.address..self.address + self.length()], + self.buffer + .slice(self.address..self.address + self.length()) + .ok_or(Error::IndexOutOfBounds)? )) } - pub fn as_blob(&self) -> Blob<'de> { - self.get_blob().unwrap_or(Blob(&[])) + + pub fn as_blob(&self) -> Blob { + self.get_blob().unwrap_or(Blob(B::empty())) } - pub fn get_str(&self) -> Result<&'de str, Error> { + + /// Retrieves str pointer, errors if invalid UTF-8, or the provided index + /// is out of bounds. + pub fn get_str(&self) -> Result { self.expect_type(FlexBufferType::String)?; - let bytes = &self.buffer[self.address..self.address + self.length()]; - Ok(std::str::from_utf8(bytes)?) + let bytes = self.buffer.slice(self.address..self.address + self.length()); + Ok(bytes.ok_or(Error::ReadUsizeOverflowed)?.buffer_str()?) } + fn get_map_info(&self) -> Result<(usize, BitWidth), Error> { self.expect_type(FlexBufferType::Map)?; if 3 * self.width.n_bytes() >= self.address { @@ -333,17 +394,18 @@ impl<'de> Reader<'de> { let keys_offset_address = self.address - 3 * self.width.n_bytes(); let keys_width = { let kw_addr = self.address - 2 * self.width.n_bytes(); - let kw = read_usize(self.buffer, kw_addr, self.width); + let kw = read_usize(&self.buffer, kw_addr, self.width); BitWidth::from_nbytes(kw).ok_or(Error::InvalidMapKeysVectorWidth) }?; Ok((keys_offset_address, keys_width)) } - pub fn get_map(&self) -> Result, Error> { + + pub fn get_map(&self) -> Result, Error> { let (keys_offset_address, keys_width) = self.get_map_info()?; - let keys_address = deref_offset(self.buffer, keys_offset_address, self.width)?; + let keys_address = deref_offset(&self.buffer, keys_offset_address, self.width)?; // TODO(cneo): Check that vectors length equals keys length. Ok(MapReader { - buffer: self.buffer, + buffer: self.buffer.shallow_copy(), values_address: self.address, values_width: self.width, keys_address, @@ -351,6 +413,7 @@ impl<'de> Reader<'de> { length: self.length(), }) } + /// Tries to read a FlexBufferType::UInt. Returns Err if the type is not a UInt or if the /// address is out of bounds. pub fn get_u64(&self) -> Result { @@ -443,7 +506,7 @@ impl<'de> Reader<'de> { FlexBufferType::Float => self.get_f64().unwrap_or_default() as u64, FlexBufferType::String => { if let Ok(s) = self.get_str() { - if let Ok(f) = u64::from_str(s) { + if let Ok(f) = u64::from_str(&s) { return f; } } @@ -470,7 +533,7 @@ impl<'de> Reader<'de> { FlexBufferType::Float => self.get_f64().unwrap_or_default() as i64, FlexBufferType::String => { if let Ok(s) = self.get_str() { - if let Ok(f) = i64::from_str(s) { + if let Ok(f) = i64::from_str(&s) { return f; } } @@ -493,7 +556,7 @@ impl<'de> Reader<'de> { FlexBufferType::Float => self.get_f64().unwrap_or_default(), FlexBufferType::String => { if let Ok(s) = self.get_str() { - if let Ok(f) = f64::from_str(s) { + if let Ok(f) = f64::from_str(&s) { return f; } } @@ -508,14 +571,15 @@ impl<'de> Reader<'de> { } /// Returns empty string if you're not trying to read a string. - pub fn as_str(&self) -> &'de str { + pub fn as_str(&self) -> B::BufferString { match self.fxb_type { - FlexBufferType::String => self.get_str().unwrap_or_default(), - FlexBufferType::Key => self.get_key().unwrap_or_default(), - _ => "", + FlexBufferType::String => self.get_str().unwrap_or(B::empty_str()), + FlexBufferType::Key => self.get_key().unwrap_or(B::empty_str()), + _ => B::empty_str(), } } - pub fn get_vector(&self) -> Result, Error> { + + pub fn get_vector(&self) -> Result, Error> { if !self.fxb_type.is_vector() { self.expect_type(FlexBufferType::Vector)?; }; @@ -526,7 +590,7 @@ impl<'de> Reader<'de> { } } -impl<'de> fmt::Display for Reader<'de> { +impl fmt::Display for Reader { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use FlexBufferType::*; match self.flexbuffer_type() { @@ -534,7 +598,7 @@ impl<'de> fmt::Display for Reader<'de> { UInt => write!(f, "{}", self.as_u64()), Int => write!(f, "{}", self.as_i64()), Float => write!(f, "{}", self.as_f64()), - Key | String => write!(f, "{:?}", self.as_str()), + Key | String => write!(f, "{:?}", &self.as_str() as &str), Bool => write!(f, "{}", self.as_bool()), Blob => write!(f, "blob"), Map => { @@ -542,9 +606,9 @@ impl<'de> fmt::Display for Reader<'de> { let m = self.as_map(); let mut pairs = m.iter_keys().zip(m.iter_values()); if let Some((k, v)) = pairs.next() { - write!(f, "{:?}: {}", k, v)?; + write!(f, "{:?}: {}", &k as &str, v)?; for (k, v) in pairs { - write!(f, ", {:?}: {}", k, v)?; + write!(f, ", {:?}: {}", &k as &str, v)?; } } write!(f, "}}") @@ -570,6 +634,7 @@ fn f32_from_le_bytes(bytes: [u8; 4]) -> f32 { let bits = ::from_le_bytes(bytes); ::from_bits(bits) } + fn f64_from_le_bytes(bytes: [u8; 8]) -> f64 { let bits = ::from_le_bytes(bytes); ::from_bits(bits) @@ -601,4 +666,4 @@ fn unpack_type(ty: u8) -> Result<(FlexBufferType, BitWidth), Error> { let w = BitWidth::try_from(ty & 3u8).map_err(|_| Error::InvalidPackedType)?; let t = FlexBufferType::try_from(ty >> 2).map_err(|_| Error::InvalidPackedType)?; Ok((t, w)) -} +} \ No newline at end of file diff --git a/rust/flexbuffers/src/reader/vector.rs b/rust/flexbuffers/src/reader/vector.rs index 8ba8fe505c7..b23cbb49101 100644 --- a/rust/flexbuffers/src/reader/vector.rs +++ b/rust/flexbuffers/src/reader/vector.rs @@ -13,22 +13,39 @@ // limitations under the License. use super::{unpack_type, Error, Reader, ReaderIterator}; -use crate::{BitWidth, FlexBufferType}; +use crate::{BitWidth, Buffer, FlexBufferType}; -#[derive(Default, Clone)] /// Allows indexing on any flexbuffer vector type, (heterogenous vector, typed vector, or fixed /// length typed vector). /// /// VectorReaders may be indexed with usize, `index` returns a result type /// which may indicate failure due to indexing out of bounds or bad data. `idx` returns a /// Null Reader in the event of any failure. -pub struct VectorReader<'de> { - pub(super) reader: Reader<'de>, +pub struct VectorReader { + pub(super) reader: Reader, // Cache the length because read_usize can be slow. pub(super) length: usize, } -impl<'de> VectorReader<'de> { +impl Clone for VectorReader { + fn clone(&self) -> Self { + VectorReader { + reader: self.reader.clone(), + ..*self + } + } +} + +impl Default for VectorReader { + fn default() -> Self { + VectorReader { + reader: Reader::default(), + length: usize::default() + } + } +} + +impl VectorReader { /// Returns the number of elements in the vector. pub fn len(&self) -> usize { self.length @@ -50,25 +67,26 @@ impl<'de> VectorReader<'de> { } } /// Index into a flexbuffer vector. Any errors are defaulted to Null Readers. - pub fn idx(&self, i: usize) -> Reader<'de> { + pub fn idx(&self, i: usize) -> Reader { self.index(i).unwrap_or_default() } /// Index into a flexbuffer. - pub fn index(&self, i: usize) -> Result, Error> { + pub fn index(&self, i: usize) -> Result, Error> { if i >= self.length { return Err(Error::IndexOutOfBounds); } let (fxb_type, bw) = self.get_elem_type(i)?; let data_address = self.reader.address + self.reader.width.n_bytes() * i; Reader::new( - self.reader.buffer, + self.reader.buffer.shallow_copy(), data_address, fxb_type, bw, self.reader.width, ) } - pub fn iter(&self) -> ReaderIterator<'de> { + + pub fn iter(&self) -> ReaderIterator { ReaderIterator::new(self.clone()) } } diff --git a/tests/rust_usage_test/benches/flexbuffers_benchmarks.rs b/tests/rust_usage_test/benches/flexbuffers_benchmarks.rs index 1e9c516e4a1..1b9a8fbbacf 100644 --- a/tests/rust_usage_test/benches/flexbuffers_benchmarks.rs +++ b/tests/rust_usage_test/benches/flexbuffers_benchmarks.rs @@ -224,7 +224,7 @@ fn serialize_monsters(b: &mut Bencher) { b.iter(go); b.bytes = n as u64; } -fn validate_monster(r: MapReader) { +fn validate_monster(r: MapReader<&[u8]>) { assert_eq!(r.idx("type").as_str(), "great orc"); assert_eq!(r.idx("age").as_u8(), 100); assert_eq!(r.idx("name").as_str(), "Mr. Orc"); diff --git a/tests/rust_usage_test/tests/flexbuffers_tests/binary_format.rs b/tests/rust_usage_test/tests/flexbuffers_tests/binary_format.rs index e52a281a0d9..910fc7881f9 100644 --- a/tests/rust_usage_test/tests/flexbuffers_tests/binary_format.rs +++ b/tests/rust_usage_test/tests/flexbuffers_tests/binary_format.rs @@ -311,7 +311,7 @@ fn utf8_snowman() { 1, // Root bytes ] ); - let r = Reader::get_root(&buf).unwrap(); + let r = Reader::get_root(buf.as_ref()).unwrap(); assert_eq!(r.get_str(), Ok("snowman ☃︎")); } #[test] diff --git a/tests/rust_usage_test/tests/flexbuffers_tests/interop.rs b/tests/rust_usage_test/tests/flexbuffers_tests/interop.rs index 54ae1fded16..705948f69e6 100644 --- a/tests/rust_usage_test/tests/flexbuffers_tests/interop.rs +++ b/tests/rust_usage_test/tests/flexbuffers_tests/interop.rs @@ -18,14 +18,14 @@ use flexbuffers::*; fn read_golden_flexbuffer() { let s = std::fs::read("../gold_flexbuffer_example.bin").expect("Unable to read golden flexbuffer."); - let r = Reader::get_root(&s).unwrap(); + let r = Reader::get_root(s.as_ref()).unwrap(); let m = r.as_map(); let vec = m.idx("vec").as_vector(); assert_eq!(vec.idx(0).as_i8(), -100); assert_eq!(vec.idx(1).as_str(), "Fred"); assert_eq!(vec.idx(2).as_f32(), 4.0); - assert_eq!(vec.idx(3).as_blob(), Blob(&[77])); + assert_eq!(vec.idx(3).as_blob(), Blob([77].as_ref())); assert_eq!(vec.idx(4).flexbuffer_type(), FlexBufferType::Bool); assert_eq!(vec.idx(4).as_bool(), false); assert_eq!(vec.idx(5).as_f64(), 4.0); diff --git a/tests/rust_usage_test/tests/flexbuffers_tests/other_api.rs b/tests/rust_usage_test/tests/flexbuffers_tests/other_api.rs index 8c8a4d4c308..d1c0873bba8 100644 --- a/tests/rust_usage_test/tests/flexbuffers_tests/other_api.rs +++ b/tests/rust_usage_test/tests/flexbuffers_tests/other_api.rs @@ -20,7 +20,7 @@ use quickcheck::QuickCheck; #[cfg(not(miri))] // slow. fn qc_reader_no_crash() { fn no_crash(xs: Vec) -> bool { - let r = Reader::get_root(&xs); + let r = Reader::get_root(xs.as_ref()); r.is_err() || r.is_ok() } QuickCheck::new() @@ -133,7 +133,7 @@ fn string_as_num() { } #[test] fn null_reader() { - let n = Reader::default(); + let n = Reader::<&[u8]>::default(); assert_eq!(n.as_i8(), 0); assert_eq!(n.as_i16(), 0); assert_eq!(n.as_i32(), 0); @@ -159,7 +159,7 @@ fn get_root_deref_oob() { (FlexBufferType::Vector as u8) << 2 | BitWidth::W8 as u8, 1, ]; - assert!(Reader::get_root(s).is_err()); + assert!(Reader::get_root(s.as_ref()).is_err()); } #[test] fn get_root_deref_u64() { @@ -170,7 +170,24 @@ fn get_root_deref_u64() { 1, ]; // The risk of crashing is reading 8 bytes from index 0. - assert_eq!(Reader::get_root(s).unwrap().as_u64(), 0); + assert_eq!(Reader::get_root(s.as_ref()).unwrap().as_u64(), 0); +} + +/// Verifies that the clone operation is shallow / zero copy. +#[test] +fn clone_is_shallow() { + let mut fxb = Builder::default(); + let mut m = fxb.start_map(); + m.push("a", &[-1i8, -2, -3, -4]); + m.push("b", 250i64); + m.push("c", 5000u16); + m.end_map(); + + let r = Reader::get_root(fxb.view()).unwrap(); + + let r2 = r.clone(); + + assert_eq!(r.buffer().as_ptr(), r2.buffer().as_ptr()); } #[test] diff --git a/tests/rust_usage_test/tests/flexbuffers_tests/rwyw.rs b/tests/rust_usage_test/tests/flexbuffers_tests/rwyw.rs index ea338b70739..dc8a201b0a7 100644 --- a/tests/rust_usage_test/tests/flexbuffers_tests/rwyw.rs +++ b/tests/rust_usage_test/tests/flexbuffers_tests/rwyw.rs @@ -43,7 +43,7 @@ quickcheck! { v.push(x); } v.end_vector(); - let r = Reader::get_root(&builder.view()).unwrap().as_vector(); + let r = Reader::get_root(builder.view()).unwrap().as_vector(); xs.iter().enumerate().all(|(i, &x)| r.index(i).unwrap().get_bool().unwrap() == x) } fn qc_vec_uint(xs: Vec) -> bool { @@ -53,7 +53,7 @@ quickcheck! { v.push(x); } v.end_vector(); - let r = Reader::get_root(&builder.view()).unwrap().as_vector(); + let r = Reader::get_root(builder.view()).unwrap().as_vector(); xs.iter().enumerate().all(|(i, &x)| r.idx(i).as_u64() == x) } fn qc_vec_int(xs: Vec) -> bool { @@ -63,7 +63,7 @@ quickcheck! { v.push(x); } v.end_vector(); - let r = Reader::get_root(&builder.view()).unwrap().as_vector(); + let r = Reader::get_root(builder.view()).unwrap().as_vector(); xs.iter().enumerate().all(|(i, &x)| r.idx(i).as_i64() == x) } fn qc_vec_float(xs: Vec) -> bool { @@ -73,7 +73,7 @@ quickcheck! { v.push(x); } v.end_vector(); - let r = Reader::get_root(&builder.view()).unwrap().as_vector(); + let r = Reader::get_root(builder.view()).unwrap().as_vector(); xs.iter().enumerate().all(|(i, &x)| (r.idx(i).as_f64() - x).abs() < std::f64::EPSILON) } fn qc_vec_string(xs: Vec) -> bool { @@ -83,7 +83,7 @@ quickcheck! { v.push(x as &str); } v.end_vector(); - let r = Reader::get_root(&builder.view()).unwrap().as_vector(); + let r = Reader::get_root(builder.view()).unwrap().as_vector(); xs.iter().enumerate().all(|(i, x)| (r.idx(i).as_str() == x)) } fn qc_map_int(xs: std::collections::BTreeMap) -> bool { @@ -93,7 +93,7 @@ quickcheck! { m.push(&k.0, v); } m.end_map(); - let r = Reader::get_root(&builder.view()).unwrap().as_map(); + let r = Reader::get_root(builder.view()).unwrap().as_map(); xs.iter().enumerate().all(|(i, (k, &v))| { r.idx(i).as_i64() == v && r.idx(k.0.as_str()).as_i64() == v }) @@ -105,7 +105,7 @@ quickcheck! { m.push(&k.0, v as &str); } m.end_map(); - let r = Reader::get_root(&builder.view()).unwrap().as_map(); + let r = Reader::get_root(builder.view()).unwrap().as_map(); xs.iter().enumerate().all(|(i, (k, v))| { r.idx(i).as_str() == v && r.idx(k.0.as_str()).as_str() == v }) @@ -114,10 +114,10 @@ quickcheck! { let mut builder = Builder::default(); let mut v = builder.start_vector(); for x in &xs { - v.push(Blob(&x)); + v.push(Blob(x.as_ref())); } v.end_vector(); - let r = Reader::get_root(&builder.view()).unwrap().as_vector(); + let r = Reader::get_root(builder.view()).unwrap().as_vector(); xs.iter().enumerate().all( |(i, x)| r.idx(i).get_blob().unwrap().0.iter().eq(x.iter()) ) @@ -209,7 +209,7 @@ fn string() { v.push("barrr"); v.push("bazzzzzz"); v.end_vector(); - let r = Reader::get_root(&builder.view()).unwrap().as_vector(); + let r = Reader::get_root(builder.view()).unwrap().as_vector(); assert_eq!(r.idx(0).as_str(), "foo"); assert_eq!(r.idx(1).as_str(), "barrr"); assert_eq!(r.idx(2).as_str(), "bazzzzzz"); @@ -218,7 +218,7 @@ fn string() { #[test] fn store_13() { let finished = singleton::(13); - let r = Reader::get_root(&finished).unwrap(); + let r = Reader::get_root(finished.as_ref()).unwrap(); assert_eq!(r.as_i32(), 13); } #[test] @@ -233,7 +233,7 @@ fn singleton_vector_uint_4_16bit() { let buf2 = singleton(&[2u8, 3, 5]); assert_eq!(buf1, buf2.as_slice()); - let r = Reader::get_root(&buf1).unwrap().as_vector(); + let r = Reader::get_root(buf1).unwrap().as_vector(); assert_eq!(r.idx(0).get_u64(), Ok(2)); assert_eq!(r.idx(1).get_u64(), Ok(3)); assert_eq!(r.idx(2).get_u64(), Ok(5)); @@ -248,7 +248,7 @@ fn vector_uint4() { v.push(5u8); v.push(7u8); v.end_vector(); - let r = Reader::get_root(&fxb.view()).unwrap(); + let r = Reader::get_root(fxb.view()).unwrap(); let v = r.as_vector(); assert_eq!(v.idx(0).get_u64(), Ok(2)); assert_eq!(v.idx(1).get_u64(), Ok(3)); @@ -264,13 +264,13 @@ fn vector_uint4() { fn store_and_read_blob() { let mut fxb = Builder::default(); let mut v = fxb.start_vector(); - v.push(Blob(&[1, 2, 3, 4])); - v.push(Blob(&[5, 6, 7])); + v.push(Blob([1, 2, 3, 4].as_ref())); + v.push(Blob([5, 6, 7].as_ref())); v.end_vector(); - let r = Reader::get_root(&fxb.view()).unwrap().as_vector(); - assert_eq!(r.idx(0).get_blob(), Ok(Blob(&[1, 2, 3, 4]))); - assert_eq!(r.idx(1).get_blob(), Ok(Blob(&[5, 6, 7]))); + let r = Reader::get_root(fxb.view()).unwrap().as_vector(); + assert_eq!(r.idx(0).get_blob(), Ok(Blob([1, 2, 3, 4].as_ref()))); + assert_eq!(r.idx(1).get_blob(), Ok(Blob([5, 6, 7].as_ref()))); } #[test] fn map_64bit() { @@ -280,7 +280,7 @@ fn map_64bit() { m.push("b", u64::max_value() - 3); m.end_map(); - let r = Reader::get_root(&fxb.view()).unwrap().as_map(); + let r = Reader::get_root(fxb.view()).unwrap().as_map(); assert_eq!(r.idx("a").as_u16(), 257); assert_eq!(r.idx("b").as_u64(), u64::max_value() - 3); } @@ -341,7 +341,7 @@ fn map_strings() { #[test] fn store_u64() { let finished = singleton(u64::max_value() - 10); - let r = Reader::get_root(&finished).unwrap(); + let r = Reader::get_root(finished.as_ref()).unwrap(); assert_eq!(r.get_u64(), Ok(u64::max_value() - 10)); } #[test] @@ -444,7 +444,7 @@ fn serialize_serde_with_bytes_as_blob() { Foo(vec![5, 6, 7, 8]).serialize(&mut s).unwrap(); let reader = Reader::get_root(s.view()).unwrap(); assert_eq!(reader.flexbuffer_type(), FlexBufferType::Blob); - assert_eq!(reader.as_blob(), Blob(&[5, 6, 7, 8])); + assert_eq!(reader.as_blob(), Blob([5, 6, 7, 8].as_ref())); } #[test] fn iter() { @@ -466,7 +466,7 @@ fn deserialize_newtype_i8() { #[derive(Deserialize)] struct Foo(u8); let data = [13, 4, 1]; - let r = Reader::get_root(&data).unwrap(); + let r = Reader::get_root(data.as_ref()).unwrap(); let foo = Foo::deserialize(r).unwrap(); assert_eq!(foo.0, 13); } @@ -475,7 +475,7 @@ fn deserialize_newtype_str() { #[derive(Deserialize)] struct Foo<'a>(&'a str); let data = [5, b'h', b'e', b'l', b'l', b'o', b'\0', 6, 5 << 2, 1]; - let r = Reader::get_root(&data).unwrap(); + let r = Reader::get_root(data.as_ref()).unwrap(); let foo = Foo::deserialize(r).unwrap(); assert_eq!(foo.0, "hello"); } @@ -490,7 +490,7 @@ fn deserialize_tuple_struct_to_vec_uint4() { 23 << 2 | 1, // (VectorUInt4, W16 - referring to data). 1, // Root width W8 - referring to vector. ]; - let r = Reader::get_root(&data).unwrap(); + let r = Reader::get_root(data.as_ref()).unwrap(); let foo = Foo::deserialize(r).unwrap(); assert_eq!(foo.0, 4); assert_eq!(foo.1, 16); @@ -503,7 +503,7 @@ fn deserialize_tuple_struct_to_vec_uint4() { 23 << 2, // Root type: VectorUInt4, W8. 1, // Root width: W8. ]; - let r = Reader::get_root(&data).unwrap(); + let r = Reader::get_root(data.as_ref()).unwrap(); let foo = Foo::deserialize(r).unwrap(); assert_eq!(foo.0, 1); assert_eq!(foo.1, 2);