Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rust/flexbuffers/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ homepage = "https://google.github.io/flatbuffers/flexbuffers"
repository = "https://github.com/google/flatbuffers"
keywords = ["flatbuffers", "flexbuffers", "serialization", "zero-copy"]
categories = ["encoding", "data-structures", "memory-management"]
rust-version = "1.82"

[features]
# Sets serde::Serializer::is_human_readable() to true.
Expand Down
9 changes: 5 additions & 4 deletions rust/flexbuffers/src/bitwidth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
// limitations under the License.

use crate::bitwidth::BitWidth::*;
use serde_derive::{Deserialize, Serialize};
use std::slice::Iter;

/// Represents the size of Flexbuffers data.
Expand Down Expand Up @@ -68,13 +69,13 @@ macro_rules! impl_bitwidth_from {
impl From<$from> for BitWidth {
fn from(x: $from) -> BitWidth {
let x = x as $w64;
if x >= $w8::min_value() as $w64 && x <= $w8::max_value() as $w64 {
if x >= $w8::MIN as $w64 && x <= $w8::MAX as $w64 {
return W8;
}
if x >= $w16::min_value() as $w64 && x <= $w16::max_value() as $w64 {
if x >= $w16::MIN as $w64 && x <= $w16::MAX as $w64 {
return W16;
}
if x >= $w32::min_value() as $w64 && x <= $w32::max_value() as $w64 {
if x >= $w32::MIN as $w64 && x <= $w32::MAX as $w64 {
return W32;
}
W64
Expand Down Expand Up @@ -107,7 +108,7 @@ pub fn align(buffer: &mut Vec<u8>, width: BitWidth) {
let bytes = 1 << width as u8;
let alignment = (bytes - buffer.len() % bytes) % bytes;
// Profiling reveals the loop is faster than Vec::resize.
for _ in 0..alignment as usize {
for _ in 0..alignment {
buffer.push(0);
}
}
10 changes: 8 additions & 2 deletions rust/flexbuffers/src/builder/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ impl<'a> MapBuilder<'a> {
self.builder.push_key(key);
// Nested vector.
let start = Some(self.builder.values.len());
VectorBuilder { builder: self.builder, start }
VectorBuilder {
builder: self.builder,
start,
}
}
/// Starts a nested map which that will be pushed onto this map
/// with key `key` when it is dropped.
Expand All @@ -60,7 +63,10 @@ impl<'a> MapBuilder<'a> {
self.builder.push_key(key);
// Nested map.
let start = Some(self.builder.values.len());
MapBuilder { builder: self.builder, start }
MapBuilder {
builder: self.builder,
start,
}
}
/// `end_map` sorts the map by key and writes it to the buffer. This happens anyway
/// when the map builder is dropped.
Expand Down
42 changes: 34 additions & 8 deletions rust/flexbuffers/src/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use crate::bitwidth::{align, BitWidth};
mod value;
use crate::FlexBufferType;
use bitflags::bitflags;
use std::cmp::max;
use value::{find_vector_type, store_value, Value};
mod map;
Expand All @@ -35,8 +36,12 @@ macro_rules! push_slice {
S: AsRef<[T]>,
{
let mut value = Value::$new_vec(xs.as_ref().len());
let mut width =
xs.as_ref().iter().map(|x| BitWidth::from((*x).into())).max().unwrap_or_default();
let mut width = xs
.as_ref()
.iter()
.map(|x| BitWidth::from((*x).into()))
.max()
.unwrap_or_default();
if !value.is_fixed_length_vector() {
let length = Value::UInt(xs.as_ref().len() as u64);
width = std::cmp::max(width, length.width_or_child_width());
Expand Down Expand Up @@ -131,8 +136,16 @@ impl Default for Builder {

impl<'a> Builder {
pub fn new(opts: BuilderOptions) -> Self {
let key_pool = if opts.contains(BuilderOptions::SHARE_KEYS) { Some(vec![]) } else { None };
Builder { key_pool, values: Vec::new(), buffer: Vec::new() }
let key_pool = if opts.contains(BuilderOptions::SHARE_KEYS) {
Some(vec![])
} else {
None
};
Builder {
key_pool,
values: Vec::new(),
buffer: Vec::new(),
}
}
/// Shows the internal flexbuffer. It will either be empty or populated with the most
/// recently built flexbuffer.
Expand All @@ -155,7 +168,10 @@ impl<'a> Builder {
}
}
fn push_key(&mut self, key: &str) {
debug_assert!(key.bytes().all(|b| b != b'\0'), "Keys must not have internal nulls.");
debug_assert!(
key.bytes().all(|b| b != b'\0'),
"Keys must not have internal nulls."
);
// Search key pool if there is one.
let found = self.key_pool.as_ref().map(|pool| {
pool.binary_search_by(|&CachedKey(addr)| {
Expand Down Expand Up @@ -202,7 +218,11 @@ impl<'a> Builder {
store_value(&mut self.buffer, length, width);
let address = self.buffer.len();
self.buffer.extend_from_slice(xs);
Value::Reference { fxb_type: FlexBufferType::Blob, address, child_width: width }
Value::Reference {
fxb_type: FlexBufferType::Blob,
address,
child_width: width,
}
}
fn push_str(&mut self, x: &str) {
let mut string = self.store_blob(x.as_bytes());
Expand Down Expand Up @@ -242,12 +262,18 @@ impl<'a> Builder {
/// The exact Flexbuffer vector type is dynamically inferred.
pub fn start_vector(&'a mut self) -> VectorBuilder<'a> {
self.reset();
VectorBuilder { builder: self, start: None }
VectorBuilder {
builder: self,
start: None,
}
}
/// Resets the builder and builds a new flexbuffer with a map at the root.
pub fn start_map(&'a mut self) -> MapBuilder<'a> {
self.reset();
MapBuilder { builder: self, start: None }
MapBuilder {
builder: self,
start: None,
}
}
/// Resets the builder and builds a new flexbuffer with the pushed value at the root.
pub fn build_singleton<P: Pushable>(&mut self, p: P) {
Expand Down
14 changes: 10 additions & 4 deletions rust/flexbuffers/src/builder/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,19 @@ impl FlexbufferSerializer {
Ok(())
}
fn start_vector(&mut self) {
let previous_end =
if self.nesting.is_empty() { None } else { Some(self.builder.values.len()) };
let previous_end = if self.nesting.is_empty() {
None
} else {
Some(self.builder.values.len())
};
self.nesting.push(previous_end);
}
fn start_map(&mut self) {
let previous_end =
if self.nesting.is_empty() { None } else { Some(self.builder.values.len()) };
let previous_end = if self.nesting.is_empty() {
None
} else {
Some(self.builder.values.len())
};
self.nesting.push(previous_end);
}
fn end_vector(&mut self) -> Result<(), Error> {
Expand Down
77 changes: 61 additions & 16 deletions rust/flexbuffers/src/builder/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,25 +47,67 @@ macro_rules! new_typed_vector {
let address = 0;
let child_width = W8;
match n {
2 => Value::Reference { address, child_width, fxb_type: $v2 },
3 => Value::Reference { address, child_width, fxb_type: $v3 },
4 => Value::Reference { address, child_width, fxb_type: $v4 },
_ => Value::Reference { address, child_width, fxb_type: $vn },
2 => Value::Reference {
address,
child_width,
fxb_type: $v2,
},
3 => Value::Reference {
address,
child_width,
fxb_type: $v3,
},
4 => Value::Reference {
address,
child_width,
fxb_type: $v4,
},
_ => Value::Reference {
address,
child_width,
fxb_type: $vn,
},
}
}
};
}

impl Value {
pub fn new_vector() -> Self {
Value::Reference { address: 0, child_width: W8, fxb_type: Vector }
Value::Reference {
address: 0,
child_width: W8,
fxb_type: Vector,
}
}
pub fn new_map() -> Self {
Value::Reference { address: 0, child_width: W8, fxb_type: Map }
Value::Reference {
address: 0,
child_width: W8,
fxb_type: Map,
}
}
new_typed_vector!(new_int_vector, VectorInt2, VectorInt3, VectorInt4, VectorInt);
new_typed_vector!(new_uint_vector, VectorUInt2, VectorUInt3, VectorUInt4, VectorUInt);
new_typed_vector!(new_float_vector, VectorFloat2, VectorFloat3, VectorFloat4, VectorFloat);
new_typed_vector!(
new_int_vector,
VectorInt2,
VectorInt3,
VectorInt4,
VectorInt
);
new_typed_vector!(
new_uint_vector,
VectorUInt2,
VectorUInt3,
VectorUInt4,
VectorUInt
);
new_typed_vector!(
new_float_vector,
VectorFloat2,
VectorFloat3,
VectorFloat4,
VectorFloat
);
pub fn fxb_type(&self) -> FlexBufferType {
match *self {
Value::Null => Null,
Expand All @@ -87,11 +129,7 @@ impl Value {
!self.is_inline()
}
pub fn is_key(&self) -> bool {
if let Value::Key(_) = self {
true
} else {
false
}
matches!(self, Value::Key(_))
}
pub fn is_typed_vector_or_map(&self) -> bool {
if let Value::Reference { fxb_type, .. } = self {
Expand Down Expand Up @@ -222,7 +260,11 @@ where
// Note that VectorString is deprecated for writing
_ => return Value::new_vector(),
};
Value::Reference { address: 0, child_width: W8, fxb_type: vector_type }
Value::Reference {
address: 0,
child_width: W8,
fxb_type: vector_type,
}
}

#[inline]
Expand Down Expand Up @@ -253,6 +295,9 @@ pub fn store_value(buffer: &mut Vec<u8>, mut value: Value, width: BitWidth) {
_ => unreachable!("Variant not considered: {:?}", value),
};
write_result.unwrap_or_else(|err| {
panic!("Error writing value {:?} with width {:?}: {:?}", value, width, err)
panic!(
"Error writing value {:?} with width {:?}: {:?}",
value, width, err
)
});
}
10 changes: 8 additions & 2 deletions rust/flexbuffers/src/builder/vector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,19 @@ impl<'a> VectorBuilder<'a> {
#[inline]
pub fn start_vector(&mut self) -> VectorBuilder<'_> {
let start = Some(self.builder.values.len());
VectorBuilder { builder: self.builder, start }
VectorBuilder {
builder: self.builder,
start,
}
}
/// Starts a nested map that will be pushed onto this vector when it is dropped.
#[inline]
pub fn start_map(&mut self) -> MapBuilder<'_> {
let start = Some(self.builder.values.len());
MapBuilder { builder: self.builder, start }
MapBuilder {
builder: self.builder,
start,
}
}
/// `end_vector` determines the type of the vector and writes it to the buffer.
/// This will happen automatically if the VectorBuilder is dropped.
Expand Down
9 changes: 4 additions & 5 deletions rust/flexbuffers/src/flexbuffer_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#![allow(deprecated)]

use serde_derive::{Deserialize, Serialize};

/// Represents all the valid types in a flexbuffer.
///
/// Flexbuffers supports
Expand All @@ -34,7 +37,6 @@
/// * Indirect numbers are stored as an offset instead of inline. Using
/// indirect numbers instead of their inline counterparts in maps and typed
/// vectors can reduce the minimum element width and therefore bytes used.

#[repr(u8)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, num_enum::TryFromPrimitive)]
pub enum FlexBufferType {
Expand Down Expand Up @@ -122,10 +124,7 @@ macro_rules! is_ty {
impl FlexBufferType {
/// Returns true for flexbuffer types that are stored inline.
pub fn is_inline(self) -> bool {
match self {
Null | Int | UInt | Float | Bool => true,
_ => false,
}
matches!(self, Null | Int | UInt | Float | Bool)
}
/// Returns true for flexbuffer types that are stored by offset.
pub fn is_reference(self) -> bool {
Expand Down
12 changes: 0 additions & 12 deletions rust/flexbuffers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,6 @@
// Serializable structs are Pushable
// Serde with maps - field names and type names.

// Until flat/flexbuffers is on Rust v1.42, we cannot use the previously unstable matches! macro.
#![allow(unknown_lints)]
#![allow(clippy::match_like_matches_macro)]

#[macro_use]
extern crate bitflags;
extern crate byteorder;
#[macro_use]
extern crate serde_derive;
extern crate num_enum;
extern crate serde;

mod bitwidth;
mod buffer;
mod builder;
Expand Down
11 changes: 8 additions & 3 deletions rust/flexbuffers/src/reader/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,10 @@ impl<'de> VariantAccess<'de> for Reader<&'de [u8]> {
V: Visitor<'de>,
{
let m = self.get_map()?;
visitor.visit_map(MapAccessor { keys: m.keys_vector().iter(), vals: m.iter_values() })
visitor.visit_map(MapAccessor {
keys: m.keys_vector().iter(),
vals: m.iter_values(),
})
}
}

Expand Down Expand Up @@ -187,8 +190,10 @@ impl<'de> Deserializer<'de> for Reader<&'de [u8]> {
(Blob, _) => visitor.visit_borrowed_bytes(self.get_blob()?.0),
(Map, _) => {
let m = self.get_map()?;
visitor
.visit_map(MapAccessor { keys: m.keys_vector().iter(), vals: m.iter_values() })
visitor.visit_map(MapAccessor {
keys: m.keys_vector().iter(),
vals: m.iter_values(),
})
}
(ty, _) if ty.is_vector() => visitor.visit_seq(self.as_vector().iter()),
(ty, bw) => unreachable!("TODO deserialize_any {:?} {:?}.", ty, bw),
Expand Down
Loading
Loading