Implement Debug trait for Rust flatbuffers. (#6207)

* Refactor idl_gen_rust to a ForAllX continuation pattern.

* Removed unneeded SetValue and updated sample rust gencode

* Make Rust flatbuffers print right

* Generated code and removed unnecessary trait constraint

* bumped rust version. Release required

* removed an unwrap in Rust Debug-print unions

* Tested formatting flatbuffers in rust.

* Set float precision in flaky debug-print test

* impl Debug for structs too

Co-authored-by: Casper Neo <cneo@google.com>
This commit is contained in:
Casper
2020-10-29 12:57:29 -07:00
committed by GitHub
parent 17ae48decc
commit b08b0a4402
12 changed files with 508 additions and 27 deletions

View File

@@ -19,6 +19,7 @@ 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")]
@@ -26,9 +27,19 @@ use crate::endian_scalar::EndianScalar;
use crate::follow::Follow;
use crate::primitives::*;
#[derive(Debug)]
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
{
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.

View File

@@ -173,12 +173,22 @@ impl flatbuffers::EndianScalar for Equipment {
pub struct EquipmentUnionTableOffset {}
// struct Vec3, aligned to 4
#[repr(C, align(4))]
#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Copy, PartialEq)]
pub struct Vec3 {
x_: f32,
y_: f32,
z_: f32,
} // pub struct Vec3
impl std::fmt::Debug for Vec3 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Vec3")
.field("x", &self.x())
.field("y", &self.y())
.field("z", &self.z())
.finish()
}
}
impl flatbuffers::SafeSliceAccess for Vec3 {}
impl<'a> flatbuffers::Follow<'a> for Vec3 {
type Inner = &'a Vec3;
@@ -238,7 +248,7 @@ impl Vec3 {
}
pub enum MonsterOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
pub struct Monster<'a> {
pub _tab: flatbuffers::Table<'a>,
@@ -429,8 +439,36 @@ impl<'a: 'b, 'b> MonsterBuilder<'a, 'b> {
}
}
impl std::fmt::Debug for Monster<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("Monster");
ds.field("pos", &self.pos());
ds.field("mana", &self.mana());
ds.field("hp", &self.hp());
ds.field("name", &self.name());
ds.field("inventory", &self.inventory());
ds.field("color", &self.color());
ds.field("weapons", &self.weapons());
ds.field("equipped_type", &self.equipped_type());
match self.equipped_type() {
Equipment::Weapon => {
if let Some(x) = self.equipped_as_weapon() {
ds.field("equipped", &x)
} else {
ds.field("equipped", &"InvalidFlatbuffer: Union discriminant does not match value.")
}
},
_ => {
let x: Option<()> = None;
ds.field("equipped", &x)
},
};
ds.field("path", &self.path());
ds.finish()
}
}
pub enum WeaponOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
pub struct Weapon<'a> {
pub _tab: flatbuffers::Table<'a>,
@@ -515,6 +553,14 @@ impl<'a: 'b, 'b> WeaponBuilder<'a, 'b> {
}
}
impl std::fmt::Debug for Weapon<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("Weapon");
ds.field("name", &self.name());
ds.field("damage", &self.damage());
ds.finish()
}
}
#[inline]
pub fn get_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> {
flatbuffers::get_root::<Monster<'a>>(buf)

View File

@@ -152,6 +152,7 @@ fn main() {
//assert_eq!(monster.path().unwrap()[1].x(), 4.0);
println!("The FlatBuffer was successfully created and accessed!");
dbg!(monster);
}
#[cfg(test)]

View File

@@ -1188,7 +1188,7 @@ class RustGenerator : public BaseGenerator {
// Generate an offset type, the base type, the Follow impl, and the
// init_from_table impl.
code_ += "pub enum {{OFFSET_TYPELABEL}} {}";
code_ += "#[derive(Copy, Clone, Debug, PartialEq)]";
code_ += "#[derive(Copy, Clone, PartialEq)]";
code_ += "";
GenComment(struct_def.doc_comment);
@@ -1454,6 +1454,45 @@ class RustGenerator : public BaseGenerator {
code_ += " }";
code_ += "}";
code_ += "";
code_ += "impl std::fmt::Debug for {{STRUCT_NAME}}<'_> {";
code_ += " fn fmt(&self, f: &mut std::fmt::Formatter<'_>"
") -> std::fmt::Result {";
code_ += " let mut ds = f.debug_struct(\"{{STRUCT_NAME}}\");";
ForAllTableFields(struct_def, [&](const FieldDef &field) {
if (GetFullType(field.value.type) == ftUnionValue) {
// Generate a match statement to handle unions properly.
code_.SetValue("KEY_TYPE", GenTableAccessorFuncReturnType(field, ""));
code_.SetValue("FIELD_TYPE_FIELD_NAME", field.name);
code_.SetValue("UNION_ERR", "&\"InvalidFlatbuffer: Union discriminant"
" does not match value.\"");
code_ += " match self.{{FIELD_NAME}}_type() {";
ForAllUnionVariantsBesidesNone(*field.value.type.enum_def,
[&](const EnumVal &unused){
(void) unused;
code_ += " {{U_ELEMENT_ENUM_TYPE}} => {";
code_ += " if let Some(x) = self.{{FIELD_TYPE_FIELD_NAME}}_as_"
"{{U_ELEMENT_NAME}}() {";
code_ += " ds.field(\"{{FIELD_NAME}}\", &x)";
code_ += " } else {";
code_ += " ds.field(\"{{FIELD_NAME}}\", {{UNION_ERR}})";
code_ += " }";
code_ += " },";
});
code_ += " _ => { ";
code_ += " let x: Option<()> = None;";
code_ += " ds.field(\"{{FIELD_NAME}}\", &x)";
code_ += " },";
code_ += " };";
} else {
// Most fields.
code_ += " ds.field(\"{{FIELD_NAME}}\", &self.{{FIELD_NAME}}());";
}
});
code_ += " ds.finish()";
code_ += " }";
code_ += "}";
}
// Generate functions to compare tables and structs by key. This function
@@ -1618,7 +1657,7 @@ class RustGenerator : public BaseGenerator {
// PartialEq is useful to derive because we can correctly compare structs
// for equality by just comparing their underlying byte data. This doesn't
// hold for PartialOrd/Ord.
code_ += "#[derive(Clone, Copy, Debug, PartialEq)]";
code_ += "#[derive(Clone, Copy, PartialEq)]";
code_ += "pub struct {{STRUCT_NAME}} {";
int padding_id = 0;
@@ -1630,9 +1669,23 @@ class RustGenerator : public BaseGenerator {
code_ += padding;
}
});
code_ += "} // pub struct {{STRUCT_NAME}}";
// Debug for structs.
code_ += "impl std::fmt::Debug for {{STRUCT_NAME}} {";
code_ += " fn fmt(&self, f: &mut std::fmt::Formatter"
") -> std::fmt::Result {";
code_ += " f.debug_struct(\"{{STRUCT_NAME}}\")";
ForAllStructFields(struct_def, [&](const FieldDef &unused) {
(void) unused;
code_ += " .field(\"{{FIELD_NAME}}\", &self.{{FIELD_NAME}}())";
});
code_ += " .finish()";
code_ += " }";
code_ += "}";
code_ += "";
// 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.

View File

@@ -88,7 +88,7 @@ TEST_CPP17_FLAGS="--cpp --cpp-std c++17 -o ./cpp17/generated_cpp17 $TEST_NOINCL_
../flatc $TEST_CPP17_FLAGS optional_scalars.fbs
cd ../samples
../flatc --cpp --lobster $TEST_BASE_FLAGS $TEST_CPP_FLAGS monster.fbs
../flatc --cpp --rust --lobster $TEST_BASE_FLAGS $TEST_CPP_FLAGS monster.fbs
../flatc -b --schema --bfbs-comments --bfbs-builtins monster.fbs
cd ../reflection
./generate_code.sh --cpp-std c++0x

View File

@@ -11,7 +11,7 @@ extern crate flatbuffers;
use self::flatbuffers::EndianScalar;
pub enum TableAOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
pub struct TableA<'a> {
pub _tab: flatbuffers::Table<'a>,
@@ -84,3 +84,10 @@ impl<'a: 'b, 'b> TableABuilder<'a, 'b> {
}
}
impl std::fmt::Debug for TableA<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("TableA");
ds.field("b", &self.b());
ds.finish()
}
}

