Rust Flatbuffers Verifier (#6269)

* Updated comments and fixed a fundemental type error.

* bump rust flatbuffers semver

* Initial commit with verifier, need to clean up

* Verifier tested. Needs clean up and refactoring.

* Display for InvalidFlatbuffer and better errors for strings

* SimpleToVerify, some refactoring

* Combined VerifierType TableAccessorFuncBody into FollowType

* scrub todos

* Update Rust get_root functions.

There are 6 variants, with verifier options, default verifier options
and no verification "fast".

* Rename root fns

* inline

* Update to use thiserror

* fix for bad compiler

* improve error formatting

* Replace multiply with saturating_multiply

* saturating adds too

* Add docs disclaiming experimental verification system

Co-authored-by: Casper Neo <cneo@google.com>
This commit is contained in:
Casper
2020-12-07 18:37:51 -05:00
committed by GitHub
parent 9064072e8c
commit 442949bc11
21 changed files with 1861 additions and 305 deletions

View File

@@ -13,3 +13,4 @@ categories = ["encoding", "data-structures", "memory-management"]
[dependencies]
smallvec = "1.0"
bitflags = "1.2"
thiserror = "1.0"

View File

@@ -435,7 +435,7 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
// Write the vtable offset, which is the start of any Table.
// We fill its value later.
let object_revloc_to_vtable: WIPOffset<VTableWIPOffset> =
WIPOffset::new(self.push::<UOffsetT>(0xF0F0_F0F0 as UOffsetT).value());
WIPOffset::new(self.push::<UOffsetT>(0xF0F0_F0F0).value());
// Layout of the data this function will create when a new vtable is
// needed.

View File

@@ -27,16 +27,9 @@ use std::marker::PhantomData;
/// Writing a new Follow implementation primarily involves deciding whether
/// you want to return data (of the type Self::Inner) or do you want to
/// continue traversing the FlatBuffer.
pub trait Follow<'a> {
pub trait Follow<'buf> {
type Inner;
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner;
}
/// Execute a follow as a top-level function.
#[allow(dead_code)]
#[inline]
pub fn lifted_follow<'a, T: Follow<'a>>(buf: &'a [u8], loc: usize) -> T::Inner {
T::follow(buf, loc)
fn follow(buf: &'buf [u8], loc: usize) -> Self::Inner;
}
/// FollowStart wraps a Follow impl in a struct type. This can make certain

View File

@@ -0,0 +1,107 @@
/*
* Copyright 2020 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
use crate::{
Follow, ForwardsUOffset, InvalidFlatbuffer, SkipSizePrefix, Verifiable, Verifier,
VerifierOptions,
};
/// Gets the root of the Flatbuffer, verifying it first with default options.
/// Note that verification is an experimental feature and may not be maximally performant or
/// catch every error (though that is the goal). See the `_unchecked` variants for previous
/// behavior.
pub fn root<'buf, T>(data: &'buf [u8]) -> Result<T::Inner, InvalidFlatbuffer>
where
T: 'buf + Follow<'buf> + Verifiable,
{
let opts = VerifierOptions::default();
root_with_opts::<T>(&opts, data)
}
#[inline]
/// Gets the root of the Flatbuffer, verifying it first with given options.
/// Note that verification is an experimental feature and may not be maximally performant or
/// catch every error (though that is the goal). See the `_unchecked` variants for previous
/// behavior.
pub fn root_with_opts<'opts, 'buf, T>(
opts: &'opts VerifierOptions,
data: &'buf [u8],
) -> Result<T::Inner, InvalidFlatbuffer>
where
T: 'buf + Follow<'buf> + Verifiable,
{
let mut v = Verifier::new(&opts, data);
<ForwardsUOffset<T>>::run_verifier(&mut v, 0)?;
Ok(unsafe { root_unchecked::<T>(data) })
}
#[inline]
/// Gets the root of a size prefixed Flatbuffer, verifying it first with default options.
/// Note that verification is an experimental feature and may not be maximally performant or
/// catch every error (though that is the goal). See the `_unchecked` variants for previous
/// behavior.
pub fn size_prefixed_root<'buf, T>(data: &'buf [u8]) -> Result<T::Inner, InvalidFlatbuffer>
where
T: 'buf + Follow<'buf> + Verifiable,
{
let opts = VerifierOptions::default();
size_prefixed_root_with_opts::<T>(&opts, data)
}
#[inline]
/// Gets the root of a size prefixed Flatbuffer, verifying it first with given options.
/// Note that verification is an experimental feature and may not be maximally performant or
/// catch every error (though that is the goal). See the `_unchecked` variants for previous
/// behavior.
pub fn size_prefixed_root_with_opts<'opts, 'buf, T>(
opts: &'opts VerifierOptions,
data: &'buf [u8],
) -> Result<T::Inner, InvalidFlatbuffer>
where
T: 'buf + Follow<'buf> + Verifiable,
{
let mut v = Verifier::new(&opts, data);
<SkipSizePrefix<ForwardsUOffset<T>>>::run_verifier(&mut v, 0)?;
Ok(unsafe { size_prefixed_root_unchecked::<T>(data) })
}
#[inline]
/// Gets root for a trusted Flatbuffer.
/// # Safety
/// Flatbuffers accessors do not perform validation checks before accessing. Unlike the other
/// `root` functions, this does not validate the flatbuffer before returning the accessor. Users
/// must trust `data` contains a valid flatbuffer (e.g. b/c it was built by your software). Reading
/// unchecked buffers may cause panics or even UB.
pub unsafe fn root_unchecked<'buf, T>(data: &'buf [u8]) -> T::Inner
where
T: Follow<'buf> + 'buf,
{
<ForwardsUOffset<T>>::follow(data, 0)
}
#[inline]
/// Gets root for a trusted, size prefixed, Flatbuffer.
/// # Safety
/// Flatbuffers accessors do not perform validation checks before accessing. Unlike the other
/// `root` functions, this does not validate the flatbuffer before returning the accessor. Users
/// must trust `data` contains a valid flatbuffer (e.g. b/c it was built by your software). Reading
/// unchecked buffers may cause panics or even UB.
pub unsafe fn size_prefixed_root_unchecked<'buf, T>(data: &'buf [u8]) -> T::Inner
where
T: Follow<'buf> + 'buf,
{
<SkipSizePrefix<ForwardsUOffset<T>>>::follow(data, 0)
}

View File

@@ -19,26 +19,27 @@
//! A library for memory-efficient serialization of data.
//!
//! This crate provides runtime support for the FlatBuffers format in the Rust programming language.
//! To use this crate, first generate code with the `flatc` compiler, as described here: https://google.github.io/flatbuffers/
//! To use this crate, first generate code with the `flatc` compiler, as described here: <https://google.github.io/flatbuffers/>
//! Then, include that code into your project.
//! Finally, add this crate to your `Cargo.toml`.
//!
//! At this time, Rust support is experimental, and APIs may change between minor versions.
//!
//! At this time, to generate Rust code, you will need the latest `master` version of `flatc`, available from here: https://github.com/google/flatbuffers
//! At this time, to generate Rust code, you will need the latest `master` version of `flatc`, available from here: <https://github.com/google/flatbuffers>
//! (On OSX, you can install FlatBuffers from `HEAD` with the Homebrew package manager.)
mod builder;
mod endian_scalar;
mod follow;
mod get_root;
mod primitives;
mod push;
mod table;
mod vector;
mod verifier;
mod vtable;
mod vtable_writer;
pub use bitflags;
pub use crate::builder::FlatBufferBuilder;
pub use crate::endian_scalar::{
byte_swap_f32, byte_swap_f64, emplace_scalar, read_scalar, read_scalar_at, EndianScalar,
@@ -46,9 +47,15 @@ pub use crate::endian_scalar::{
pub use crate::follow::{Follow, FollowStart};
pub use crate::primitives::*;
pub use crate::push::Push;
pub use crate::table::{buffer_has_identifier, get_root, get_size_prefixed_root, Table};
pub use crate::table::{buffer_has_identifier, Table};
pub use crate::vector::{follow_cast_ref, SafeSliceAccess, Vector, VectorIter};
pub use crate::verifier::{
ErrorTraceDetail, InvalidFlatbuffer, SimpleToVerifyInSlice, Verifiable, Verifier,
VerifierOptions,
};
pub use crate::vtable::field_index_to_field_offset;
pub use bitflags;
pub use get_root::*;
// TODO(rw): Unify `create_vector` and `create_vector_direct` by using
// `Into<Vector<...>>`.

View File

@@ -55,14 +55,6 @@ impl<'a> Follow<'a> for Table<'a> {
}
}
#[inline]
pub fn get_root<'a, T: Follow<'a> + 'a>(data: &'a [u8]) -> T::Inner {
<ForwardsUOffset<T>>::follow(data, 0)
}
#[inline]
pub fn get_size_prefixed_root<'a, T: Follow<'a> + 'a>(data: &'a [u8]) -> T::Inner {
<SkipSizePrefix<ForwardsUOffset<T>>>::follow(data, 0)
}
#[inline]
pub fn buffer_has_identifier(data: &[u8], ident: &str, size_prefixed: bool) -> bool {
assert_eq!(ident.len(), FILE_IDENTIFIER_LENGTH);

View File

@@ -14,12 +14,12 @@
* limitations under the License.
*/
use std::fmt::{Debug, Formatter, Result};
use std::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator};
use std::marker::PhantomData;
use std::mem::size_of;
use std::slice::from_raw_parts;
use std::str::from_utf8_unchecked;
use std::fmt::{Debug, Result, Formatter};
use crate::endian_scalar::read_scalar_at;
#[cfg(target_endian = "little")]
@@ -32,14 +32,13 @@ pub struct Vector<'a, T: 'a>(&'a [u8], usize, PhantomData<T>);
impl<'a, T> Debug for Vector<'a, T>
where
T: 'a + Follow<'a>,
<T as Follow<'a>>::Inner : Debug
<T as Follow<'a>>::Inner: Debug,
{
fn fmt(&self, f: &mut Formatter) -> Result {
f.debug_list().entries(self.iter()).finish()
}
}
// We cannot use derive for these two impls, as it would only implement Copy
// and Clone for `T: Copy` and `T: Clone` respectively. However `Vector<'a, T>`
// can always be copied, no matter that `T` you have.
@@ -104,6 +103,8 @@ impl SafeSliceAccess for u8 {}
impl SafeSliceAccess for i8 {}
impl SafeSliceAccess for bool {}
// TODO(caspern): Get rid of this. Conditional compliation is unnecessary complexity.
// Vectors of primitives just don't work on big endian machines!!!
#[cfg(target_endian = "little")]
mod le_safe_slice_impls {
impl super::SafeSliceAccess for u16 {}

View File

@@ -0,0 +1,559 @@
use crate::follow::Follow;
use crate::{ForwardsUOffset, SOffsetT, SkipSizePrefix, UOffsetT, VOffsetT, Vector, SIZE_UOFFSET};
use std::ops::Range;
use thiserror::Error;
/// Traces the location of data errors. Not populated for Dos detecting errors.
/// Useful for MissingRequiredField and Utf8Error in particular, though
/// the other errors should not be producible by correct flatbuffers implementations.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ErrorTraceDetail {
VectorElement {
index: usize,
position: usize,
},
TableField {
field_name: &'static str,
position: usize,
},
UnionVariant {
variant: &'static str,
position: usize,
},
}
#[derive(PartialEq, Eq, Default, Debug, Clone)]
pub struct ErrorTrace(Vec<ErrorTraceDetail>);
impl std::convert::AsRef<[ErrorTraceDetail]> for ErrorTrace {
#[inline]
fn as_ref(&self) -> &[ErrorTraceDetail] {
&self.0
}
}
/// Describes how a flatuffer is invalid and, for data errors, roughly where. No extra tracing
/// information is given for DoS detecting errors since it will probably be a lot.
#[derive(Clone, Error, Debug, PartialEq, Eq)]
pub enum InvalidFlatbuffer {
#[error("Missing required field `{required}`.\n{error_trace}")]
MissingRequiredField {
required: &'static str,
error_trace: ErrorTrace,
},
#[error("Union exactly one of union discriminant (`{field_type}`) and value \
(`{field}`) are present.\n{error_trace}")]
InconsistentUnion {
field: &'static str,
field_type: &'static str,
error_trace: ErrorTrace,
},
#[error("Utf8 error for string in {range:?}: {error}\n{error_trace}")]
Utf8Error {
#[source]
error: std::str::Utf8Error,
range: Range<usize>,
error_trace: ErrorTrace,
},
#[error("String in range [{}, {}) is missing its null terminator.\n{error_trace}",
range.start, range.end)]
MissingNullTerminator {
range: Range<usize>,
error_trace: ErrorTrace,
},
#[error("Type `{unaligned_type}` at position {position} is unaligned.\n{error_trace}")]
Unaligned {
position: usize,
unaligned_type: &'static str,
error_trace: ErrorTrace,
},
#[error("Range [{}, {}) is out of bounds.\n{error_trace}", range.start, range.end)]
RangeOutOfBounds {
range: Range<usize>,
error_trace: ErrorTrace,
},
#[error("Signed offset at position {position} has value {soffset} which points out of bounds.\
\n{error_trace}")]
SignedOffsetOutOfBounds {
soffset: SOffsetT,
position: usize,
error_trace: ErrorTrace,
},
// Dos detecting errors. These do not get error traces since it will probably be very large.
#[error("Too many tables.")]
TooManyTables,
#[error("Apparent size too large.")]
ApparentSizeTooLarge,
#[error("Nested table depth limit reached.")]
DepthLimitReached,
}
impl std::fmt::Display for ErrorTrace {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
use ErrorTraceDetail::*;
for e in self.0.iter() {
match e {
VectorElement { index, position } => {
writeln!(
f,
"\twhile verifying vector element {:?} at position {:?}",
index, position
)?;
}
TableField {
field_name,
position,
} => {
writeln!(
f,
"\twhile verifying table field `{}` at position {:?}",
field_name, position
)?;
}
UnionVariant { variant, position } => {
writeln!(
f,
"\t while verifying union variant `{}` at position {:?}",
variant, position
)?;
}
}
}
Ok(())
}
}
pub type Result<T> = std::prelude::v1::Result<T, InvalidFlatbuffer>;
impl InvalidFlatbuffer {
fn new_range_oob<T>(start: usize, end: usize) -> Result<T> {
Err(Self::RangeOutOfBounds {
range: Range { start, end },
error_trace: Default::default(),
})
}
fn new_inconsistent_union<T>(field: &'static str, field_type: &'static str) -> Result<T> {
Err(Self::InconsistentUnion {
field,
field_type,
error_trace: Default::default(),
})
}
fn new_missing_required<T>(required: &'static str) -> Result<T> {
Err(Self::MissingRequiredField {
required,
error_trace: Default::default(),
})
}
}
/// Records the path to the verifier detail if the error is a data error and not a DoS error.
fn append_trace<T>(mut res: Result<T>, d: ErrorTraceDetail) -> Result<T> {
if let Err(e) = res.as_mut() {
use InvalidFlatbuffer::*;
if let MissingRequiredField { error_trace, .. }
| Unaligned { error_trace, .. }
| RangeOutOfBounds { error_trace, .. }
| InconsistentUnion { error_trace, .. }
| Utf8Error { error_trace, .. }
| MissingNullTerminator { error_trace, .. }
| SignedOffsetOutOfBounds { error_trace, .. } = e
{
error_trace.0.push(d)
}
}
res
}
/// Adds a TableField trace detail if `res` is a data error.
fn trace_field<T>(res: Result<T>, field_name: &'static str, position: usize) -> Result<T> {
append_trace(
res,
ErrorTraceDetail::TableField {
field_name,
position,
},
)
}
/// Adds a TableField trace detail if `res` is a data error.
fn trace_elem<T>(res: Result<T>, index: usize, position: usize) -> Result<T> {
append_trace(res, ErrorTraceDetail::VectorElement { index, position })
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VerifierOptions {
/// Maximum depth of nested tables allowed in a valid flatbuffer.
pub max_depth: usize,
/// Maximum number of tables allowed in a valid flatbuffer.
pub max_tables: usize,
/// Maximum "apparent" size of the message if the Flatbuffer object DAG is expanded into a
/// tree.
pub max_apparent_size: usize,
/// Ignore errors where a string is missing its null terminator.
/// This is mostly a problem if the message will be sent to a client using old c-strings.
pub ignore_missing_null_terminator: bool,
// probably want an option to ignore utf8 errors since strings come from c++
// options to error un-recognized enums and unions? possible footgun.
// Ignore nested flatbuffers, etc?
}
impl Default for VerifierOptions {
fn default() -> Self {
Self {
max_depth: 64,
max_tables: 1_000_000,
// size_ might do something different.
max_apparent_size: 1 << 31,
ignore_missing_null_terminator: false,
}
}
}
/// Carries the verification state. Should not be reused between tables.
#[derive(Debug)]
pub struct Verifier<'opts, 'buf> {
buffer: &'buf [u8],
opts: &'opts VerifierOptions,
depth: usize,
num_tables: usize,
apparent_size: usize,
}
impl<'opts, 'buf> Verifier<'opts, 'buf> {
pub fn new(opts: &'opts VerifierOptions, buffer: &'buf [u8]) -> Self {
Self {
opts,
buffer,
depth: 0,
num_tables: 0,
apparent_size: 0,
}
}
/// Resets verifier internal state.
#[inline]
pub fn reset(&mut self) {
self.depth = 0;
self.num_tables = 0;
self.num_tables = 0;
}
/// Check that there really is a T in there.
#[inline]
fn is_aligned<T>(&self, pos: usize) -> Result<()> {
// Safe because we're not dereferencing.
let p = unsafe { self.buffer.as_ptr().add(pos) };
if (p as usize) % std::mem::align_of::<T>() == 0 {
Ok(())
} else {
Err(InvalidFlatbuffer::Unaligned {
unaligned_type: std::any::type_name::<T>(),
position: pos,
error_trace: Default::default(),
})
}
}
#[inline]
fn range_in_buffer(&mut self, pos: usize, size: usize) -> Result<()> {
let end = pos.saturating_add(size);
if end > self.buffer.len() {
return InvalidFlatbuffer::new_range_oob(pos, end);
}
self.apparent_size += size;
if self.apparent_size > self.opts.max_apparent_size {
return Err(InvalidFlatbuffer::ApparentSizeTooLarge);
}
Ok(())
}
#[inline]
pub fn in_buffer<T>(&mut self, pos: usize) -> Result<()> {
self.is_aligned::<T>(pos)?;
self.range_in_buffer(pos, std::mem::size_of::<T>())
}
#[inline]
fn get_u16(&mut self, pos: usize) -> Result<u16> {
self.in_buffer::<u16>(pos)?;
Ok(u16::from_le_bytes([self.buffer[pos], self.buffer[pos + 1]]))
}
#[inline]
fn get_uoffset(&mut self, pos: usize) -> Result<UOffsetT> {
self.in_buffer::<u32>(pos)?;
Ok(u32::from_le_bytes([
self.buffer[pos],
self.buffer[pos + 1],
self.buffer[pos + 2],
self.buffer[pos + 3],
]))
}
#[inline]
fn deref_soffset(&mut self, pos: usize) -> Result<usize> {
self.in_buffer::<SOffsetT>(pos)?;
let offset = SOffsetT::from_le_bytes([
self.buffer[pos],
self.buffer[pos + 1],
self.buffer[pos + 2],
self.buffer[pos + 3],
]);
// signed offsets are subtracted.
let derefed = if offset > 0 {
pos.checked_sub(offset.abs() as usize)
} else {
pos.checked_add(offset.abs() as usize)
};
if let Some(x) = derefed {
if x < self.buffer.len() {
return Ok(x);
}
}
Err(InvalidFlatbuffer::SignedOffsetOutOfBounds {
soffset: offset,
position: pos,
error_trace: Default::default(),
})
}
#[inline]
pub fn visit_table<'ver>(
&'ver mut self,
table_pos: usize,
) -> Result<TableVerifier<'ver, 'opts, 'buf>> {
let vtable_pos = self.deref_soffset(table_pos)?;
let vtable_len = self.get_u16(vtable_pos)? as usize;
self.is_aligned::<VOffsetT>(vtable_pos.saturating_add(vtable_len))?; // i.e. vtable_len is even.
self.range_in_buffer(vtable_pos, vtable_len)?;
// Check bounds.
self.num_tables += 1;
if self.num_tables > self.opts.max_tables {
return Err(InvalidFlatbuffer::TooManyTables);
}
self.depth += 1;
if self.depth > self.opts.max_depth {
return Err(InvalidFlatbuffer::DepthLimitReached);
}
Ok(TableVerifier {
pos: table_pos,
vtable: vtable_pos,
vtable_len,
verifier: self,
})
}
/// Runs the union variant's type's verifier assuming the variant is at the given position,
/// tracing the error.
pub fn verify_union_variant<T: Verifiable>(
&mut self,
variant: &'static str,
position: usize,
) -> Result<()> {
let res = T::run_verifier(self, position);
append_trace(res, ErrorTraceDetail::UnionVariant { variant, position })
}
}
// Cache table metadata in usize so we don't have to cast types or jump around so much.
// We will visit every field anyway.
pub struct TableVerifier<'ver, 'opts, 'buf> {
// Absolute position of table in buffer
pos: usize,
// Absolute position of vtable in buffer.
vtable: usize,
// Length of vtable.
vtable_len: usize,
// Verifier struct which holds the surrounding state and options.
verifier: &'ver mut Verifier<'opts, 'buf>,
}
impl<'ver, 'opts, 'buf> TableVerifier<'ver, 'opts, 'buf> {
fn deref(&mut self, field: VOffsetT) -> Result<Option<usize>> {
let field = field as usize;
if field < self.vtable_len {
let field_offset = self.verifier.get_u16(self.vtable.saturating_add(field))?;
if field_offset > 0 {
// Field is present.
let field_pos = self.pos.saturating_add(field_offset as usize);
return Ok(Some(field_pos));
}
}
Ok(None)
}
#[inline]
pub fn visit_field<T: Verifiable>(
mut self,
field_name: &'static str,
field: VOffsetT,
required: bool,
) -> Result<Self> {
if let Some(field_pos) = self.deref(field)? {
trace_field(
T::run_verifier(self.verifier, field_pos),
field_name,
field_pos,
)?;
return Ok(self);
}
if required {
InvalidFlatbuffer::new_missing_required(field_name)
} else {
Ok(self)
}
}
#[inline]
/// Union verification is complicated. The schemas passes this function the metadata of the
/// union's key (discriminant) and value fields, and a callback. The function verifies and
/// reads the key, then invokes the callback to perform data-dependent verification.
pub fn visit_union<Key, UnionVerifier>(
mut self,
key_field_name: &'static str,
key_field_voff: VOffsetT,
val_field_name: &'static str,
val_field_voff: VOffsetT,
required: bool,
verify_union: UnionVerifier,
) -> Result<Self>
where
Key: Follow<'buf> + Verifiable,
UnionVerifier:
(std::ops::FnOnce(<Key as Follow<'buf>>::Inner, &mut Verifier, usize) -> Result<()>),
// NOTE: <Key as Follow<'buf>>::Inner == Key
{
// TODO(caspern): how to trace vtable errors?
let val_pos = self.deref(val_field_voff)?;
let key_pos = self.deref(key_field_voff)?;
match (key_pos, val_pos) {
(None, None) => {
if required {
InvalidFlatbuffer::new_missing_required(val_field_name)
} else {
Ok(self)
}
}
(Some(k), Some(v)) => {
trace_field(Key::run_verifier(self.verifier, k), key_field_name, k)?;
let discriminant = Key::follow(self.verifier.buffer, k);
trace_field(
verify_union(discriminant, self.verifier, v),
val_field_name,
v,
)?;
Ok(self)
}
_ => InvalidFlatbuffer::new_inconsistent_union(key_field_name, val_field_name),
}
}
pub fn finish(self) -> &'ver mut Verifier<'opts, 'buf> {
self.verifier.depth -= 1;
self.verifier
}
}
// Needs to be implemented for Tables and maybe structs.
// Unions need some special treatment.
pub trait Verifiable {
/// Runs the verifier for this type, assuming its at position `pos` in the verifier's buffer.
/// Should not need to be called directly.
fn run_verifier(v: &mut Verifier, pos: usize) -> Result<()>;
}
// Verify the uoffset and then pass verifier to the type being pointed to.
impl<T: Verifiable> Verifiable for ForwardsUOffset<T> {
#[inline]
fn run_verifier(v: &mut Verifier, pos: usize) -> Result<()> {
let offset = v.get_uoffset(pos)? as usize;
let next_pos = offset.saturating_add(pos);
T::run_verifier(v, next_pos)
}
}
/// Checks and returns the range containing the flatbuffers vector.
fn verify_vector_range<T>(v: &mut Verifier, pos: usize) -> Result<std::ops::Range<usize>> {
let len = v.get_uoffset(pos)? as usize;
let start = pos.saturating_add(SIZE_UOFFSET);
v.is_aligned::<T>(start)?;
let size = len.saturating_mul(std::mem::size_of::<T>());
let end = start.saturating_add(size);
v.range_in_buffer(start, size)?;
Ok(std::ops::Range { start, end })
}
pub trait SimpleToVerifyInSlice {}
impl SimpleToVerifyInSlice for bool {}
impl SimpleToVerifyInSlice for i8 {}
impl SimpleToVerifyInSlice for u8 {}
impl SimpleToVerifyInSlice for i16 {}
impl SimpleToVerifyInSlice for u16 {}
impl SimpleToVerifyInSlice for i32 {}
impl SimpleToVerifyInSlice for u32 {}
impl SimpleToVerifyInSlice for f32 {}
impl SimpleToVerifyInSlice for i64 {}
impl SimpleToVerifyInSlice for u64 {}
impl SimpleToVerifyInSlice for f64 {}
impl<T: SimpleToVerifyInSlice> Verifiable for Vector<'_, T> {
fn run_verifier(v: &mut Verifier, pos: usize) -> Result<()> {
verify_vector_range::<T>(v, pos)?;
Ok(())
}
}
impl<T: Verifiable> Verifiable for SkipSizePrefix<T> {
#[inline]
fn run_verifier(v: &mut Verifier, pos: usize) -> Result<()> {
T::run_verifier(v, pos.saturating_add(crate::SIZE_SIZEPREFIX))
}
}
impl<T: Verifiable> Verifiable for Vector<'_, ForwardsUOffset<T>> {
#[inline]
fn run_verifier(v: &mut Verifier, pos: usize) -> Result<()> {
let range = verify_vector_range::<ForwardsUOffset<T>>(v, pos)?;
let size = std::mem::size_of::<ForwardsUOffset<T>>();
for (i, element_pos) in range.step_by(size).enumerate() {
trace_elem(
<ForwardsUOffset<T>>::run_verifier(v, element_pos),
i,
element_pos,
)?;
}
Ok(())
}
}
impl<'a> Verifiable for &'a str {
#[inline]
fn run_verifier(v: &mut Verifier, pos: usize) -> Result<()> {
let range = verify_vector_range::<u8>(v, pos)?;
let has_null_terminator = v.buffer.get(range.end).map(|&b| b == 0).unwrap_or(false);
let s = std::str::from_utf8(&v.buffer[range.clone()]);
if let Err(error) = s {
return Err(InvalidFlatbuffer::Utf8Error {
error,
range,
error_trace: Default::default(),
});
}
if !v.opts.ignore_missing_null_terminator && !has_null_terminator {
return Err(InvalidFlatbuffer::MissingNullTerminator {
range,
error_trace: Default::default(),
});
}
Ok(())
}
}
// Verify VectorOfTables, Unions, Arrays, Structs...
macro_rules! impl_verifiable_for {
($T: ty) => {
impl Verifiable for $T {
#[inline]
fn run_verifier<'opts, 'buf>(v: &mut Verifier<'opts, 'buf>, pos: usize) -> Result<()> {
v.in_buffer::<$T>(pos)
}
}
};
}
impl_verifiable_for!(bool);
impl_verifiable_for!(u8);
impl_verifiable_for!(i8);
impl_verifiable_for!(u16);
impl_verifiable_for!(i16);
impl_verifiable_for!(u32);
impl_verifiable_for!(i32);
impl_verifiable_for!(f32);
impl_verifiable_for!(u64);
impl_verifiable_for!(i64);
impl_verifiable_for!(f64);

