mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-09 14:46:26 +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:
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user