View File

@@ -97,10 +97,18 @@ impl flatbuffers::EndianScalar for FromInclude {
// struct Unused, aligned to 4
#[repr(C, align(4))]
#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Copy, PartialEq)]
pub struct Unused {
a_: i32,
} // pub struct Unused
impl std::fmt::Debug for Unused {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Unused")
.field("a", &self.a())
.finish()
}
}
impl flatbuffers::SafeSliceAccess for Unused {}
impl<'a> flatbuffers::Follow<'a> for Unused {
type Inner = &'a Unused;
@@ -152,7 +160,7 @@ impl Unused {
}
pub enum TableBOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
pub struct TableB<'a> {
pub _tab: flatbuffers::Table<'a>,
@@ -225,6 +233,13 @@ impl<'a: 'b, 'b> TableBBuilder<'a, 'b> {
}
}
impl std::fmt::Debug for TableB<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("TableB");
ds.field("a", &self.a());
ds.finish()
}
}
} // pub mod OtherNameSpace
} // pub mod MyGame

View File

@@ -23,7 +23,7 @@ pub mod my_game {
use self::flatbuffers::EndianScalar;
pub enum InParentNamespaceOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
pub struct InParentNamespace<'a> {
pub _tab: flatbuffers::Table<'a>,
@@ -87,6 +87,12 @@ impl<'a: 'b, 'b> InParentNamespaceBuilder<'a, 'b> {
}
}
impl std::fmt::Debug for InParentNamespace<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("InParentNamespace");
ds.finish()
}
}
#[allow(unused_imports, dead_code)]
pub mod example_2 {
@@ -99,7 +105,7 @@ pub mod example_2 {
use self::flatbuffers::EndianScalar;
pub enum MonsterOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
pub struct Monster<'a> {
pub _tab: flatbuffers::Table<'a>,
@@ -163,6 +169,12 @@ impl<'a: 'b, 'b> MonsterBuilder<'a, 'b> {
}
}
impl std::fmt::Debug for Monster<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("Monster");
ds.finish()
}
}
} // pub mod Example2
#[allow(unused_imports, dead_code)]
@@ -539,12 +551,21 @@ impl flatbuffers::EndianScalar for AnyAmbiguousAliases {
pub struct AnyAmbiguousAliasesUnionTableOffset {}
// struct Test, aligned to 2
#[repr(C, align(2))]
#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Copy, PartialEq)]
pub struct Test {
a_: i16,
b_: i8,
padding0__: u8,
} // pub struct Test
impl std::fmt::Debug for Test {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Test")
.field("a", &self.a())
.field("b", &self.b())
.finish()
}
}
impl flatbuffers::SafeSliceAccess for Test {}
impl<'a> flatbuffers::Follow<'a> for Test {
type Inner = &'a Test;
@@ -606,7 +627,7 @@ impl Test {
// struct Vec3, aligned to 8
#[repr(C, align(8))]
#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Copy, PartialEq)]
pub struct Vec3 {
x_: f32,
y_: f32,
@@ -618,6 +639,19 @@ pub struct Vec3 {
test3_: Test,
padding2__: u16,
} // pub struct Vec3
impl std::fmt::Debug for Vec3 {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Vec3")
.field("x", &self.x())
.field("y", &self.y())
.field("z", &self.z())
.field("test1", &self.test1())
.field("test2", &self.test2())
.field("test3", &self.test3())
.finish()
}
}
impl flatbuffers::SafeSliceAccess for Vec3 {}
impl<'a> flatbuffers::Follow<'a> for Vec3 {
type Inner = &'a Vec3;
@@ -697,11 +731,20 @@ impl Vec3 {
// struct Ability, aligned to 4
#[repr(C, align(4))]
#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Copy, PartialEq)]
pub struct Ability {
id_: u32,
distance_: u32,
} // pub struct Ability
impl std::fmt::Debug for Ability {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("Ability")
.field("id", &self.id())
.field("distance", &self.distance())
.finish()
}
}
impl flatbuffers::SafeSliceAccess for Ability {}
impl<'a> flatbuffers::Follow<'a> for Ability {
type Inner = &'a Ability;
@@ -771,7 +814,7 @@ impl Ability {
}
pub enum TestSimpleTableWithEnumOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
pub struct TestSimpleTableWithEnum<'a> {
pub _tab: flatbuffers::Table<'a>,
@@ -848,8 +891,15 @@ impl<'a: 'b, 'b> TestSimpleTableWithEnumBuilder<'a, 'b> {
}
}
impl std::fmt::Debug for TestSimpleTableWithEnum<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("TestSimpleTableWithEnum");
ds.field("color", &self.color());
ds.finish()
}
}
pub enum StatOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
pub struct Stat<'a> {
pub _tab: flatbuffers::Table<'a>,
@@ -950,8 +1000,17 @@ impl<'a: 'b, 'b> StatBuilder<'a, 'b> {
}
}
impl std::fmt::Debug for Stat<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("Stat");
ds.field("id", &self.id());
ds.field("val", &self.val());
ds.field("count", &self.count());
ds.finish()
}
}
pub enum ReferrableOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
pub struct Referrable<'a> {
pub _tab: flatbuffers::Table<'a>,
@@ -1038,8 +1097,15 @@ impl<'a: 'b, 'b> ReferrableBuilder<'a, 'b> {
}
}
impl std::fmt::Debug for Referrable<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("Referrable");
ds.field("id", &self.id());
ds.finish()
}
}
pub enum MonsterOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
/// an example documentation comment: "monster object"
pub struct Monster<'a> {
@@ -1790,8 +1856,140 @@ impl<'a: 'b, 'b> MonsterBuilder<'a, 'b> {
}
}
impl std::fmt::Debug for Monster<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("Monster");
ds.field("pos", &self.pos());
ds.field("mana", &self.mana());
ds.field("hp", &self.hp());
ds.field("name", &self.name());
ds.field("inventory", &self.inventory());
ds.field("color", &self.color());
ds.field("test_type", &self.test_type());
match self.test_type() {
Any::Monster => {
if let Some(x) = self.test_as_monster() {
ds.field("test", &x)
} else {
ds.field("test", &"InvalidFlatbuffer: Union discriminant does not match value.")
}
},
Any::TestSimpleTableWithEnum => {
if let Some(x) = self.test_as_test_simple_table_with_enum() {
ds.field("test", &x)
} else {
ds.field("test", &"InvalidFlatbuffer: Union discriminant does not match value.")
}
},
Any::MyGame_Example2_Monster => {
if let Some(x) = self.test_as_my_game_example_2_monster() {
ds.field("test", &x)
} else {
ds.field("test", &"InvalidFlatbuffer: Union discriminant does not match value.")
}
},
_ => {
let x: Option<()> = None;
ds.field("test", &x)
},
};
ds.field("test4", &self.test4());
ds.field("testarrayofstring", &self.testarrayofstring());
ds.field("testarrayoftables", &self.testarrayoftables());
ds.field("enemy", &self.enemy());
ds.field("testnestedflatbuffer", &self.testnestedflatbuffer());
ds.field("testempty", &self.testempty());
ds.field("testbool", &self.testbool());
ds.field("testhashs32_fnv1", &self.testhashs32_fnv1());
ds.field("testhashu32_fnv1", &self.testhashu32_fnv1());
ds.field("testhashs64_fnv1", &self.testhashs64_fnv1());
ds.field("testhashu64_fnv1", &self.testhashu64_fnv1());
ds.field("testhashs32_fnv1a", &self.testhashs32_fnv1a());
ds.field("testhashu32_fnv1a", &self.testhashu32_fnv1a());
ds.field("testhashs64_fnv1a", &self.testhashs64_fnv1a());
ds.field("testhashu64_fnv1a", &self.testhashu64_fnv1a());
ds.field("testarrayofbools", &self.testarrayofbools());
ds.field("testf", &self.testf());
ds.field("testf2", &self.testf2());
ds.field("testf3", &self.testf3());
ds.field("testarrayofstring2", &self.testarrayofstring2());
ds.field("testarrayofsortedstruct", &self.testarrayofsortedstruct());
ds.field("flex", &self.flex());
ds.field("test5", &self.test5());
ds.field("vector_of_longs", &self.vector_of_longs());
ds.field("vector_of_doubles", &self.vector_of_doubles());
ds.field("parent_namespace_test", &self.parent_namespace_test());
ds.field("vector_of_referrables", &self.vector_of_referrables());
ds.field("single_weak_reference", &self.single_weak_reference());
ds.field("vector_of_weak_references", &self.vector_of_weak_references());
ds.field("vector_of_strong_referrables", &self.vector_of_strong_referrables());
ds.field("co_owning_reference", &self.co_owning_reference());
ds.field("vector_of_co_owning_references", &self.vector_of_co_owning_references());
ds.field("non_owning_reference", &self.non_owning_reference());
ds.field("vector_of_non_owning_references", &self.vector_of_non_owning_references());
ds.field("any_unique_type", &self.any_unique_type());
match self.any_unique_type() {
AnyUniqueAliases::M => {
if let Some(x) = self.any_unique_as_m() {
ds.field("any_unique", &x)
} else {
ds.field("any_unique", &"InvalidFlatbuffer: Union discriminant does not match value.")
}
},
AnyUniqueAliases::TS => {
if let Some(x) = self.any_unique_as_ts() {
ds.field("any_unique", &x)
} else {
ds.field("any_unique", &"InvalidFlatbuffer: Union discriminant does not match value.")
}
},
AnyUniqueAliases::M2 => {
if let Some(x) = self.any_unique_as_m2() {
ds.field("any_unique", &x)
} else {
ds.field("any_unique", &"InvalidFlatbuffer: Union discriminant does not match value.")
}
},
_ => {
let x: Option<()> = None;
ds.field("any_unique", &x)
},
};
ds.field("any_ambiguous_type", &self.any_ambiguous_type());
match self.any_ambiguous_type() {
AnyAmbiguousAliases::M1 => {
if let Some(x) = self.any_ambiguous_as_m1() {
ds.field("any_ambiguous", &x)
} else {
ds.field("any_ambiguous", &"InvalidFlatbuffer: Union discriminant does not match value.")
}
},
AnyAmbiguousAliases::M2 => {
if let Some(x) = self.any_ambiguous_as_m2() {
ds.field("any_ambiguous", &x)
} else {
ds.field("any_ambiguous", &"InvalidFlatbuffer: Union discriminant does not match value.")
}
},
AnyAmbiguousAliases::M3 => {
if let Some(x) = self.any_ambiguous_as_m3() {
ds.field("any_ambiguous", &x)
} else {
ds.field("any_ambiguous", &"InvalidFlatbuffer: Union discriminant does not match value.")
}
},
_ => {
let x: Option<()> = None;
ds.field("any_ambiguous", &x)
},
};
ds.field("vector_of_enums", &self.vector_of_enums());
ds.field("signed_enum", &self.signed_enum());
ds.finish()
}
}
pub enum TypeAliasesOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
pub struct TypeAliases<'a> {
pub _tab: flatbuffers::Table<'a>,
@@ -2000,6 +2198,24 @@ impl<'a: 'b, 'b> TypeAliasesBuilder<'a, 'b> {
}
}
impl std::fmt::Debug for TypeAliases<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("TypeAliases");
ds.field("i8_", &self.i8_());
ds.field("u8_", &self.u8_());
ds.field("i16_", &self.i16_());
ds.field("u16_", &self.u16_());
ds.field("i32_", &self.i32_());
ds.field("u32_", &self.u32_());
ds.field("i64_", &self.i64_());
ds.field("u64_", &self.u64_());
ds.field("f32_", &self.f32_());
ds.field("f64_", &self.f64_());
ds.field("v8", &self.v8());
ds.field("vf64", &self.vf64());
ds.finish()
}
}
#[inline]
pub fn get_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> {
flatbuffers::get_root::<Monster<'a>>(buf)

View File

@@ -102,11 +102,20 @@ impl flatbuffers::EndianScalar for EnumInNestedNS {
// struct StructInNestedNS, aligned to 4
#[repr(C, align(4))]
#[derive(Clone, Copy, Debug, PartialEq)]
#[derive(Clone, Copy, PartialEq)]
pub struct StructInNestedNS {
a_: i32,
b_: i32,
} // pub struct StructInNestedNS
impl std::fmt::Debug for StructInNestedNS {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("StructInNestedNS")
.field("a", &self.a())
.field("b", &self.b())
.finish()
}
}
impl flatbuffers::SafeSliceAccess for StructInNestedNS {}
impl<'a> flatbuffers::Follow<'a> for StructInNestedNS {
type Inner = &'a StructInNestedNS;
@@ -166,7 +175,7 @@ impl StructInNestedNS {
}
pub enum TableInNestedNSOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
pub struct TableInNestedNS<'a> {
pub _tab: flatbuffers::Table<'a>,
@@ -243,6 +252,13 @@ impl<'a: 'b, 'b> TableInNestedNSBuilder<'a, 'b> {
}
}
impl std::fmt::Debug for TableInNestedNS<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("TableInNestedNS");
ds.field("foo", &self.foo());
ds.finish()
}
}
} // pub mod NamespaceB
} // pub mod NamespaceA