View File

@@ -77,7 +77,8 @@ impl<'a> flatbuffers::Follow<'a> for Color {
type Inner = Self;
#[inline]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self(flatbuffers::read_scalar_at::<i8>(buf, loc))
let b = flatbuffers::read_scalar_at::<i8>(buf, loc);
Self(b)
}
}
@@ -92,14 +93,27 @@ impl flatbuffers::Push for Color {
impl flatbuffers::EndianScalar for Color {
#[inline]
fn to_little_endian(self) -> Self {
Self(i8::to_le(self.0))
let b = i8::to_le(self.0);
Self(b)
}
#[inline]
fn from_little_endian(self) -> Self {
Self(i8::from_le(self.0))
let b = i8::from_le(self.0);
Self(b)
}
}
impl<'a> flatbuffers::Verifiable for Color {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
i8::run_verifier(v, pos)
}
}
impl flatbuffers::SimpleToVerifyInSlice for Color {}
#[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")]
pub const ENUM_MIN_EQUIPMENT: u8 = 0;
#[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")]
@@ -143,11 +157,13 @@ impl std::fmt::Debug for Equipment {
}
}
}
pub struct EquipmentUnionTableOffset {}
impl<'a> flatbuffers::Follow<'a> for Equipment {
type Inner = Self;
#[inline]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self(flatbuffers::read_scalar_at::<u8>(buf, loc))
let b = flatbuffers::read_scalar_at::<u8>(buf, loc);
Self(b)
}
}
@@ -162,15 +178,27 @@ impl flatbuffers::Push for Equipment {
impl flatbuffers::EndianScalar for Equipment {
#[inline]
fn to_little_endian(self) -> Self {
Self(u8::to_le(self.0))
let b = u8::to_le(self.0);
Self(b)
}
#[inline]
fn from_little_endian(self) -> Self {
Self(u8::from_le(self.0))
let b = u8::from_le(self.0);
Self(b)
}
}
pub struct EquipmentUnionTableOffset {}
impl<'a> flatbuffers::Verifiable for Equipment {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
u8::run_verifier(v, pos)
}
}
impl flatbuffers::SimpleToVerifyInSlice for Equipment {}
// struct Vec3, aligned to 4
#[repr(C, align(4))]
#[derive(Clone, Copy, PartialEq)]
@@ -189,6 +217,7 @@ impl std::fmt::Debug for Vec3 {
}
}
impl flatbuffers::SimpleToVerifyInSlice for Vec3 {}
impl flatbuffers::SafeSliceAccess for Vec3 {}
impl<'a> flatbuffers::Follow<'a> for Vec3 {
type Inner = &'a Vec3;
@@ -226,7 +255,15 @@ impl<'b> flatbuffers::Push for &'b Vec3 {
}
}
impl<'a> flatbuffers::Verifiable for Vec3 {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.in_buffer::<Self>(pos)
}
}
impl Vec3 {
pub fn new(_x: f32, _y: f32, _z: f32) -> Self {
Vec3 {
@@ -324,7 +361,7 @@ impl<'a> Monster<'a> {
}
#[inline]
pub fn weapons(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Weapon<'a>>>> {
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<Weapon<'a>>>>>(Monster::VT_WEAPONS, None)
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Weapon>>>>(Monster::VT_WEAPONS, None)
}
#[inline]
pub fn equipped_type(&self) -> Equipment {
@@ -336,7 +373,7 @@ impl<'a> Monster<'a> {
}
#[inline]
pub fn path(&self) -> Option<&'a [Vec3]> {
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<Vec3>>>(Monster::VT_PATH, None).map(|v| v.safe_slice() )
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, Vec3>>>(Monster::VT_PATH, None).map(|v| v.safe_slice())
}
#[inline]
#[allow(non_snake_case)]
@@ -350,6 +387,31 @@ impl<'a> Monster<'a> {
}
impl flatbuffers::Verifiable for Monster<'_> {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<Vec3>(&"pos", Self::VT_POS, false)?
.visit_field::<i16>(&"mana", Self::VT_MANA, false)?
.visit_field::<i16>(&"hp", Self::VT_HP, false)?
.visit_field::<flatbuffers::ForwardsUOffset<&str>>(&"name", Self::VT_NAME, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, u8>>>(&"inventory", Self::VT_INVENTORY, false)?
.visit_field::<Color>(&"color", Self::VT_COLOR, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, flatbuffers::ForwardsUOffset<Weapon>>>>(&"weapons", Self::VT_WEAPONS, false)?
.visit_union::<Equipment, _>(&"equipped_type", Self::VT_EQUIPPED_TYPE, &"equipped", Self::VT_EQUIPPED, false, |key, v, pos| {
match key {
Equipment::Weapon => v.verify_union_variant::<flatbuffers::ForwardsUOffset<Weapon>>("Equipment::Weapon", pos),
_ => Ok(()),
}
})?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, Vec3>>>(&"path", Self::VT_PATH, false)?
.finish();
Ok(())
}
}
pub struct MonsterArgs<'a> {
pub pos: Option<&'a Vec3>,
pub mana: i16,
@@ -512,6 +574,19 @@ impl<'a> Weapon<'a> {
}
}
impl flatbuffers::Verifiable for Weapon<'_> {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<flatbuffers::ForwardsUOffset<&str>>(&"name", Self::VT_NAME, false)?
.visit_field::<i16>(&"damage", Self::VT_DAMAGE, false)?
.finish();
Ok(())
}
}
pub struct WeaponArgs<'a> {
pub name: Option<flatbuffers::WIPOffset<&'a str>>,
pub damage: i16,
@@ -562,15 +637,77 @@ impl std::fmt::Debug for Weapon<'_> {
}
}
#[inline]
#[deprecated(since="1.13", note="Deprecated in favor of `root_as...` methods.")]
pub fn get_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> {
flatbuffers::get_root::<Monster<'a>>(buf)
unsafe { flatbuffers::root_unchecked::<Monster<'a>>(buf) }
}
#[inline]
#[deprecated(since="1.13", note="Deprecated in favor of `root_as...` methods.")]
pub fn get_size_prefixed_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> {
flatbuffers::get_size_prefixed_root::<Monster<'a>>(buf)
unsafe { flatbuffers::size_prefixed_root_unchecked::<Monster<'a>>(buf) }
}
#[inline]
/// Verifies that a buffer of bytes contains a `Monster`
/// and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_monster_unchecked`.
pub fn root_as_monster(buf: &[u8]) -> Result<Monster, flatbuffers::InvalidFlatbuffer> {
flatbuffers::root::<Monster>(buf)
}
#[inline]
/// Verifies that a buffer of bytes contains a size prefixed
/// `Monster` and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `size_prefixed_root_as_monster_unchecked`.
pub fn size_prefixed_root_as_monster(buf: &[u8]) -> Result<Monster, flatbuffers::InvalidFlatbuffer> {
flatbuffers::size_prefixed_root::<Monster>(buf)
}
#[inline]
/// Verifies, with the given options, that a buffer of bytes
/// contains a `Monster` and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_monster_unchecked`.
pub fn root_as_monster_with_opts<'b, 'o>(
opts: &'o flatbuffers::VerifierOptions,
buf: &'b [u8],
) -> Result<Monster<'b>, flatbuffers::InvalidFlatbuffer> {
flatbuffers::root_with_opts::<Monster<'b>>(opts, buf)
}
#[inline]
/// Verifies, with the given verifier options, that a buffer of
/// bytes contains a size prefixed `Monster` and returns
/// it. Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_monster_unchecked`.
pub fn size_prefixed_root_as_monster_with_opts<'b, 'o>(
opts: &'o flatbuffers::VerifierOptions,
buf: &'b [u8],
) -> Result<Monster<'b>, flatbuffers::InvalidFlatbuffer> {
flatbuffers::size_prefixed_root_with_opts::<Monster<'b>>(opts, buf)
}
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a Monster and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid `Monster`.
pub unsafe fn root_as_monster_unchecked(buf: &[u8]) -> Monster {
flatbuffers::root_unchecked::<Monster>(buf)
}
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a size prefixed Monster and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid size prefixed `Monster`.
pub unsafe fn size_prefixed_root_as_monster_unchecked(buf: &[u8]) -> Monster {
flatbuffers::size_prefixed_root_unchecked::<Monster>(buf)
}
#[inline]
pub fn finish_monster_buffer<'a, 'b>(
fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>,

View File

@@ -20,8 +20,7 @@ extern crate flatbuffers;
// import the generated code
#[path = "./monster_generated.rs"]
mod monster_generated;
pub use monster_generated::my_game::sample::{get_root_as_monster,
Color, Equipment,
pub use monster_generated::my_game::sample::{Color, Equipment,
Monster, MonsterArgs,
Vec3,
Weapon, WeaponArgs};
@@ -98,7 +97,7 @@ fn main() {
let buf = builder.finished_data(); // Of type `&[u8]`
// Get access to the root:
let monster = get_root_as_monster(buf);
let monster = flatbuffers::root::<Monster>(buf).unwrap();
// Get and test some scalar types from the FlatBuffer.
let hp = monster.hp();

View File

@@ -555,111 +555,93 @@ class RustGenerator : public BaseGenerator {
code_ += "pub use self::bitflags_{{ENUM_NAME_SNAKE}}::{{ENUM_NAME}};";
code_ += "";
// Generate Follow and Push so we can serialize and stuff.
code_ += "impl<'a> flatbuffers::Follow<'a> for {{ENUM_NAME}} {";
code_ += " type Inner = Self;";
code_ += " #[inline]";
code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
code_ += " let bits = flatbuffers::read_scalar_at::<{{BASE_TYPE}}>(buf, loc);";
code_ += " unsafe { Self::from_bits_unchecked(bits) }";
code_ += " }";
code_ += "}";
code_.SetValue("FROM_BASE", "unsafe { Self::from_bits_unchecked(b) }");
code_.SetValue("INTO_BASE", "self.bits()");
} else {
// Normal, c-modelled enums.
// Deprecated associated constants;
const std::string deprecation_warning =
"#[deprecated(since = \"1.13\", note = \"Use associated constants"
" instead. This will no longer be generated in 2021.\")]";
code_ += deprecation_warning;
code_ += "pub const ENUM_MIN_{{ENUM_NAME_CAPS}}: {{BASE_TYPE}}"
" = {{ENUM_MIN_BASE_VALUE}};";
code_ += deprecation_warning;
code_ += "pub const ENUM_MAX_{{ENUM_NAME_CAPS}}: {{BASE_TYPE}}"
" = {{ENUM_MAX_BASE_VALUE}};";
auto num_fields = NumToString(enum_def.size());
code_ += deprecation_warning;
code_ += "#[allow(non_camel_case_types)]";
code_ += "pub const ENUM_VALUES_{{ENUM_NAME_CAPS}}: [{{ENUM_NAME}}; " +
num_fields + "] = [";
ForAllEnumValues1(enum_def, [&](const EnumVal &ev){
code_ += " " + GetEnumValue(enum_def, ev) + ",";
});
code_ += "];";
code_ += "";
code_ += "impl flatbuffers::Push for {{ENUM_NAME}} {";
code_ += " type Output = {{ENUM_NAME}};";
code_ += " #[inline]";
code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
code_ += " flatbuffers::emplace_scalar::<{{BASE_TYPE}}>"
"(dst, self.bits());";
GenComment(enum_def.doc_comment);
code_ +=
"#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]";
code_ += "#[repr(transparent)]";
code_ += "pub struct {{ENUM_NAME}}(pub {{BASE_TYPE}});";
code_ += "#[allow(non_upper_case_globals)]";
code_ += "impl {{ENUM_NAME}} {";
ForAllEnumValues1(enum_def, [&](const EnumVal &ev){
this->GenComment(ev.doc_comment, " ");
code_ += " pub const {{VARIANT}}: Self = Self({{VALUE}});";
});
code_ += "";
// Generate Associated constants
code_ += " pub const ENUM_MIN: {{BASE_TYPE}} = {{ENUM_MIN_BASE_VALUE}};";
code_ += " pub const ENUM_MAX: {{BASE_TYPE}} = {{ENUM_MAX_BASE_VALUE}};";
code_ += " pub const ENUM_VALUES: &'static [Self] = &[";
ForAllEnumValues(enum_def, [&](){
code_ += " Self::{{VARIANT}},";
});
code_ += " ];";
code_ += " /// Returns the variant's name or \"\" if unknown.";
code_ += " pub fn variant_name(self) -> Option<&'static str> {";
code_ += " match self {";
ForAllEnumValues(enum_def, [&](){
code_ += " Self::{{VARIANT}} => Some(\"{{VARIANT}}\"),";
});
code_ += " _ => None,";
code_ += " }";
code_ += "}";
code_ += "";
code_ += "impl flatbuffers::EndianScalar for {{ENUM_NAME}} {";
code_ += " #[inline]";
code_ += " fn to_little_endian(self) -> Self {";
code_ += " let bits = {{BASE_TYPE}}::to_le(self.bits());";
code_ += " unsafe { Self::from_bits_unchecked(bits) }";
code_ += " }";
code_ += " #[inline]";
code_ += " fn from_little_endian(self) -> Self {";
code_ += " let bits = {{BASE_TYPE}}::from_le(self.bits());";
code_ += " unsafe { Self::from_bits_unchecked(bits) }";
code_ += " }";
code_ += "}";
code_ += "";
return;
// Generate Debug. Unknown variants are printed like "<UNKNOWN 42>".
code_ += "impl std::fmt::Debug for {{ENUM_NAME}} {";
code_ += " fn fmt(&self, f: &mut std::fmt::Formatter) ->"
" std::fmt::Result {";
code_ += " if let Some(name) = self.variant_name() {";
code_ += " f.write_str(name)";
code_ += " } else {";
code_ += " f.write_fmt(format_args!(\"<UNKNOWN {:?}>\", self.0))";
code_ += " }";
code_ += " }";
code_ += "}";
if (enum_def.is_union) {
// Generate tyoesafe offset(s) for unions
code_.SetValue("NAME", Name(enum_def));
code_.SetValue("UNION_OFFSET_NAME", Name(enum_def) + "UnionTableOffset");
code_ += "pub struct {{UNION_OFFSET_NAME}} {}";
}
code_.SetValue("FROM_BASE", "Self(b)");
code_.SetValue("INTO_BASE", "self.0");
}
// Deprecated associated constants;
code_ += "#[deprecated(since = \"1.13\", note = \"Use associated constants"
" instead. This will no longer be generated in 2021.\")]";
code_ += "pub const ENUM_MIN_{{ENUM_NAME_CAPS}}: {{BASE_TYPE}}"
" = {{ENUM_MIN_BASE_VALUE}};";
code_ += "#[deprecated(since = \"1.13\", note = \"Use associated constants"
" instead. This will no longer be generated in 2021.\")]";
code_ += "pub const ENUM_MAX_{{ENUM_NAME_CAPS}}: {{BASE_TYPE}}"
" = {{ENUM_MAX_BASE_VALUE}};";
auto num_fields = NumToString(enum_def.size());
code_ += "#[deprecated(since = \"1.13\", note = \"Use associated constants"
" instead. This will no longer be generated in 2021.\")]";
code_ += "#[allow(non_camel_case_types)]";
code_ += "pub const ENUM_VALUES_{{ENUM_NAME_CAPS}}: [{{ENUM_NAME}}; " +
num_fields + "] = [";
ForAllEnumValues1(enum_def, [&](const EnumVal &ev){
code_ += " " + GetEnumValue(enum_def, ev) + ",";
});
code_ += "];";
code_ += "";
GenComment(enum_def.doc_comment);
code_ +=
"#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]";
code_ += "#[repr(transparent)]";
code_ += "pub struct {{ENUM_NAME}}(pub {{BASE_TYPE}});";
code_ += "#[allow(non_upper_case_globals)]";
code_ += "impl {{ENUM_NAME}} {";
ForAllEnumValues1(enum_def, [&](const EnumVal &ev){
this->GenComment(ev.doc_comment, " ");
code_ += " pub const {{VARIANT}}: Self = Self({{VALUE}});";
});
code_ += "";
// Generate Associated constants
code_ += " pub const ENUM_MIN: {{BASE_TYPE}} = {{ENUM_MIN_BASE_VALUE}};";
code_ += " pub const ENUM_MAX: {{BASE_TYPE}} = {{ENUM_MAX_BASE_VALUE}};";
code_ += " pub const ENUM_VALUES: &'static [Self] = &[";
ForAllEnumValues(enum_def, [&](){
code_ += " Self::{{VARIANT}},";
});
code_ += " ];";
code_ += " /// Returns the variant's name or \"\" if unknown.";
code_ += " pub fn variant_name(self) -> Option<&'static str> {";
code_ += " match self {";
ForAllEnumValues(enum_def, [&](){
code_ += " Self::{{VARIANT}} => Some(\"{{VARIANT}}\"),";
});
code_ += " _ => None,";
code_ += " }";
code_ += " }";
code_ += "}";
// Generate Debug. Unknown variants are printed like "<UNKNOWN 42>".
code_ += "impl std::fmt::Debug for {{ENUM_NAME}} {";
code_ += " fn fmt(&self, f: &mut std::fmt::Formatter) ->"
" std::fmt::Result {";
code_ += " if let Some(name) = self.variant_name() {";
code_ += " f.write_str(name)";
code_ += " } else {";
code_ += " f.write_fmt(format_args!(\"<UNKNOWN {:?}>\", self.0))";
code_ += " }";
code_ += " }";
code_ += "}";
// Generate Follow and Push so we can serialize and stuff.
code_ += "impl<'a> flatbuffers::Follow<'a> for {{ENUM_NAME}} {";
code_ += " type Inner = Self;";
code_ += " #[inline]";
code_ += " fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {";
code_ += " Self(flatbuffers::read_scalar_at::<{{BASE_TYPE}}>(buf, loc))";
code_ += " let b = flatbuffers::read_scalar_at::<{{BASE_TYPE}}>(buf,"
" loc);";
code_ += " {{FROM_BASE}}";
code_ += " }";
code_ += "}";
code_ += "";
@@ -668,28 +650,36 @@ class RustGenerator : public BaseGenerator {
code_ += " #[inline]";
code_ += " fn push(&self, dst: &mut [u8], _rest: &[u8]) {";
code_ += " flatbuffers::emplace_scalar::<{{BASE_TYPE}}>"
"(dst, self.0);";
"(dst, {{INTO_BASE}});";
code_ += " }";
code_ += "}";
code_ += "";
code_ += "impl flatbuffers::EndianScalar for {{ENUM_NAME}} {";
code_ += " #[inline]";
code_ += " fn to_little_endian(self) -> Self {";
code_ += " Self({{BASE_TYPE}}::to_le(self.0))";
code_ += " let b = {{BASE_TYPE}}::to_le({{INTO_BASE}});";
code_ += " {{FROM_BASE}}";
code_ += " }";
code_ += " #[inline]";
code_ += " fn from_little_endian(self) -> Self {";
code_ += " Self({{BASE_TYPE}}::from_le(self.0))";
code_ += " let b = {{BASE_TYPE}}::from_le({{INTO_BASE}});";
code_ += " {{FROM_BASE}}";
code_ += " }";
code_ += "}";
code_ += "";
if (enum_def.is_union) {
// Generate tyoesafe offset(s) for unions
code_.SetValue("NAME", Name(enum_def));
code_.SetValue("UNION_OFFSET_NAME", Name(enum_def) + "UnionTableOffset");
code_ += "pub struct {{UNION_OFFSET_NAME}} {}";
}
// Generate verifier - deferring to the base type.
code_ += "impl<'a> flatbuffers::Verifiable for {{ENUM_NAME}} {";
code_ += " #[inline]";
code_ += " fn run_verifier<'o, 'b>(";
code_ += " v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize";
code_ += " ) -> Result<(), flatbuffers::InvalidFlatbuffer> {";
code_ += " use self::flatbuffers::Verifiable;";
code_ += " {{BASE_TYPE}}::run_verifier(v, pos)";
code_ += " }";
code_ += "}";
code_ += "";
// Enums are basically integers.
code_ += "impl flatbuffers::SimpleToVerifyInSlice for {{ENUM_NAME}} {}";
}
std::string GetFieldOffsetName(const FieldDef &field) {
@@ -1003,109 +993,60 @@ class RustGenerator : public BaseGenerator {
return "INVALID_CODE_GENERATION"; // for return analysis
}
std::string GenTableAccessorFuncBody(const FieldDef &field,
const std::string &lifetime,
const std::string &offset_prefix) {
const std::string offset_name =
offset_prefix + "::" + GetFieldOffsetName(field);
const Type &type = field.value.type;
std::string FollowType(const Type &type, const std::string &lifetime) {
// IsVector... This can be made iterative?
switch (GetFullType(field.value.type)) {
const auto WrapForwardsUOffset = [](std::string ty) -> std::string {
return "flatbuffers::ForwardsUOffset<" + ty + ">";
};
const auto WrapVector = [&](std::string ty) -> std::string {
return "flatbuffers::Vector<" + lifetime + ", " + ty + ">";
};
switch (GetFullType(type)) {
case ftInteger:
case ftFloat:
case ftBool: {
const auto typname = GetTypeBasic(type);
if (field.optional) {
return "self._tab.get::<" + typname + ">(" + offset_name + ", None)";
} else {
const auto default_value = GetDefaultScalarValue(field);
return "self._tab.get::<" + typname + ">(" + offset_name + ", Some(" +
default_value + ")).unwrap()";
}
return GetTypeBasic(type);
}
case ftStruct: {
const auto typname = WrapInNameSpace(*type.struct_def);
return AddUnwrapIfRequired(
"self._tab.get::<" + typname + ">(" + offset_name + ", None)",
field.required);
}
case ftTable: {
const auto typname = WrapInNameSpace(*type.struct_def);
return AddUnwrapIfRequired(
"self._tab.get::<flatbuffers::ForwardsUOffset<" + typname + "<" +
lifetime + ">>>(" + offset_name + ", None)",
field.required);
}
case ftUnionValue: {
return AddUnwrapIfRequired(
"self._tab.get::<flatbuffers::ForwardsUOffset<"
"flatbuffers::Table<" +
lifetime + ">>>(" + offset_name + ", None)",
field.required);
return WrapInNameSpace(*type.struct_def);
}
case ftUnionKey:
case ftEnumKey: {
const std::string typname = WrapInNameSpace(*type.enum_def);
const std::string default_value = GetDefaultScalarValue(field);
if (field.optional) {
return "self._tab.get::<" + typname + ">(" + offset_name + ", None)";
} else {
return "self._tab.get::<" + typname + ">(" + offset_name + ", Some(" +
default_value + ")).unwrap()";
}
return WrapInNameSpace(*type.enum_def);
}
case ftTable: {
const auto typname = WrapInNameSpace(*type.struct_def);
return WrapForwardsUOffset(typname);
}
case ftUnionValue: {
return WrapForwardsUOffset("flatbuffers::Table<" + lifetime + ">");
}
case ftString: {
return AddUnwrapIfRequired(
"self._tab.get::<flatbuffers::ForwardsUOffset<&str>>(" +
offset_name + ", None)",
field.required);
return WrapForwardsUOffset("&str");
}
case ftVectorOfInteger:
case ftVectorOfBool:
case ftVectorOfFloat: {
const auto typname = GetTypeBasic(type.VectorType());
std::string s =
"self._tab.get::<flatbuffers::ForwardsUOffset<"
"flatbuffers::Vector<" +
lifetime + ", " + typname + ">>>(" + offset_name + ", None)";
// single-byte values are safe to slice
if (IsOneByte(type.VectorType().base_type)) {
s += ".map(|v| v.safe_slice())";
}
return AddUnwrapIfRequired(s, field.required);
return WrapForwardsUOffset(WrapVector(typname));
}
case ftVectorOfEnumKey: {
const auto typname = WrapInNameSpace(*type.enum_def);
return AddUnwrapIfRequired(
"self._tab.get::<flatbuffers::ForwardsUOffset<"
"flatbuffers::Vector<" +
lifetime + ", " + typname + ">>>(" + offset_name + ", None)",
field.required);
const auto typname = WrapInNameSpace(*type.VectorType().enum_def);
return WrapForwardsUOffset(WrapVector(typname));
}
case ftVectorOfStruct: {
const auto typname = WrapInNameSpace(*type.struct_def);
return AddUnwrapIfRequired(
"self._tab.get::<flatbuffers::ForwardsUOffset<"
"flatbuffers::Vector<" +
typname + ">>>(" + offset_name +
", None).map(|v| v.safe_slice() )",
field.required);
return WrapForwardsUOffset(WrapVector(typname));
}
case ftVectorOfTable: {
const auto typname = WrapInNameSpace(*type.struct_def);
return AddUnwrapIfRequired(
"self._tab.get::<flatbuffers::ForwardsUOffset<"
"flatbuffers::Vector<flatbuffers::ForwardsUOffset<" +
typname + "<" + lifetime + ">>>>>(" + offset_name + ", None)",
field.required);
return WrapForwardsUOffset(WrapVector(WrapForwardsUOffset(typname)));
}
case ftVectorOfString: {
return AddUnwrapIfRequired(
"self._tab.get::<flatbuffers::ForwardsUOffset<"
"flatbuffers::Vector<flatbuffers::ForwardsUOffset<&" +
lifetime + " str>>>>(" + offset_name + ", None)",
field.required);
return WrapForwardsUOffset(WrapVector(WrapForwardsUOffset(
"&" + lifetime + " str")));
}
case ftVectorOfUnionValue: {
FLATBUFFERS_ASSERT(false && "vectors of unions are not yet supported");
@@ -1115,6 +1056,28 @@ class RustGenerator : public BaseGenerator {
return "INVALID_CODE_GENERATION"; // for return analysis
}
std::string GenTableAccessorFuncBody(const FieldDef &field,
const std::string &lifetime) {
const std::string vt_offset = GetFieldOffsetName(field);
const std::string typname = FollowType(field.value.type, lifetime);
// Default-y fields (scalars so far) are neither optional nor required.
const std::string default_value = !(field.optional || field.required) ?
"Some(" + GetDefaultScalarValue(field) + ")" : "None";
const std::string unwrap = field.optional ? "" : ".unwrap()";
const auto t = GetFullType(field.value.type);
// TODO(caspern): Shouldn't 1byte VectorOfEnumKey be slice too?
const std::string safe_slice = (
t == ftVectorOfStruct ||
((t == ftVectorOfBool || t == ftVectorOfFloat || t == ftVectorOfInteger)
&& IsOneByte(field.value.type.VectorType().base_type))
) ? ".map(|v| v.safe_slice())" : "";
return "self._tab.get::<" + typname + ">({{STRUCT_NAME}}::" +
vt_offset + ", " + default_value + ")" + safe_slice + unwrap;
}
bool TableFieldReturnsOption(const FieldDef &field) {
if (field.optional) return true;
switch (GetFullType(field.value.type)) {
@@ -1272,17 +1235,14 @@ class RustGenerator : public BaseGenerator {
// pub fn name(&'a self) -> user_facing_type {
// self._tab.get::<internal_type>(offset, defaultval).unwrap()
// }
const auto offset_prefix = Name(struct_def);
ForAllTableFields(struct_def, [&](const FieldDef &field) {
code_.SetValue("RETURN_TYPE",
GenTableAccessorFuncReturnType(field, "'a"));
code_.SetValue("FUNC_BODY",
GenTableAccessorFuncBody(field, "'a", offset_prefix));
this->GenComment(field.doc_comment, " ");
code_ += " #[inline]";
code_ += " pub fn {{FIELD_NAME}}(&self) -> {{RETURN_TYPE}} {";
code_ += " {{FUNC_BODY}}";
code_ += " " + GenTableAccessorFuncBody(field, "'a");
code_ += " }";
// Generate a comparison function for this field if it is a key.
@@ -1369,6 +1329,50 @@ class RustGenerator : public BaseGenerator {
code_ += "}"; // End of table impl.
code_ += "";
// Generate Verifier;
code_ += "impl flatbuffers::Verifiable for {{STRUCT_NAME}}<'_> {";
code_ += " #[inline]";
code_ += " fn run_verifier<'o, 'b>(";
code_ += " v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize";
code_ += " ) -> Result<(), flatbuffers::InvalidFlatbuffer> {";
code_ += " use self::flatbuffers::Verifiable;";
code_ += " v.visit_table(pos)?\\";
// Escape newline and insert it onthe next line so we can end the builder
// with a nice semicolon.
ForAllTableFields(struct_def, [&](const FieldDef &field) {
if (GetFullType(field.value.type) == ftUnionKey) return;
code_.SetValue("IS_REQ", field.required ? "true" : "false");
if (GetFullType(field.value.type) != ftUnionValue) {
// All types besides unions.
code_.SetValue("TY", FollowType(field.value.type, "'_"));
code_ += "\n .visit_field::<{{TY}}>(&\"{{FIELD_NAME}}\", "
"Self::{{OFFSET_NAME}}, {{IS_REQ}})?\\";
return;
}
// Unions.
EnumDef &union_def = *field.value.type.enum_def;
code_.SetValue("UNION_TYPE", Name(union_def));
code_ += "\n .visit_union::<{{UNION_TYPE}}, _>("
"&\"{{FIELD_NAME}}_type\", Self::{{OFFSET_NAME}}_TYPE, "
"&\"{{FIELD_NAME}}\", Self::{{OFFSET_NAME}}, {{IS_REQ}}, "
"|key, v, pos| {";
code_ += " match key {";
ForAllUnionVariantsBesidesNone(union_def, [&](const EnumVal &unused) {
(void) unused;
code_ += " {{U_ELEMENT_ENUM_TYPE}} => v.verify_union_variant::"
"<flatbuffers::ForwardsUOffset<{{U_ELEMENT_TABLE_TYPE}}>>("
"\"{{U_ELEMENT_ENUM_TYPE}}\", pos),";
});
code_ += " _ => Ok(()),";
code_ += " }";
code_ += " })?\\";
});
code_ += "\n .finish();";
code_ += " Ok(())";
code_ += " }";
code_ += "}";
// Generate an args struct:
code_.SetValue("MAYBE_LT",
TableBuilderArgsNeedsLifetime(struct_def) ? "<'a>" : "");
@@ -1538,22 +1542,105 @@ class RustGenerator : public BaseGenerator {
// The root datatype accessors:
code_ += "#[inline]";
code_ += "#[deprecated(since=\"1.13\", "
"note=\"Deprecated in favor of `root_as...` methods.\")]";
code_ +=
"pub fn get_root_as_{{STRUCT_NAME_SNAKECASE}}<'a>(buf: &'a [u8])"
" -> {{STRUCT_NAME}}<'a> {";
code_ += " flatbuffers::get_root::<{{STRUCT_NAME}}<'a>>(buf)";
code_ += " unsafe { flatbuffers::root_unchecked::<{{STRUCT_NAME}}"
"<'a>>(buf) }";
code_ += "}";
code_ += "";
code_ += "#[inline]";
code_ += "#[deprecated(since=\"1.13\", "
"note=\"Deprecated in favor of `root_as...` methods.\")]";
code_ +=
"pub fn get_size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}"
"<'a>(buf: &'a [u8]) -> {{STRUCT_NAME}}<'a> {";
code_ +=
" flatbuffers::get_size_prefixed_root::<{{STRUCT_NAME}}<'a>>"
"(buf)";
" unsafe { flatbuffers::size_prefixed_root_unchecked::<{{STRUCT_NAME}}"
"<'a>>(buf) }";
code_ += "}";
code_ += "";
// Default verifier root fns.
code_ += "#[inline]";
code_ += "/// Verifies that a buffer of bytes contains a `{{STRUCT_NAME}}`";
code_ += "/// and returns it.";
code_ += "/// Note that verification is still experimental and may not";
code_ += "/// catch every error, or be maximally performant. For the";
code_ += "/// previous, unchecked, behavior use";
code_ += "/// `root_as_{{STRUCT_NAME_SNAKECASE}}_unchecked`.";
code_ += "pub fn root_as_{{STRUCT_NAME_SNAKECASE}}(buf: &[u8]) "
"-> Result<{{STRUCT_NAME}}, flatbuffers::InvalidFlatbuffer> {";
code_ += " flatbuffers::root::<{{STRUCT_NAME}}>(buf)";
code_ += "}";
code_ += "#[inline]";
code_ += "/// Verifies that a buffer of bytes contains a size prefixed";
code_ += "/// `{{STRUCT_NAME}}` and returns it.";
code_ += "/// Note that verification is still experimental and may not";
code_ += "/// catch every error, or be maximally performant. For the";
code_ += "/// previous, unchecked, behavior use";
code_ += "/// `size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}_unchecked`.";
code_ += "pub fn size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}"
"(buf: &[u8]) -> Result<{{STRUCT_NAME}}, "
"flatbuffers::InvalidFlatbuffer> {";
code_ += " flatbuffers::size_prefixed_root::<{{STRUCT_NAME}}>(buf)";
code_ += "}";
// Verifier with options root fns.
code_ += "#[inline]";
code_ += "/// Verifies, with the given options, that a buffer of bytes";
code_ += "/// contains a `{{STRUCT_NAME}}` and returns it.";
code_ += "/// Note that verification is still experimental and may not";
code_ += "/// catch every error, or be maximally performant. For the";
code_ += "/// previous, unchecked, behavior use";
code_ += "/// `root_as_{{STRUCT_NAME_SNAKECASE}}_unchecked`.";
code_ += "pub fn root_as_{{STRUCT_NAME_SNAKECASE}}_with_opts<'b, 'o>(";
code_ += " opts: &'o flatbuffers::VerifierOptions,";
code_ += " buf: &'b [u8],";
code_ += ") -> Result<{{STRUCT_NAME}}<'b>, flatbuffers::InvalidFlatbuffer>"
" {";
code_ += " flatbuffers::root_with_opts::<{{STRUCT_NAME}}<'b>>(opts, buf)";
code_ += "}";
code_ += "#[inline]";
code_ += "/// Verifies, with the given verifier options, that a buffer of";
code_ += "/// bytes contains a size prefixed `{{STRUCT_NAME}}` and returns";
code_ += "/// it. Note that verification is still experimental and may not";
code_ += "/// catch every error, or be maximally performant. For the";
code_ += "/// previous, unchecked, behavior use";
code_ += "/// `root_as_{{STRUCT_NAME_SNAKECASE}}_unchecked`.";
code_ += "pub fn size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}_with_opts"
"<'b, 'o>(";
code_ += " opts: &'o flatbuffers::VerifierOptions,";
code_ += " buf: &'b [u8],";
code_ += ") -> Result<{{STRUCT_NAME}}<'b>, flatbuffers::InvalidFlatbuffer>"
" {";
code_ += " flatbuffers::size_prefixed_root_with_opts::<{{STRUCT_NAME}}"
"<'b>>(opts, buf)";
code_ += "}";
// Unchecked root fns.
code_ += "#[inline]";
code_ += "/// Assumes, without verification, that a buffer of bytes "
"contains a {{STRUCT_NAME}} and returns it.";
code_ += "/// # Safety";
code_ += "/// Callers must trust the given bytes do indeed contain a valid"
" `{{STRUCT_NAME}}`.";
code_ += "pub unsafe fn root_as_{{STRUCT_NAME_SNAKECASE}}_unchecked"
"(buf: &[u8]) -> {{STRUCT_NAME}} {";
code_ += " flatbuffers::root_unchecked::<{{STRUCT_NAME}}>(buf)";
code_ += "}";
code_ += "#[inline]";
code_ += "/// Assumes, without verification, that a buffer of bytes "
"contains a size prefixed {{STRUCT_NAME}} and returns it.";
code_ += "/// # Safety";
code_ += "/// Callers must trust the given bytes do indeed contain a valid"
" size prefixed `{{STRUCT_NAME}}`.";
code_ += "pub unsafe fn size_prefixed_root_as_{{STRUCT_NAME_SNAKECASE}}"
"_unchecked(buf: &[u8]) -> {{STRUCT_NAME}} {";
code_ += " flatbuffers::size_prefixed_root_unchecked::<{{STRUCT_NAME}}>"
"(buf)";
code_ += "}";
if (parser_.file_identifier_.length()) {
// Declare the identifier
@@ -1697,6 +1784,7 @@ class RustGenerator : public BaseGenerator {
// Generate impls for SafeSliceAccess (because all structs are endian-safe),
// Follow for the value type, Follow for the reference type, Push for the
// value type, and Push for the reference type.
code_ += "impl flatbuffers::SimpleToVerifyInSlice for {{STRUCT_NAME}} {}";
code_ += "impl flatbuffers::SafeSliceAccess for {{STRUCT_NAME}} {}";
code_ += "impl<'a> flatbuffers::Follow<'a> for {{STRUCT_NAME}} {";
code_ += " type Inner = &'a {{STRUCT_NAME}};";
@@ -1738,7 +1826,18 @@ class RustGenerator : public BaseGenerator {
code_ += " }";
code_ += "}";
code_ += "";
code_ += "";
// Generate verifier: Structs are simple so presence and alignment are
// all that need to be checked.
code_ += "impl<'a> flatbuffers::Verifiable for {{STRUCT_NAME}} {";
code_ += " #[inline]";
code_ += " fn run_verifier<'o, 'b>(";
code_ += " v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize";
code_ += " ) -> Result<(), flatbuffers::InvalidFlatbuffer> {";
code_ += " use self::flatbuffers::Verifiable;";
code_ += " v.in_buffer::<Self>(pos)";
code_ += " }";
code_ += "}";
// Generate a constructor that takes all fields as arguments.
code_ += "impl {{STRUCT_NAME}} {";

View File

@@ -45,10 +45,22 @@ impl<'a> TableA<'a> {
#[inline]
pub fn b(&self) -> Option<my_game::other_name_space::TableB<'a>> {
self._tab.get::<flatbuffers::ForwardsUOffset<my_game::other_name_space::TableB<'a>>>(TableA::VT_B, None)
self._tab.get::<flatbuffers::ForwardsUOffset<my_game::other_name_space::TableB>>(TableA::VT_B, None)
}
}
impl flatbuffers::Verifiable for TableA<'_> {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<flatbuffers::ForwardsUOffset<my_game::other_name_space::TableB>>(&"b", Self::VT_B, false)?
.finish();
Ok(())
}
}
pub struct TableAArgs<'a> {
pub b: Option<flatbuffers::WIPOffset<my_game::other_name_space::TableB<'a>>>,
}

View File

@@ -72,7 +72,8 @@ impl<'a> flatbuffers::Follow<'a> for FromInclude {
type Inner = Self;
#[inline]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self(flatbuffers::read_scalar_at::<i64>(buf, loc))
let b = flatbuffers::read_scalar_at::<i64>(buf, loc);
Self(b)
}
}
@@ -87,14 +88,27 @@ impl flatbuffers::Push for FromInclude {
impl flatbuffers::EndianScalar for FromInclude {
#[inline]
fn to_little_endian(self) -> Self {
Self(i64::to_le(self.0))
let b = i64::to_le(self.0);
Self(b)
}
#[inline]
fn from_little_endian(self) -> Self {
Self(i64::from_le(self.0))
let b = i64::from_le(self.0);
Self(b)
}
}
impl<'a> flatbuffers::Verifiable for FromInclude {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
i64::run_verifier(v, pos)
}
}
impl flatbuffers::SimpleToVerifyInSlice for FromInclude {}
// struct Unused, aligned to 4
#[repr(C, align(4))]
#[derive(Clone, Copy, PartialEq)]
@@ -109,6 +123,7 @@ impl std::fmt::Debug for Unused {
}
}
impl flatbuffers::SimpleToVerifyInSlice for Unused {}
impl flatbuffers::SafeSliceAccess for Unused {}
impl<'a> flatbuffers::Follow<'a> for Unused {
type Inner = &'a Unused;
@@ -146,7 +161,15 @@ impl<'b> flatbuffers::Push for &'b Unused {
}
}
impl<'a> flatbuffers::Verifiable for Unused {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.in_buffer::<Self>(pos)
}
}
impl Unused {
pub fn new(_a: i32) -> Self {
Unused {
@@ -194,10 +217,22 @@ impl<'a> TableB<'a> {
#[inline]
pub fn a(&self) -> Option<super::super::TableA<'a>> {
self._tab.get::<flatbuffers::ForwardsUOffset<super::super::TableA<'a>>>(TableB::VT_A, None)
self._tab.get::<flatbuffers::ForwardsUOffset<super::super::TableA>>(TableB::VT_A, None)
}
}
impl flatbuffers::Verifiable for TableB<'_> {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<flatbuffers::ForwardsUOffset<super::super::TableA>>(&"a", Self::VT_A, false)?
.finish();
Ok(())
}
}
pub struct TableBArgs<'a> {
pub a: Option<flatbuffers::WIPOffset<super::super::TableA<'a>>>,
}

View File

@@ -58,6 +58,17 @@ impl<'a> InParentNamespace<'a> {
}
impl flatbuffers::Verifiable for InParentNamespace<'_> {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.finish();
Ok(())
}
}
pub struct InParentNamespaceArgs {
}
impl<'a> Default for InParentNamespaceArgs {
@@ -140,6 +151,17 @@ impl<'a> Monster<'a> {
}
impl flatbuffers::Verifiable for Monster<'_> {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.finish();
Ok(())
}
}
pub struct MonsterArgs {
}
impl<'a> Default for MonsterArgs {
@@ -208,8 +230,8 @@ impl<'a> flatbuffers::Follow<'a> for Color {
type Inner = Self;
#[inline]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
let bits = flatbuffers::read_scalar_at::<u8>(buf, loc);
unsafe { Self::from_bits_unchecked(bits) }
let b = flatbuffers::read_scalar_at::<u8>(buf, loc);
unsafe { Self::from_bits_unchecked(b) }
}
}
@@ -224,16 +246,27 @@ impl flatbuffers::Push for Color {
impl flatbuffers::EndianScalar for Color {
#[inline]
fn to_little_endian(self) -> Self {
let bits = u8::to_le(self.bits());
unsafe { Self::from_bits_unchecked(bits) }
let b = u8::to_le(self.bits());
unsafe { Self::from_bits_unchecked(b) }
}
#[inline]
fn from_little_endian(self) -> Self {
let bits = u8::from_le(self.bits());
unsafe { Self::from_bits_unchecked(bits) }
let b = u8::from_le(self.bits());
unsafe { Self::from_bits_unchecked(b) }
}
}
impl<'a> flatbuffers::Verifiable for Color {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
u8::run_verifier(v, pos)
}
}
impl flatbuffers::SimpleToVerifyInSlice for Color {}
#[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")]
pub const ENUM_MIN_RACE: i8 = -1;
#[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")]
@@ -289,7 +322,8 @@ impl<'a> flatbuffers::Follow<'a> for Race {
type Inner = Self;
#[inline]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self(flatbuffers::read_scalar_at::<i8>(buf, loc))
let b = flatbuffers::read_scalar_at::<i8>(buf, loc);
Self(b)
}
}
@@ -304,14 +338,27 @@ impl flatbuffers::Push for Race {
impl flatbuffers::EndianScalar for Race {
#[inline]
fn to_little_endian(self) -> Self {
Self(i8::to_le(self.0))
let b = i8::to_le(self.0);
Self(b)
}
#[inline]
fn from_little_endian(self) -> Self {
Self(i8::from_le(self.0))
let b = i8::from_le(self.0);
Self(b)
}
}
impl<'a> flatbuffers::Verifiable for Race {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
i8::run_verifier(v, pos)
}
}
impl flatbuffers::SimpleToVerifyInSlice for Race {}
#[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")]
pub const ENUM_MIN_ANY: u8 = 0;
#[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")]
@@ -363,11 +410,13 @@ impl std::fmt::Debug for Any {
}
}
}
pub struct AnyUnionTableOffset {}
impl<'a> flatbuffers::Follow<'a> for Any {
type Inner = Self;
#[inline]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self(flatbuffers::read_scalar_at::<u8>(buf, loc))
let b = flatbuffers::read_scalar_at::<u8>(buf, loc);
Self(b)
}
}
@@ -382,15 +431,27 @@ impl flatbuffers::Push for Any {
impl flatbuffers::EndianScalar for Any {
#[inline]
fn to_little_endian(self) -> Self {
Self(u8::to_le(self.0))
let b = u8::to_le(self.0);
Self(b)
}
#[inline]
fn from_little_endian(self) -> Self {
Self(u8::from_le(self.0))
let b = u8::from_le(self.0);
Self(b)
}
}
pub struct AnyUnionTableOffset {}
impl<'a> flatbuffers::Verifiable for Any {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
u8::run_verifier(v, pos)
}
}
impl flatbuffers::SimpleToVerifyInSlice for Any {}
#[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")]
pub const ENUM_MIN_ANY_UNIQUE_ALIASES: u8 = 0;
#[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")]
@@ -442,11 +503,13 @@ impl std::fmt::Debug for AnyUniqueAliases {
}
}
}
pub struct AnyUniqueAliasesUnionTableOffset {}
impl<'a> flatbuffers::Follow<'a> for AnyUniqueAliases {
type Inner = Self;
#[inline]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self(flatbuffers::read_scalar_at::<u8>(buf, loc))
let b = flatbuffers::read_scalar_at::<u8>(buf, loc);
Self(b)
}
}
@@ -461,15 +524,27 @@ impl flatbuffers::Push for AnyUniqueAliases {
impl flatbuffers::EndianScalar for AnyUniqueAliases {
#[inline]
fn to_little_endian(self) -> Self {
Self(u8::to_le(self.0))
let b = u8::to_le(self.0);
Self(b)
}
#[inline]
fn from_little_endian(self) -> Self {
Self(u8::from_le(self.0))
let b = u8::from_le(self.0);
Self(b)
}
}
pub struct AnyUniqueAliasesUnionTableOffset {}
impl<'a> flatbuffers::Verifiable for AnyUniqueAliases {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
u8::run_verifier(v, pos)
}
}
impl flatbuffers::SimpleToVerifyInSlice for AnyUniqueAliases {}
#[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")]
pub const ENUM_MIN_ANY_AMBIGUOUS_ALIASES: u8 = 0;
#[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")]
@@ -521,11 +596,13 @@ impl std::fmt::Debug for AnyAmbiguousAliases {
}
}
}
pub struct AnyAmbiguousAliasesUnionTableOffset {}
impl<'a> flatbuffers::Follow<'a> for AnyAmbiguousAliases {
type Inner = Self;
#[inline]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self(flatbuffers::read_scalar_at::<u8>(buf, loc))
let b = flatbuffers::read_scalar_at::<u8>(buf, loc);
Self(b)
}
}
@@ -540,15 +617,27 @@ impl flatbuffers::Push for AnyAmbiguousAliases {
impl flatbuffers::EndianScalar for AnyAmbiguousAliases {
#[inline]
fn to_little_endian(self) -> Self {
Self(u8::to_le(self.0))
let b = u8::to_le(self.0);
Self(b)
}
#[inline]
fn from_little_endian(self) -> Self {
Self(u8::from_le(self.0))
let b = u8::from_le(self.0);
Self(b)
}
}
pub struct AnyAmbiguousAliasesUnionTableOffset {}
impl<'a> flatbuffers::Verifiable for AnyAmbiguousAliases {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
u8::run_verifier(v, pos)
}
}
impl flatbuffers::SimpleToVerifyInSlice for AnyAmbiguousAliases {}
// struct Test, aligned to 2
#[repr(C, align(2))]
#[derive(Clone, Copy, PartialEq)]
@@ -566,6 +655,7 @@ impl std::fmt::Debug for Test {
}
}
impl flatbuffers::SimpleToVerifyInSlice for Test {}
impl flatbuffers::SafeSliceAccess for Test {}
impl<'a> flatbuffers::Follow<'a> for Test {
type Inner = &'a Test;
@@ -603,7 +693,15 @@ impl<'b> flatbuffers::Push for &'b Test {
}
}
impl<'a> flatbuffers::Verifiable for Test {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.in_buffer::<Self>(pos)
}
}
impl Test {
pub fn new(_a: i16, _b: i8) -> Self {
Test {
@@ -652,6 +750,7 @@ impl std::fmt::Debug for Vec3 {
}
}
impl flatbuffers::SimpleToVerifyInSlice for Vec3 {}
impl flatbuffers::SafeSliceAccess for Vec3 {}
impl<'a> flatbuffers::Follow<'a> for Vec3 {
type Inner = &'a Vec3;
@@ -689,7 +788,15 @@ impl<'b> flatbuffers::Push for &'b Vec3 {
}
}
impl<'a> flatbuffers::Verifiable for Vec3 {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.in_buffer::<Self>(pos)
}
}
impl Vec3 {
pub fn new(_x: f32, _y: f32, _z: f32, _test1: f64, _test2: Color, _test3: &Test) -> Self {
Vec3 {
@@ -745,6 +852,7 @@ impl std::fmt::Debug for Ability {
}
}
impl flatbuffers::SimpleToVerifyInSlice for Ability {}
impl flatbuffers::SafeSliceAccess for Ability {}
impl<'a> flatbuffers::Follow<'a> for Ability {
type Inner = &'a Ability;
@@ -782,7 +890,15 @@ impl<'b> flatbuffers::Push for &'b Ability {
}
}
impl<'a> flatbuffers::Verifiable for Ability {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.in_buffer::<Self>(pos)
}
}
impl Ability {
pub fn new(_id: u32, _distance: u32) -> Self {
Ability {
@@ -856,6 +972,18 @@ impl<'a> TestSimpleTableWithEnum<'a> {
}
}
impl flatbuffers::Verifiable for TestSimpleTableWithEnum<'_> {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<Color>(&"color", Self::VT_COLOR, false)?
.finish();
Ok(())
}
}
pub struct TestSimpleTableWithEnumArgs {
pub color: Color,
}
@@ -953,6 +1081,20 @@ impl<'a> Stat<'a> {
}
}
impl flatbuffers::Verifiable for Stat<'_> {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<flatbuffers::ForwardsUOffset<&str>>(&"id", Self::VT_ID, false)?
.visit_field::<i64>(&"val", Self::VT_VAL, false)?
.visit_field::<u16>(&"count", Self::VT_COUNT, false)?
.finish();
Ok(())
}
}
pub struct StatArgs<'a> {
pub id: Option<flatbuffers::WIPOffset<&'a str>>,
pub val: i64,
@@ -1062,6 +1204,18 @@ impl<'a> Referrable<'a> {
}
}
impl flatbuffers::Verifiable for Referrable<'_> {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<u64>(&"id", Self::VT_ID, false)?
.finish();
Ok(())
}
}
pub struct ReferrableArgs {
pub id: u64,
}
@@ -1282,21 +1436,21 @@ impl<'a> Monster<'a> {
}
#[inline]
pub fn test4(&self) -> Option<&'a [Test]> {
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<Test>>>(Monster::VT_TEST4, None).map(|v| v.safe_slice() )
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, Test>>>(Monster::VT_TEST4, None).map(|v| v.safe_slice())
}
#[inline]
pub fn testarrayofstring(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<&'a str>>> {
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<&'a str>>>>(Monster::VT_TESTARRAYOFSTRING, None)
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<&'a str>>>>(Monster::VT_TESTARRAYOFSTRING, None)
}
/// an example documentation comment: this will end up in the generated code
/// multiline too
#[inline]
pub fn testarrayoftables(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Monster<'a>>>> {
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<Monster<'a>>>>>(Monster::VT_TESTARRAYOFTABLES, None)
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Monster>>>>(Monster::VT_TESTARRAYOFTABLES, None)
}
#[inline]
pub fn enemy(&self) -> Option<Monster<'a>> {
self._tab.get::<flatbuffers::ForwardsUOffset<Monster<'a>>>(Monster::VT_ENEMY, None)
self._tab.get::<flatbuffers::ForwardsUOffset<Monster>>(Monster::VT_ENEMY, None)
}
#[inline]
pub fn testnestedflatbuffer(&self) -> Option<&'a [u8]> {
@@ -1310,7 +1464,7 @@ impl<'a> Monster<'a> {
}
#[inline]
pub fn testempty(&self) -> Option<Stat<'a>> {
self._tab.get::<flatbuffers::ForwardsUOffset<Stat<'a>>>(Monster::VT_TESTEMPTY, None)
self._tab.get::<flatbuffers::ForwardsUOffset<Stat>>(Monster::VT_TESTEMPTY, None)
}
#[inline]
pub fn testbool(&self) -> bool {
@@ -1366,11 +1520,11 @@ impl<'a> Monster<'a> {
}
#[inline]
pub fn testarrayofstring2(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<&'a str>>> {
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<&'a str>>>>(Monster::VT_TESTARRAYOFSTRING2, None)
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<&'a str>>>>(Monster::VT_TESTARRAYOFSTRING2, None)
}
#[inline]
pub fn testarrayofsortedstruct(&self) -> Option<&'a [Ability]> {
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<Ability>>>(Monster::VT_TESTARRAYOFSORTEDSTRUCT, None).map(|v| v.safe_slice() )
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, Ability>>>(Monster::VT_TESTARRAYOFSORTEDSTRUCT, None).map(|v| v.safe_slice())
}
#[inline]
pub fn flex(&self) -> Option<&'a [u8]> {
@@ -1378,7 +1532,7 @@ impl<'a> Monster<'a> {
}
#[inline]
pub fn test5(&self) -> Option<&'a [Test]> {
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<Test>>>(Monster::VT_TEST5, None).map(|v| v.safe_slice() )
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, Test>>>(Monster::VT_TEST5, None).map(|v| v.safe_slice())
}
#[inline]
pub fn vector_of_longs(&self) -> Option<flatbuffers::Vector<'a, i64>> {
@@ -1390,11 +1544,11 @@ impl<'a> Monster<'a> {
}
#[inline]
pub fn parent_namespace_test(&self) -> Option<super::InParentNamespace<'a>> {
self._tab.get::<flatbuffers::ForwardsUOffset<super::InParentNamespace<'a>>>(Monster::VT_PARENT_NAMESPACE_TEST, None)
self._tab.get::<flatbuffers::ForwardsUOffset<super::InParentNamespace>>(Monster::VT_PARENT_NAMESPACE_TEST, None)
}
#[inline]
pub fn vector_of_referrables(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Referrable<'a>>>> {
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<Referrable<'a>>>>>(Monster::VT_VECTOR_OF_REFERRABLES, None)
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Referrable>>>>(Monster::VT_VECTOR_OF_REFERRABLES, None)
}
#[inline]
pub fn single_weak_reference(&self) -> u64 {
@@ -1406,7 +1560,7 @@ impl<'a> Monster<'a> {
}
#[inline]
pub fn vector_of_strong_referrables(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Referrable<'a>>>> {
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<Referrable<'a>>>>>(Monster::VT_VECTOR_OF_STRONG_REFERRABLES, None)
self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Referrable>>>>(Monster::VT_VECTOR_OF_STRONG_REFERRABLES, None)
}
#[inline]
pub fn co_owning_reference(&self) -> u64 {
@@ -1550,6 +1704,84 @@ impl<'a> Monster<'a> {
}
impl flatbuffers::Verifiable for Monster<'_> {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<Vec3>(&"pos", Self::VT_POS, false)?
.visit_field::<i16>(&"mana", Self::VT_MANA, false)?
.visit_field::<i16>(&"hp", Self::VT_HP, false)?
.visit_field::<flatbuffers::ForwardsUOffset<&str>>(&"name", Self::VT_NAME, true)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, u8>>>(&"inventory", Self::VT_INVENTORY, false)?
.visit_field::<Color>(&"color", Self::VT_COLOR, false)?
.visit_union::<Any, _>(&"test_type", Self::VT_TEST_TYPE, &"test", Self::VT_TEST, false, |key, v, pos| {
match key {
Any::Monster => v.verify_union_variant::<flatbuffers::ForwardsUOffset<Monster>>("Any::Monster", pos),
Any::TestSimpleTableWithEnum => v.verify_union_variant::<flatbuffers::ForwardsUOffset<TestSimpleTableWithEnum>>("Any::TestSimpleTableWithEnum", pos),
Any::MyGame_Example2_Monster => v.verify_union_variant::<flatbuffers::ForwardsUOffset<super::example_2::Monster>>("Any::MyGame_Example2_Monster", pos),
_ => Ok(()),
}
})?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, Test>>>(&"test4", Self::VT_TEST4, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, flatbuffers::ForwardsUOffset<&'_ str>>>>(&"testarrayofstring", Self::VT_TESTARRAYOFSTRING, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, flatbuffers::ForwardsUOffset<Monster>>>>(&"testarrayoftables", Self::VT_TESTARRAYOFTABLES, false)?
.visit_field::<flatbuffers::ForwardsUOffset<Monster>>(&"enemy", Self::VT_ENEMY, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, u8>>>(&"testnestedflatbuffer", Self::VT_TESTNESTEDFLATBUFFER, false)?
.visit_field::<flatbuffers::ForwardsUOffset<Stat>>(&"testempty", Self::VT_TESTEMPTY, false)?
.visit_field::<bool>(&"testbool", Self::VT_TESTBOOL, false)?
.visit_field::<i32>(&"testhashs32_fnv1", Self::VT_TESTHASHS32_FNV1, false)?
.visit_field::<u32>(&"testhashu32_fnv1", Self::VT_TESTHASHU32_FNV1, false)?
.visit_field::<i64>(&"testhashs64_fnv1", Self::VT_TESTHASHS64_FNV1, false)?
.visit_field::<u64>(&"testhashu64_fnv1", Self::VT_TESTHASHU64_FNV1, false)?
.visit_field::<i32>(&"testhashs32_fnv1a", Self::VT_TESTHASHS32_FNV1A, false)?
.visit_field::<u32>(&"testhashu32_fnv1a", Self::VT_TESTHASHU32_FNV1A, false)?
.visit_field::<i64>(&"testhashs64_fnv1a", Self::VT_TESTHASHS64_FNV1A, false)?
.visit_field::<u64>(&"testhashu64_fnv1a", Self::VT_TESTHASHU64_FNV1A, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, bool>>>(&"testarrayofbools", Self::VT_TESTARRAYOFBOOLS, false)?
.visit_field::<f32>(&"testf", Self::VT_TESTF, false)?
.visit_field::<f32>(&"testf2", Self::VT_TESTF2, false)?
.visit_field::<f32>(&"testf3", Self::VT_TESTF3, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, flatbuffers::ForwardsUOffset<&'_ str>>>>(&"testarrayofstring2", Self::VT_TESTARRAYOFSTRING2, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, Ability>>>(&"testarrayofsortedstruct", Self::VT_TESTARRAYOFSORTEDSTRUCT, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, u8>>>(&"flex", Self::VT_FLEX, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, Test>>>(&"test5", Self::VT_TEST5, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, i64>>>(&"vector_of_longs", Self::VT_VECTOR_OF_LONGS, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, f64>>>(&"vector_of_doubles", Self::VT_VECTOR_OF_DOUBLES, false)?
.visit_field::<flatbuffers::ForwardsUOffset<super::InParentNamespace>>(&"parent_namespace_test", Self::VT_PARENT_NAMESPACE_TEST, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, flatbuffers::ForwardsUOffset<Referrable>>>>(&"vector_of_referrables", Self::VT_VECTOR_OF_REFERRABLES, false)?
.visit_field::<u64>(&"single_weak_reference", Self::VT_SINGLE_WEAK_REFERENCE, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, u64>>>(&"vector_of_weak_references", Self::VT_VECTOR_OF_WEAK_REFERENCES, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, flatbuffers::ForwardsUOffset<Referrable>>>>(&"vector_of_strong_referrables", Self::VT_VECTOR_OF_STRONG_REFERRABLES, false)?
.visit_field::<u64>(&"co_owning_reference", Self::VT_CO_OWNING_REFERENCE, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, u64>>>(&"vector_of_co_owning_references", Self::VT_VECTOR_OF_CO_OWNING_REFERENCES, false)?
.visit_field::<u64>(&"non_owning_reference", Self::VT_NON_OWNING_REFERENCE, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, u64>>>(&"vector_of_non_owning_references", Self::VT_VECTOR_OF_NON_OWNING_REFERENCES, false)?
.visit_union::<AnyUniqueAliases, _>(&"any_unique_type", Self::VT_ANY_UNIQUE_TYPE, &"any_unique", Self::VT_ANY_UNIQUE, false, |key, v, pos| {
match key {
AnyUniqueAliases::M => v.verify_union_variant::<flatbuffers::ForwardsUOffset<Monster>>("AnyUniqueAliases::M", pos),
AnyUniqueAliases::TS => v.verify_union_variant::<flatbuffers::ForwardsUOffset<TestSimpleTableWithEnum>>("AnyUniqueAliases::TS", pos),
AnyUniqueAliases::M2 => v.verify_union_variant::<flatbuffers::ForwardsUOffset<super::example_2::Monster>>("AnyUniqueAliases::M2", pos),
_ => Ok(()),
}
})?
.visit_union::<AnyAmbiguousAliases, _>(&"any_ambiguous_type", Self::VT_ANY_AMBIGUOUS_TYPE, &"any_ambiguous", Self::VT_ANY_AMBIGUOUS, false, |key, v, pos| {
match key {
AnyAmbiguousAliases::M1 => v.verify_union_variant::<flatbuffers::ForwardsUOffset<Monster>>("AnyAmbiguousAliases::M1", pos),
AnyAmbiguousAliases::M2 => v.verify_union_variant::<flatbuffers::ForwardsUOffset<Monster>>("AnyAmbiguousAliases::M2", pos),
AnyAmbiguousAliases::M3 => v.verify_union_variant::<flatbuffers::ForwardsUOffset<Monster>>("AnyAmbiguousAliases::M3", pos),
_ => Ok(()),
}
})?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, Color>>>(&"vector_of_enums", Self::VT_VECTOR_OF_ENUMS, false)?
.visit_field::<Race>(&"signed_enum", Self::VT_SIGNED_ENUM, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, u8>>>(&"testrequirednestedflatbuffer", Self::VT_TESTREQUIREDNESTEDFLATBUFFER, false)?
.finish();
Ok(())
}
}
pub struct MonsterArgs<'a> {
pub pos: Option<&'a Vec3>,
pub mana: i16,
@@ -2116,6 +2348,29 @@ impl<'a> TypeAliases<'a> {
}
}
impl flatbuffers::Verifiable for TypeAliases<'_> {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<i8>(&"i8_", Self::VT_I8_, false)?
.visit_field::<u8>(&"u8_", Self::VT_U8_, false)?
.visit_field::<i16>(&"i16_", Self::VT_I16_, false)?
.visit_field::<u16>(&"u16_", Self::VT_U16_, false)?
.visit_field::<i32>(&"i32_", Self::VT_I32_, false)?
.visit_field::<u32>(&"u32_", Self::VT_U32_, false)?
.visit_field::<i64>(&"i64_", Self::VT_I64_, false)?
.visit_field::<u64>(&"u64_", Self::VT_U64_, false)?
.visit_field::<f32>(&"f32_", Self::VT_F32_, false)?
.visit_field::<f64>(&"f64_", Self::VT_F64_, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, i8>>>(&"v8", Self::VT_V8, false)?
.visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, f64>>>(&"vf64", Self::VT_VF64, false)?
.finish();
Ok(())
}
}
pub struct TypeAliasesArgs<'a> {
pub i8_: i8,
pub u8_: u8,
@@ -2236,15 +2491,77 @@ impl std::fmt::Debug for TypeAliases<'_> {
}
}
#[inline]
#[deprecated(since="1.13", note="Deprecated in favor of `root_as...` methods.")]
pub fn get_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> {
flatbuffers::get_root::<Monster<'a>>(buf)
unsafe { flatbuffers::root_unchecked::<Monster<'a>>(buf) }
}
#[inline]
#[deprecated(since="1.13", note="Deprecated in favor of `root_as...` methods.")]
pub fn get_size_prefixed_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> {
flatbuffers::get_size_prefixed_root::<Monster<'a>>(buf)
unsafe { flatbuffers::size_prefixed_root_unchecked::<Monster<'a>>(buf) }
}
#[inline]
/// Verifies that a buffer of bytes contains a `Monster`
/// and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_monster_unchecked`.
pub fn root_as_monster(buf: &[u8]) -> Result<Monster, flatbuffers::InvalidFlatbuffer> {
flatbuffers::root::<Monster>(buf)
}
#[inline]
/// Verifies that a buffer of bytes contains a size prefixed
/// `Monster` and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `size_prefixed_root_as_monster_unchecked`.
pub fn size_prefixed_root_as_monster(buf: &[u8]) -> Result<Monster, flatbuffers::InvalidFlatbuffer> {
flatbuffers::size_prefixed_root::<Monster>(buf)
}
#[inline]
/// Verifies, with the given options, that a buffer of bytes
/// contains a `Monster` and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_monster_unchecked`.
pub fn root_as_monster_with_opts<'b, 'o>(
opts: &'o flatbuffers::VerifierOptions,
buf: &'b [u8],
) -> Result<Monster<'b>, flatbuffers::InvalidFlatbuffer> {
flatbuffers::root_with_opts::<Monster<'b>>(opts, buf)
}
#[inline]
/// Verifies, with the given verifier options, that a buffer of
/// bytes contains a size prefixed `Monster` and returns
/// it. Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_monster_unchecked`.
pub fn size_prefixed_root_as_monster_with_opts<'b, 'o>(
opts: &'o flatbuffers::VerifierOptions,
buf: &'b [u8],
) -> Result<Monster<'b>, flatbuffers::InvalidFlatbuffer> {
flatbuffers::size_prefixed_root_with_opts::<Monster<'b>>(opts, buf)
}
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a Monster and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid `Monster`.
pub unsafe fn root_as_monster_unchecked(buf: &[u8]) -> Monster {
flatbuffers::root_unchecked::<Monster>(buf)
}
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a size prefixed Monster and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid size prefixed `Monster`.
pub unsafe fn size_prefixed_root_as_monster_unchecked(buf: &[u8]) -> Monster {
flatbuffers::size_prefixed_root_unchecked::<Monster>(buf)
}
pub const MONSTER_IDENTIFIER: &str = "MONS";
#[inline]

View File

@@ -77,7 +77,8 @@ impl<'a> flatbuffers::Follow<'a> for EnumInNestedNS {
type Inner = Self;
#[inline]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self(flatbuffers::read_scalar_at::<i8>(buf, loc))
let b = flatbuffers::read_scalar_at::<i8>(buf, loc);
Self(b)
}
}
@@ -92,14 +93,27 @@ impl flatbuffers::Push for EnumInNestedNS {
impl flatbuffers::EndianScalar for EnumInNestedNS {
#[inline]
fn to_little_endian(self) -> Self {
Self(i8::to_le(self.0))
let b = i8::to_le(self.0);
Self(b)
}
#[inline]
fn from_little_endian(self) -> Self {
Self(i8::from_le(self.0))
let b = i8::from_le(self.0);
Self(b)
}
}
impl<'a> flatbuffers::Verifiable for EnumInNestedNS {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
i8::run_verifier(v, pos)
}
}
impl flatbuffers::SimpleToVerifyInSlice for EnumInNestedNS {}
// struct StructInNestedNS, aligned to 4
#[repr(C, align(4))]
#[derive(Clone, Copy, PartialEq)]
@@ -116,6 +130,7 @@ impl std::fmt::Debug for StructInNestedNS {
}
}
impl flatbuffers::SimpleToVerifyInSlice for StructInNestedNS {}
impl flatbuffers::SafeSliceAccess for StructInNestedNS {}
impl<'a> flatbuffers::Follow<'a> for StructInNestedNS {
type Inner = &'a StructInNestedNS;
@@ -153,7 +168,15 @@ impl<'b> flatbuffers::Push for &'b StructInNestedNS {
}
}
impl<'a> flatbuffers::Verifiable for StructInNestedNS {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.in_buffer::<Self>(pos)
}
}
impl StructInNestedNS {
pub fn new(_a: i32, _b: i32) -> Self {
StructInNestedNS {
@@ -217,6 +240,18 @@ impl<'a> TableInNestedNS<'a> {
}
}
impl flatbuffers::Verifiable for TableInNestedNS<'_> {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<i32>(&"foo", Self::VT_FOO, false)?
.finish();
Ok(())
}
}
pub struct TableInNestedNSArgs {
pub foo: i32,
}

View File

@@ -63,7 +63,7 @@ impl<'a> TableInFirstNS<'a> {
#[inline]
pub fn foo_table(&self) -> Option<namespace_b::TableInNestedNS<'a>> {
self._tab.get::<flatbuffers::ForwardsUOffset<namespace_b::TableInNestedNS<'a>>>(TableInFirstNS::VT_FOO_TABLE, None)
self._tab.get::<flatbuffers::ForwardsUOffset<namespace_b::TableInNestedNS>>(TableInFirstNS::VT_FOO_TABLE, None)
}
#[inline]
pub fn foo_enum(&self) -> namespace_b::EnumInNestedNS {
@@ -75,6 +75,20 @@ impl<'a> TableInFirstNS<'a> {
}
}
impl flatbuffers::Verifiable for TableInFirstNS<'_> {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<flatbuffers::ForwardsUOffset<namespace_b::TableInNestedNS>>(&"foo_table", Self::VT_FOO_TABLE, false)?
.visit_field::<namespace_b::EnumInNestedNS>(&"foo_enum", Self::VT_FOO_ENUM, false)?
.visit_field::<namespace_b::StructInNestedNS>(&"foo_struct", Self::VT_FOO_STRUCT, false)?
.finish();
Ok(())
}
}
pub struct TableInFirstNSArgs<'a> {
pub foo_table: Option<flatbuffers::WIPOffset<namespace_b::TableInNestedNS<'a>>>,
pub foo_enum: namespace_b::EnumInNestedNS,
@@ -170,10 +184,22 @@ impl<'a> SecondTableInA<'a> {
#[inline]
pub fn refer_to_c(&self) -> Option<super::namespace_c::TableInC<'a>> {
self._tab.get::<flatbuffers::ForwardsUOffset<super::namespace_c::TableInC<'a>>>(SecondTableInA::VT_REFER_TO_C, None)
self._tab.get::<flatbuffers::ForwardsUOffset<super::namespace_c::TableInC>>(SecondTableInA::VT_REFER_TO_C, None)
}
}
impl flatbuffers::Verifiable for SecondTableInA<'_> {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<flatbuffers::ForwardsUOffset<super::namespace_c::TableInC>>(&"refer_to_c", Self::VT_REFER_TO_C, false)?
.finish();
Ok(())
}
}
pub struct SecondTableInAArgs<'a> {
pub refer_to_c: Option<flatbuffers::WIPOffset<super::namespace_c::TableInC<'a>>>,
}
@@ -269,14 +295,27 @@ impl<'a> TableInC<'a> {
#[inline]
pub fn refer_to_a1(&self) -> Option<super::namespace_a::TableInFirstNS<'a>> {
self._tab.get::<flatbuffers::ForwardsUOffset<super::namespace_a::TableInFirstNS<'a>>>(TableInC::VT_REFER_TO_A1, None)
self._tab.get::<flatbuffers::ForwardsUOffset<super::namespace_a::TableInFirstNS>>(TableInC::VT_REFER_TO_A1, None)
}
#[inline]
pub fn refer_to_a2(&self) -> Option<super::namespace_a::SecondTableInA<'a>> {
self._tab.get::<flatbuffers::ForwardsUOffset<super::namespace_a::SecondTableInA<'a>>>(TableInC::VT_REFER_TO_A2, None)
self._tab.get::<flatbuffers::ForwardsUOffset<super::namespace_a::SecondTableInA>>(TableInC::VT_REFER_TO_A2, None)
}
}
impl flatbuffers::Verifiable for TableInC<'_> {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<flatbuffers::ForwardsUOffset<super::namespace_a::TableInFirstNS>>(&"refer_to_a1", Self::VT_REFER_TO_A1, false)?
.visit_field::<flatbuffers::ForwardsUOffset<super::namespace_a::SecondTableInA>>(&"refer_to_a2", Self::VT_REFER_TO_A2, false)?
.finish();
Ok(())
}
}
pub struct TableInCArgs<'a> {
pub refer_to_a1: Option<flatbuffers::WIPOffset<super::namespace_a::TableInFirstNS<'a>>>,
pub refer_to_a2: Option<flatbuffers::WIPOffset<super::namespace_a::SecondTableInA<'a>>>,

