mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-11 07:27:27 +00:00
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:
@@ -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>,
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user