View File

@@ -21,7 +21,7 @@ pub mod namespace_a {
use self::flatbuffers::EndianScalar;
pub enum TableInFirstNSOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
pub struct TableInFirstNS<'a> {
pub _tab: flatbuffers::Table<'a>,
@@ -122,8 +122,17 @@ impl<'a: 'b, 'b> TableInFirstNSBuilder<'a, 'b> {
}
}
impl std::fmt::Debug for TableInFirstNS<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("TableInFirstNS");
ds.field("foo_table", &self.foo_table());
ds.field("foo_enum", &self.foo_enum());
ds.field("foo_struct", &self.foo_struct());
ds.finish()
}
}
pub enum SecondTableInAOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
pub struct SecondTableInA<'a> {
pub _tab: flatbuffers::Table<'a>,
@@ -200,6 +209,13 @@ impl<'a: 'b, 'b> SecondTableInABuilder<'a, 'b> {
}
}
impl std::fmt::Debug for SecondTableInA<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("SecondTableInA");
ds.field("refer_to_c", &self.refer_to_c());
ds.finish()
}
}
} // pub mod NamespaceA
#[allow(unused_imports, dead_code)]
@@ -213,7 +229,7 @@ pub mod namespace_c {
use self::flatbuffers::EndianScalar;
pub enum TableInCOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
pub struct TableInC<'a> {
pub _tab: flatbuffers::Table<'a>,
@@ -302,5 +318,13 @@ impl<'a: 'b, 'b> TableInCBuilder<'a, 'b> {
}
}
impl std::fmt::Debug for TableInC<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("TableInC");
ds.field("refer_to_a1", &self.refer_to_a1());
ds.field("refer_to_a2", &self.refer_to_a2());
ds.finish()
}
}
} // pub mod NamespaceC