View File

@@ -69,7 +69,8 @@ impl<'a> flatbuffers::Follow<'a> for OptionalByte {
type Inner = Self;
#[inline]
fn follow(buf: &'a [u8], loc: usize) -> Self::Inner {
Self(flatbuffers::read_scalar_at::<i8>(buf, loc))
let b = flatbuffers::read_scalar_at::<i8>(buf, loc);
Self(b)
}
}
@@ -84,14 +85,27 @@ impl flatbuffers::Push for OptionalByte {
impl flatbuffers::EndianScalar for OptionalByte {
#[inline]
fn to_little_endian(self) -> Self {
Self(i8::to_le(self.0))
let b = i8::to_le(self.0);
Self(b)
}
#[inline]
fn from_little_endian(self) -> Self {
Self(i8::from_le(self.0))
let b = i8::from_le(self.0);
Self(b)
}
}
impl<'a> flatbuffers::Verifiable for OptionalByte {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
i8::run_verifier(v, pos)
}
}
impl flatbuffers::SimpleToVerifyInSlice for OptionalByte {}
pub enum ScalarStuffOffset {}
#[derive(Copy, Clone, PartialEq)]
@@ -341,6 +355,53 @@ impl<'a> ScalarStuff<'a> {
}
}
impl flatbuffers::Verifiable for ScalarStuff<'_> {
#[inline]
fn run_verifier<'o, 'b>(
v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize
) -> Result<(), flatbuffers::InvalidFlatbuffer> {
use self::flatbuffers::Verifiable;
v.visit_table(pos)?
.visit_field::<i8>(&"just_i8", Self::VT_JUST_I8, false)?
.visit_field::<i8>(&"maybe_i8", Self::VT_MAYBE_I8, false)?
.visit_field::<i8>(&"default_i8", Self::VT_DEFAULT_I8, false)?
.visit_field::<u8>(&"just_u8", Self::VT_JUST_U8, false)?
.visit_field::<u8>(&"maybe_u8", Self::VT_MAYBE_U8, false)?
.visit_field::<u8>(&"default_u8", Self::VT_DEFAULT_U8, false)?
.visit_field::<i16>(&"just_i16", Self::VT_JUST_I16, false)?
.visit_field::<i16>(&"maybe_i16", Self::VT_MAYBE_I16, false)?
.visit_field::<i16>(&"default_i16", Self::VT_DEFAULT_I16, false)?
.visit_field::<u16>(&"just_u16", Self::VT_JUST_U16, false)?
.visit_field::<u16>(&"maybe_u16", Self::VT_MAYBE_U16, false)?
.visit_field::<u16>(&"default_u16", Self::VT_DEFAULT_U16, false)?
.visit_field::<i32>(&"just_i32", Self::VT_JUST_I32, false)?
.visit_field::<i32>(&"maybe_i32", Self::VT_MAYBE_I32, false)?
.visit_field::<i32>(&"default_i32", Self::VT_DEFAULT_I32, false)?
.visit_field::<u32>(&"just_u32", Self::VT_JUST_U32, false)?
.visit_field::<u32>(&"maybe_u32", Self::VT_MAYBE_U32, false)?
.visit_field::<u32>(&"default_u32", Self::VT_DEFAULT_U32, false)?
.visit_field::<i64>(&"just_i64", Self::VT_JUST_I64, false)?
.visit_field::<i64>(&"maybe_i64", Self::VT_MAYBE_I64, false)?
.visit_field::<i64>(&"default_i64", Self::VT_DEFAULT_I64, false)?
.visit_field::<u64>(&"just_u64", Self::VT_JUST_U64, false)?
.visit_field::<u64>(&"maybe_u64", Self::VT_MAYBE_U64, false)?
.visit_field::<u64>(&"default_u64", Self::VT_DEFAULT_U64, false)?
.visit_field::<f32>(&"just_f32", Self::VT_JUST_F32, false)?
.visit_field::<f32>(&"maybe_f32", Self::VT_MAYBE_F32, false)?
.visit_field::<f32>(&"default_f32", Self::VT_DEFAULT_F32, false)?
.visit_field::<f64>(&"just_f64", Self::VT_JUST_F64, false)?
.visit_field::<f64>(&"maybe_f64", Self::VT_MAYBE_F64, false)?
.visit_field::<f64>(&"default_f64", Self::VT_DEFAULT_F64, false)?
.visit_field::<bool>(&"just_bool", Self::VT_JUST_BOOL, false)?
.visit_field::<bool>(&"maybe_bool", Self::VT_MAYBE_BOOL, false)?
.visit_field::<bool>(&"default_bool", Self::VT_DEFAULT_BOOL, false)?
.visit_field::<OptionalByte>(&"just_enum", Self::VT_JUST_ENUM, false)?
.visit_field::<OptionalByte>(&"maybe_enum", Self::VT_MAYBE_ENUM, false)?
.visit_field::<OptionalByte>(&"default_enum", Self::VT_DEFAULT_ENUM, false)?
.finish();
Ok(())
}
}
pub struct ScalarStuffArgs {
pub just_i8: i8,
pub maybe_i8: Option<i8>,
@@ -629,15 +690,77 @@ impl std::fmt::Debug for ScalarStuff<'_> {
}
}
#[inline]
#[deprecated(since="1.13", note="Deprecated in favor of `root_as...` methods.")]
pub fn get_root_as_scalar_stuff<'a>(buf: &'a [u8]) -> ScalarStuff<'a> {
flatbuffers::get_root::<ScalarStuff<'a>>(buf)
unsafe { flatbuffers::root_unchecked::<ScalarStuff<'a>>(buf) }
}
#[inline]
#[deprecated(since="1.13", note="Deprecated in favor of `root_as...` methods.")]
pub fn get_size_prefixed_root_as_scalar_stuff<'a>(buf: &'a [u8]) -> ScalarStuff<'a> {
flatbuffers::get_size_prefixed_root::<ScalarStuff<'a>>(buf)
unsafe { flatbuffers::size_prefixed_root_unchecked::<ScalarStuff<'a>>(buf) }
}
#[inline]
/// Verifies that a buffer of bytes contains a `ScalarStuff`
/// and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_scalar_stuff_unchecked`.
pub fn root_as_scalar_stuff(buf: &[u8]) -> Result<ScalarStuff, flatbuffers::InvalidFlatbuffer> {
flatbuffers::root::<ScalarStuff>(buf)
}
#[inline]
/// Verifies that a buffer of bytes contains a size prefixed
/// `ScalarStuff` and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `size_prefixed_root_as_scalar_stuff_unchecked`.
pub fn size_prefixed_root_as_scalar_stuff(buf: &[u8]) -> Result<ScalarStuff, flatbuffers::InvalidFlatbuffer> {
flatbuffers::size_prefixed_root::<ScalarStuff>(buf)
}
#[inline]
/// Verifies, with the given options, that a buffer of bytes
/// contains a `ScalarStuff` and returns it.
/// Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_scalar_stuff_unchecked`.
pub fn root_as_scalar_stuff_with_opts<'b, 'o>(
opts: &'o flatbuffers::VerifierOptions,
buf: &'b [u8],
) -> Result<ScalarStuff<'b>, flatbuffers::InvalidFlatbuffer> {
flatbuffers::root_with_opts::<ScalarStuff<'b>>(opts, buf)
}
#[inline]
/// Verifies, with the given verifier options, that a buffer of
/// bytes contains a size prefixed `ScalarStuff` and returns
/// it. Note that verification is still experimental and may not
/// catch every error, or be maximally performant. For the
/// previous, unchecked, behavior use
/// `root_as_scalar_stuff_unchecked`.
pub fn size_prefixed_root_as_scalar_stuff_with_opts<'b, 'o>(
opts: &'o flatbuffers::VerifierOptions,
buf: &'b [u8],
) -> Result<ScalarStuff<'b>, flatbuffers::InvalidFlatbuffer> {
flatbuffers::size_prefixed_root_with_opts::<ScalarStuff<'b>>(opts, buf)
}
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a ScalarStuff and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid `ScalarStuff`.
pub unsafe fn root_as_scalar_stuff_unchecked(buf: &[u8]) -> ScalarStuff {
flatbuffers::root_unchecked::<ScalarStuff>(buf)
}
#[inline]
/// Assumes, without verification, that a buffer of bytes contains a size prefixed ScalarStuff and returns it.
/// # Safety
/// Callers must trust the given bytes do indeed contain a valid size prefixed `ScalarStuff`.
pub unsafe fn size_prefixed_root_as_scalar_stuff_unchecked(buf: &[u8]) -> ScalarStuff {
flatbuffers::size_prefixed_root_unchecked::<ScalarStuff>(buf)
}
pub const SCALAR_STUFF_IDENTIFIER: &str = "NULL";
#[inline]

