mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-07 13:53:38 +00:00
[rust] Genericize flexbuffer reader (#6450)
* feature/rust-tokio-bytes added feature name for tokio-bytes * Added flexbuffer implementation, TODO: typecast to avoid recurse * Converted codebase to utilize FlexBuffer implementation, need to resolve deserialization issues * Added todo for lifetime issue, may use &'de [u8] for deserializer instead of current method * Added proper &[u8] implementation * Removed unused struct * Added experimental fix to get_slice * Added experimental fix to get_slice * Avoided lifetime issues via ref structs, need to check if this hurts peformance * Updated deserializer implementation to allow for borrowed data from Reader struct * Fixed bug with str * Removed unnecessary generic parameter * Added unsafe to avoid lifetime complaints, current tests pass, need to review alternatives to unsafe * Opinionated: Removed bytes crate as this implementation could be done in a separate crate * Cleaned up flatbuffer * Fixed sample / example * Resolved PR feedback, need to resolve issues with tests * Cleaned up FlexBuffer trait to be an auto impl * Removed TODO * Reverted Deserializer to only support &'de [u8] * Cleaned up / renamed function for clarification * Renamed FlexBuffer -> InternalBuffer for clarification on it's purpose * Fixed issue with key bytes * resolved issues with broken tests, confirming this is a breaking change * Removed FIXME that's solved by splitting String and Key variants * Implemented associated types approach * Fixed backward slice logic * Fixed MapReader compile error * Added from_buffer for deserialization, removed function since it's only needed for deserialization * Removed dead code * Cleaned up buffer, removed AsRef in favor of Deref * Renamed Buffer::as_str -> Buffer::buffer_str * Minor cleanup * Updated documentation, need to fix tests * Removed unnecessary & * Removed unused lifetime * removed unnecessary as_ref * Minor optimization wrap-up * resolved issue with Clone * Added test to verify no deep-copy * Added for optimization * Updated to use empty fn instead of default * Updated comments / test name - plus the 0.3.0 version bump * comment
This commit is contained in:
@@ -35,6 +35,7 @@ impl std::fmt::Display for DeserializationError {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::de::Error for DeserializationError {
|
||||
fn custom<T>(msg: T) -> Self
|
||||
where
|
||||
@@ -43,14 +44,16 @@ impl serde::de::Error for DeserializationError {
|
||||
Self::Serde(format!("{}", msg))
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<super::Error> 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<T>(
|
||||
&mut self,
|
||||
seed: T,
|
||||
@@ -64,6 +67,7 @@ impl<'de> SeqAccess<'de> for ReaderIterator<'de> {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> Option<usize> {
|
||||
Some(self.len())
|
||||
}
|
||||
@@ -71,12 +75,13 @@ impl<'de> SeqAccess<'de> for ReaderIterator<'de> {
|
||||
|
||||
struct EnumReader<'de> {
|
||||
variant: &'de str,
|
||||
value: Option<Reader<'de>>,
|
||||
value: Option<Reader<&'de [u8]>>,
|
||||
}
|
||||
|
||||
impl<'de> EnumAccess<'de> for EnumReader<'de> {
|
||||
type Error = DeserializationError;
|
||||
type Variant = Reader<'de>;
|
||||
type Variant = Reader<&'de [u8]>;
|
||||
|
||||
fn variant_seed<V>(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<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
|
||||
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<T>(self, seed: T) -> Result<T::Value, Self::Error>
|
||||
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<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
|
||||
@@ -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<V>(
|
||||
@@ -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<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_char(self.as_u8() as char)
|
||||
}
|
||||
|
||||
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
visitor.visit_byte_buf(self.get_blob()?.0.to_vec())
|
||||
}
|
||||
|
||||
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
@@ -214,6 +229,7 @@ impl<'de> Deserializer<'de> for crate::Reader<'de> {
|
||||
visitor.visit_some(self)
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_newtype_struct<V>(
|
||||
self,
|
||||
_name: &'static str,
|
||||
@@ -224,6 +240,7 @@ impl<'de> Deserializer<'de> for crate::Reader<'de> {
|
||||
{
|
||||
visitor.visit_newtype_struct(self)
|
||||
}
|
||||
|
||||
fn deserialize_enum<V>(
|
||||
self,
|
||||
_name: &'static str,
|
||||
|
||||
@@ -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<B> {
|
||||
pub(super) reader: VectorReader<B>,
|
||||
pub(super) front: usize,
|
||||
end: usize,
|
||||
}
|
||||
impl<'de> ReaderIterator<'de> {
|
||||
pub(super) fn new(reader: VectorReader<'de>) -> Self {
|
||||
|
||||
impl<B: Buffer> ReaderIterator<B> {
|
||||
pub(super) fn new(reader: VectorReader<B>) -> 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<B: Buffer> Iterator for ReaderIterator<B> {
|
||||
type Item = Reader<B>;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
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<B: Buffer> DoubleEndedIterator for ReaderIterator<B> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
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<B: Buffer> ExactSizeIterator for ReaderIterator<B> {}
|
||||
impl<B: Buffer> FusedIterator for ReaderIterator<B> {}
|
||||
|
||||
@@ -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<B> {
|
||||
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<B: Buffer> Clone for MapReader<B> {
|
||||
fn clone(&self) -> Self {
|
||||
MapReader {
|
||||
buffer: self.buffer.shallow_copy(),
|
||||
..*self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Buffer> Default for MapReader<B> {
|
||||
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<B: Buffer> std::fmt::Debug for MapReader<B> {
|
||||
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<B: Buffer> MapReader<B> {
|
||||
/// 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<usize> {
|
||||
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<I: MapReaderIndexer>(&self, i: I) -> Result<Reader<'de>, Error> {
|
||||
pub fn index<I: MapReaderIndexer>(&self, i: I) -> Result<Reader<B>, 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<I: MapReaderIndexer>(&self, i: I) -> Reader<'de> {
|
||||
pub fn idx<I: MapReaderIndexer>(&self, i: I) -> Reader<B> {
|
||||
i.index_map_reader(self).unwrap_or_default()
|
||||
}
|
||||
fn usize_index(&self, i: usize) -> Result<Reader<'de>, Error> {
|
||||
|
||||
fn usize_index(&self, i: usize) -> Result<Reader<B>, 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<Reader<'de>, Error> {
|
||||
|
||||
fn key_index(&self, k: &str) -> Result<Reader<B>, 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<B> {
|
||||
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<Item = &'de str> + DoubleEndedIterator + ExactSizeIterator + FusedIterator
|
||||
) -> impl Iterator<Item = B::BufferString> + 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<B> {
|
||||
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<Reader<'de>, Error>;
|
||||
fn index_map_reader<B: Buffer>(self, r: &MapReader<B>) -> Result<Reader<B>, Error>;
|
||||
}
|
||||
|
||||
impl MapReaderIndexer for usize {
|
||||
#[inline]
|
||||
fn index_map_reader<'de>(self, r: &MapReader<'de>) -> Result<Reader<'de>, Error> {
|
||||
fn index_map_reader<B: Buffer>(self, r: &MapReader<B>) -> Result<Reader<B>, Error> {
|
||||
r.usize_index(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl MapReaderIndexer for &str {
|
||||
#[inline]
|
||||
fn index_map_reader<'de>(self, r: &MapReader<'de>) -> Result<Reader<'de>, Error> {
|
||||
fn index_map_reader<B: Buffer>(self, r: &MapReader<B>) -> Result<Reader<B>, Error> {
|
||||
r.key_index(self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<B> {
|
||||
fxb_type: FlexBufferType,
|
||||
width: BitWidth,
|
||||
address: usize,
|
||||
buffer: &'de [u8],
|
||||
buffer: B,
|
||||
}
|
||||
|
||||
impl<B: Buffer> Clone for Reader<B> {
|
||||
fn clone(&self) -> Self {
|
||||
Reader {
|
||||
fxb_type: self.fxb_type,
|
||||
width: self.width,
|
||||
address: self.address,
|
||||
buffer: self.buffer.shallow_copy(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Buffer> Default for Reader<B> {
|
||||
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<B> std::fmt::Debug for Reader<B> {
|
||||
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<usize,
|
||||
safe_sub(address, off)
|
||||
}
|
||||
|
||||
impl<'de> Reader<'de> {
|
||||
impl<B: Buffer> Reader<B> {
|
||||
fn new(
|
||||
buffer: &'de [u8],
|
||||
buffer: B,
|
||||
mut address: usize,
|
||||
mut fxb_type: FlexBufferType,
|
||||
width: BitWidth,
|
||||
parent_width: BitWidth,
|
||||
) -> Result<Self, Error> {
|
||||
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<Self, Error> {
|
||||
pub fn get_root(buffer: B) -> Result<Self, Error> {
|
||||
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<B>);
|
||||
as_default!(as_map, get_map, MapReader<B>);
|
||||
|
||||
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<T: ReadLE>(&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<T: ReadLE>(&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::<T>();
|
||||
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<bool, Error> {
|
||||
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<usize, Error> {
|
||||
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<Blob<'de>, Error> {
|
||||
|
||||
/// Retrieves the string value up until the first `\0` character.
|
||||
pub fn get_key(&self) -> Result<B::BufferString, Error> {
|
||||
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<Blob<B>, 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<B> {
|
||||
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<B::BufferString, Error> {
|
||||
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<MapReader<'de>, Error> {
|
||||
|
||||
pub fn get_map(&self) -> Result<MapReader<B>, 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<u64, Error> {
|
||||
@@ -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<VectorReader<'de>, Error> {
|
||||
|
||||
pub fn get_vector(&self) -> Result<VectorReader<B>, 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<B: Buffer> fmt::Display for Reader<B> {
|
||||
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 = <u32>::from_le_bytes(bytes);
|
||||
<f32>::from_bits(bits)
|
||||
}
|
||||
|
||||
fn f64_from_le_bytes(bytes: [u8; 8]) -> f64 {
|
||||
let bits = <u64>::from_le_bytes(bytes);
|
||||
<f64>::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))
|
||||
}
|
||||
}
|
||||
@@ -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<B> {
|
||||
pub(super) reader: Reader<B>,
|
||||
// Cache the length because read_usize can be slow.
|
||||
pub(super) length: usize,
|
||||
}
|
||||
|
||||
impl<'de> VectorReader<'de> {
|
||||
impl<B: Buffer> Clone for VectorReader<B> {
|
||||
fn clone(&self) -> Self {
|
||||
VectorReader {
|
||||
reader: self.reader.clone(),
|
||||
..*self
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Buffer> Default for VectorReader<B> {
|
||||
fn default() -> Self {
|
||||
VectorReader {
|
||||
reader: Reader::default(),
|
||||
length: usize::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Buffer> VectorReader<B> {
|
||||
/// 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<B> {
|
||||
self.index(i).unwrap_or_default()
|
||||
}
|
||||
/// Index into a flexbuffer.
|
||||
pub fn index(&self, i: usize) -> Result<Reader<'de>, Error> {
|
||||
pub fn index(&self, i: usize) -> Result<Reader<B>, 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<B> {
|
||||
ReaderIterator::new(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user