View File

@@ -93,7 +93,7 @@ impl flatbuffers::EndianScalar for OptionalByte {
}
pub enum ScalarStuffOffset {}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, PartialEq)]
pub struct ScalarStuff<'a> {
pub _tab: flatbuffers::Table<'a>,
@@ -586,6 +586,48 @@ impl<'a: 'b, 'b> ScalarStuffBuilder<'a, 'b> {
}
}
impl std::fmt::Debug for ScalarStuff<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut ds = f.debug_struct("ScalarStuff");
ds.field("just_i8", &self.just_i8());
ds.field("maybe_i8", &self.maybe_i8());
ds.field("default_i8", &self.default_i8());
ds.field("just_u8", &self.just_u8());
ds.field("maybe_u8", &self.maybe_u8());
ds.field("default_u8", &self.default_u8());
ds.field("just_i16", &self.just_i16());
ds.field("maybe_i16", &self.maybe_i16());
ds.field("default_i16", &self.default_i16());
ds.field("just_u16", &self.just_u16());
ds.field("maybe_u16", &self.maybe_u16());
ds.field("default_u16", &self.default_u16());
ds.field("just_i32", &self.just_i32());
ds.field("maybe_i32", &self.maybe_i32());
ds.field("default_i32", &self.default_i32());
ds.field("just_u32", &self.just_u32());
ds.field("maybe_u32", &self.maybe_u32());
ds.field("default_u32", &self.default_u32());
ds.field("just_i64", &self.just_i64());
ds.field("maybe_i64", &self.maybe_i64());
ds.field("default_i64", &self.default_i64());
ds.field("just_u64", &self.just_u64());
ds.field("maybe_u64", &self.maybe_u64());
ds.field("default_u64", &self.default_u64());
ds.field("just_f32", &self.just_f32());
ds.field("maybe_f32", &self.maybe_f32());
ds.field("default_f32", &self.default_f32());
ds.field("just_f64", &self.just_f64());
ds.field("maybe_f64", &self.maybe_f64());
ds.field("default_f64", &self.default_f64());
ds.field("just_bool", &self.just_bool());
ds.field("maybe_bool", &self.maybe_bool());
ds.field("default_bool", &self.default_bool());
ds.field("just_enum", &self.just_enum());
ds.field("maybe_enum", &self.maybe_enum());
ds.field("default_enum", &self.default_enum());
ds.finish()
}
}
#[inline]
pub fn get_root_as_scalar_stuff<'a>(buf: &'a [u8]) -> ScalarStuff<'a> {
flatbuffers::get_root::<ScalarStuff<'a>>(buf)