View File

@@ -131,7 +131,7 @@ fn main() {
// do many reads, forcing them to execute by using assert_eq:
{
let m = my_game::example::get_root_as_monster(buf);
let m = unsafe { my_game::example::root_as_monster_unchecked(buf) };
assert_eq!(80, m.hp());
assert_eq!(150, m.mana());
assert_eq!("MyMonster", m.name());

View File

@@ -20,7 +20,7 @@ fn main() {
let mut buf = Vec::new();
f.read_to_end(&mut buf).expect("file reading failed");
let monster = my_game::example::get_root_as_monster(&buf[..]);
let monster = my_game::example::root_as_monster(&buf[..]).unwrap();
println!("{}", monster.hp()); // `80`
println!("{}", monster.mana()); // default value of `150`
println!("{:?}", monster.name()); // Some("MyMonster")

View File

@@ -177,9 +177,9 @@ fn serialized_example_is_accessible_and_correct(bytes: &[u8], identifier_require
}
let m = if size_prefixed {
my_game::example::get_size_prefixed_root_as_monster(bytes)
my_game::example::size_prefixed_root_as_monster(bytes).unwrap()
} else {
my_game::example::get_root_as_monster(bytes)
my_game::example::root_as_monster(bytes).unwrap()
};
check_eq!(m.hp(), 80)?;
@@ -245,6 +245,106 @@ fn builder_collapses_into_vec() {
serialized_example_is_accessible_and_correct(&backing_buf[head..], true, false).unwrap();
}
#[test]
fn verifier_one_byte_errors_do_not_crash() {
let mut b = flatbuffers::FlatBufferBuilder::new();
create_serialized_example_with_library_code(&mut b);
let mut badbuf = b.finished_data().to_vec();
// If the verifier says a buffer is okay then using it won't cause a crash.
// We use write_fmt since Debug visits all the fields - but there's no need to store anything.
struct ForgetfulWriter;
use std::fmt::Write;
impl Write for ForgetfulWriter {
fn write_str(&mut self, _: &str) -> Result<(), std::fmt::Error> {
Ok(())
}
}
let mut w = ForgetfulWriter;
for d in 1..=255u8 {
for i in 0..badbuf.len() {
let orig = badbuf[i];
badbuf[i] = badbuf[i].wrapping_add(d);
if let Ok(m) = flatbuffers::root::<my_game::example::Monster>(&badbuf) {
w.write_fmt(format_args!("{:?}", m)).unwrap()
}
badbuf[i] = orig;
}
}
}
#[test]
fn verifier_too_many_tables() {
use my_game::example::*;
let b = &mut flatbuffers::FlatBufferBuilder::new();
let r = Referrable::create(b, &ReferrableArgs { id: 42 });
let rs = b.create_vector(&vec![r; 500]);
let name = Some(b.create_string("foo"));
let m = Monster::create(b, &MonsterArgs {
vector_of_referrables: Some(rs),
name, // required field.
..Default::default()
});
b.finish(m, None);
let data = b.finished_data();
let mut opts = flatbuffers::VerifierOptions::default();
opts.max_tables = 500;
let res = flatbuffers::root_with_opts::<Monster>(&opts, data);
assert_eq!(res.unwrap_err(), flatbuffers::InvalidFlatbuffer::TooManyTables);
opts.max_tables += 2;
assert!(flatbuffers::root_with_opts::<Monster>(&opts, data).is_ok());
}
#[test]
fn verifier_apparent_size_too_large() {
use my_game::example::*;
let b = &mut flatbuffers::FlatBufferBuilder::new();
let name = Some(b.create_string("foo"));
// String amplification attack.
let s = b.create_string(&(std::iter::repeat("X").take(1000).collect::<String>()));
let testarrayofstring = Some(b.create_vector(&vec![s; 1000]));
let m = Monster::create(b, &MonsterArgs {
testarrayofstring,
name, // required field.
..Default::default()
});
b.finish(m, None);
let data = b.finished_data();
assert!(data.len() < 5100); // est 4000 for the vector + 1000 for the string + 100 overhead.
let mut opts = flatbuffers::VerifierOptions::default();
opts.max_apparent_size = 1_000_000;
let res = flatbuffers::root_with_opts::<Monster>(&opts, data);
assert_eq!(res.unwrap_err(), flatbuffers::InvalidFlatbuffer::ApparentSizeTooLarge);
opts.max_apparent_size += 20_000;
assert!(flatbuffers::root_with_opts::<Monster>(&opts, data).is_ok());
}
#[test]
fn verifier_in_too_deep() {
use my_game::example::*;
let b = &mut flatbuffers::FlatBufferBuilder::new();
let name = Some(b.create_string("foo"));
let mut prev_monster = None;
for _ in 0..11 {
prev_monster = Some(Monster::create(b, &MonsterArgs {
enemy: prev_monster,
name, // required field.
..Default::default()
}));
};
b.finish(prev_monster.unwrap(), None);
let mut opts = flatbuffers::VerifierOptions::default();
opts.max_depth = 10;
let data = b.finished_data();
let res = flatbuffers::root_with_opts::<Monster>(&opts, data);
assert_eq!(res.unwrap_err(), flatbuffers::InvalidFlatbuffer::DepthLimitReached);
opts.max_depth += 1;
assert!(flatbuffers::root_with_opts::<Monster>(&opts, data).is_ok());
}
#[cfg(test)]
mod generated_constants {
extern crate flatbuffers;
@@ -316,7 +416,7 @@ mod lifetime_correctness {
let slice: &[u8] = &buf;
let slice: &'static [u8] = unsafe { mem::transmute(slice) };
// make sure values retrieved from the 'static buffer are themselves 'static
let monster: my_game::example::Monster<'static> = my_game::example::get_root_as_monster(slice);
let monster: my_game::example::Monster<'static> = my_game::example::root_as_monster(slice).unwrap();
// this line should compile:
let name: Option<&'static str> = monster._tab.get::<flatbuffers::ForwardsUOffset<&str>>(my_game::example::Monster::VT_NAME, None);
assert_eq!(name, Some("MyMonster"));
@@ -334,7 +434,7 @@ mod lifetime_correctness {
fn table_object_self_lifetime_in_closure() {
// This test is designed to ensure that lifetimes for temporary intermediate tables aren't inflated beyond where the need to be.
let buf = load_file("../monsterdata_test.mon").expect("missing monsterdata_test.mon");
let monster = my_game::example::get_root_as_monster(&buf);
let monster = my_game::example::root_as_monster(&buf).unwrap();
let enemy: Option<my_game::example::Monster> = monster.enemy();
// This line won't compile if "self" is required to live for the lifetime of buf above as the borrow disappears at the end of the closure.
let enemy_of_my_enemy = enemy.map(|e| {
@@ -357,7 +457,7 @@ mod roundtrip_generated_code {
fn build_mon<'a, 'b>(builder: &'a mut flatbuffers::FlatBufferBuilder, args: &'b my_game::example::MonsterArgs) -> my_game::example::Monster<'a> {
let mon = my_game::example::Monster::create(builder, &args);
my_game::example::finish_monster_buffer(builder, mon);
my_game::example::get_root_as_monster(builder.finished_data())
my_game::example::root_as_monster(builder.finished_data()).unwrap()
}
#[test]
@@ -437,7 +537,7 @@ mod roundtrip_generated_code {
my_game::example::finish_monster_buffer(b, outer);
}
let mon = my_game::example::get_root_as_monster(b.finished_data());
let mon = my_game::example::root_as_monster(b.finished_data()).unwrap();
assert_eq!(mon.name(), "bar");
assert_eq!(mon.test_type(), my_game::example::Any::Monster);
assert_eq!(my_game::example::Monster::init_from_table(mon.test().unwrap()).name(),
@@ -473,7 +573,7 @@ mod roundtrip_generated_code {
my_game::example::finish_monster_buffer(b, outer);
}
let mon = my_game::example::get_root_as_monster(b.finished_data());
let mon = my_game::example::root_as_monster(b.finished_data()).unwrap();
assert_eq!(mon.name(), "bar");
assert_eq!(mon.enemy().unwrap().name(), "foo");
}
@@ -503,7 +603,7 @@ mod roundtrip_generated_code {
my_game::example::finish_monster_buffer(b, outer);
}
let mon = my_game::example::get_root_as_monster(b.finished_data());
let mon = my_game::example::root_as_monster(b.finished_data()).unwrap();
assert_eq!(mon.name(), "bar");
assert_eq!(mon.testempty().unwrap().id(), Some("foo"));
}
@@ -540,12 +640,12 @@ mod roundtrip_generated_code {
b1
};
let m = my_game::example::get_root_as_monster(b1.finished_data());
let m = my_game::example::root_as_monster(b1.finished_data()).unwrap();
assert!(m.testnestedflatbuffer().is_some());
assert_eq!(m.testnestedflatbuffer().unwrap(), b0.finished_data());
let m2_a = my_game::example::get_root_as_monster(m.testnestedflatbuffer().unwrap());
let m2_a = my_game::example::root_as_monster(m.testnestedflatbuffer().unwrap()).unwrap();
assert_eq!(m2_a.hp(), 123);
assert_eq!(m2_a.name(), "foobar");
@@ -799,7 +899,7 @@ mod generated_code_alignment_and_padding {
my_game::example::finish_monster_buffer(b, mon);
}
let buf = b.finished_data();
let mon = my_game::example::get_root_as_monster(buf);
let mon = my_game::example::root_as_monster(buf).unwrap();
let vec3 = mon.pos().unwrap();
let start_ptr = buf.as_ptr() as usize;
@@ -835,7 +935,7 @@ mod generated_code_alignment_and_padding {
my_game::example::finish_monster_buffer(b, mon);
}
let buf = b.finished_data();
let mon = my_game::example::get_root_as_monster(buf);
let mon = my_game::example::root_as_monster(buf).unwrap();
let abilities = mon.testarrayofsortedstruct().unwrap();
let start_ptr = buf.as_ptr() as usize;
@@ -1142,7 +1242,7 @@ mod framing_format {
// Access it.
let buf = b.finished_data();
let m = flatbuffers::get_size_prefixed_root::<my_game::example::Monster>(buf);
let m = flatbuffers::size_prefixed_root::<my_game::example::Monster>(buf).unwrap();
assert_eq!(m.mana(), 200);
assert_eq!(m.hp(), 300);
assert_eq!(m.name(), "bob");
@@ -1538,7 +1638,7 @@ mod write_and_read_examples {
create_serialized_example_with_generated_code(b);
let buf = b.finished_data();
serialized_example_is_accessible_and_correct(&buf, true, false).unwrap();
let m = super::my_game::example::get_root_as_monster(buf);
let m = super::my_game::example::root_as_monster(buf).unwrap();
assert_eq!(
format!("{:.5?}", &m),
"Monster { pos: Some(Vec3 { x: 1.00000, y: 2.00000, z: 3.00000, \
@@ -1728,7 +1828,7 @@ mod generated_key_comparisons {
let builder = &mut flatbuffers::FlatBufferBuilder::new();
super::create_serialized_example_with_library_code(builder);
let buf = builder.finished_data();
let a = my_game::example::get_root_as_monster(buf);
let a = my_game::example::root_as_monster(buf).unwrap();
// preconditions
assert_eq!(a.name(), "MyMonster");
@@ -1744,7 +1844,7 @@ mod generated_key_comparisons {
let builder = &mut flatbuffers::FlatBufferBuilder::new();
super::create_serialized_example_with_library_code(builder);
let buf = builder.finished_data();
let a = my_game::example::get_root_as_monster(buf);
let a = my_game::example::root_as_monster(buf).unwrap();
let b = a.test_as_monster().unwrap();
// preconditions

View File

@@ -27,13 +27,13 @@ macro_rules! make_test {
);
builder.finish(ss, None);
let s = flatbuffers::get_root::<ScalarStuff>(builder.finished_data());
let s = flatbuffers::root::<ScalarStuff>(builder.finished_data()).unwrap();
assert_eq!(s.$just(), $five);
assert_eq!(s.$default(), $five);
assert_eq!(s.$maybe(), Some($five));
// Test defaults are used when not specified.
let s = flatbuffers::get_root::<ScalarStuff>(&[0; 8]);
let s = flatbuffers::root::<ScalarStuff>(&[0; 8]).unwrap();
assert_eq!(s.$just(), $zero);
assert_eq!(s.$default(), $fortytwo);
assert_eq!(s.$maybe(), None);