View File

@@ -1532,6 +1532,56 @@ mod write_and_read_examples {
serialized_example_is_accessible_and_correct(&buf[..], true, false).unwrap();
}
#[test]
fn generated_code_debug_prints_correctly() {
let b = &mut flatbuffers::FlatBufferBuilder::new();
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);
assert_eq!(
format!("{:.5?}", &m),
"Monster { pos: Some(Vec3 { x: 1.00000, y: 2.00000, z: 3.00000, \
test1: 3.00000, test2: Green, test3: Test { a: 5, b: 6 } }), \
mana: 150, hp: 80, name: \"MyMonster\", \
inventory: Some([0, 1, 2, 3, 4]), color: Blue, test_type: Monster, \
test: Monster { pos: None, mana: 150, hp: 100, name: \"Fred\", \
inventory: None, color: Blue, test_type: NONE, test: None, \
test4: None, testarrayofstring: None, testarrayoftables: None, \
enemy: None, testnestedflatbuffer: None, testempty: None, \
testbool: false, testhashs32_fnv1: 0, testhashu32_fnv1: 0, \
testhashs64_fnv1: 0, testhashu64_fnv1: 0, testhashs32_fnv1a: 0, \
testhashu32_fnv1a: 0, testhashs64_fnv1a: 0, testhashu64_fnv1a: 0, \
testarrayofbools: None, testf: 3.14159, testf2: 3.00000, testf3: 0.00000, \
testarrayofstring2: None, testarrayofsortedstruct: None, flex: None, \
test5: None, vector_of_longs: None, vector_of_doubles: None, \
parent_namespace_test: None, vector_of_referrables: None, \
single_weak_reference: 0, vector_of_weak_references: None, \
vector_of_strong_referrables: None, co_owning_reference: 0, \
vector_of_co_owning_references: None, non_owning_reference: 0, \
vector_of_non_owning_references: None, any_unique_type: NONE, \
any_unique: None, any_ambiguous_type: NONE, any_ambiguous: None, \
vector_of_enums: None, signed_enum: None }, test4: Some([Test { \
a: 10, b: 20 }, Test { a: 30, b: 40 }]), \
testarrayofstring: Some([\"test1\", \"test2\"]), \
testarrayoftables: None, enemy: None, testnestedflatbuffer: None, \
testempty: None, testbool: false, testhashs32_fnv1: 0, \
testhashu32_fnv1: 0, testhashs64_fnv1: 0, testhashu64_fnv1: 0, \
testhashs32_fnv1a: 0, testhashu32_fnv1a: 0, testhashs64_fnv1a: 0, \
testhashu64_fnv1a: 0, testarrayofbools: None, testf: 3.14159, \
testf2: 3.00000, testf3: 0.00000, testarrayofstring2: None, \
testarrayofsortedstruct: None, flex: None, test5: None, \
vector_of_longs: None, vector_of_doubles: None, \
parent_namespace_test: None, vector_of_referrables: None, \
single_weak_reference: 0, vector_of_weak_references: None, \
vector_of_strong_referrables: None, co_owning_reference: 0, \
vector_of_co_owning_references: None, non_owning_reference: 0, \
vector_of_non_owning_references: None, any_unique_type: NONE, \
any_unique: None, any_ambiguous_type: NONE, any_ambiguous: None, \
vector_of_enums: None, signed_enum: None }"
);
}
#[test]
fn generated_code_creates_correct_example_repeatedly_with_reset() {
let b = &mut flatbuffers::FlatBufferBuilder::new();