diff --git a/rust/flatbuffers/src/vector.rs b/rust/flatbuffers/src/vector.rs index 3079649db..5236ea16e 100644 --- a/rust/flatbuffers/src/vector.rs +++ b/rust/flatbuffers/src/vector.rs @@ -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); +impl<'a, T> Debug for Vector<'a, T> +where + T: 'a + 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. diff --git a/samples/monster_generated.rs b/samples/monster_generated.rs index b86cb1952..e352b7583 100644 --- a/samples/monster_generated.rs +++ b/samples/monster_generated.rs @@ -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::>(buf) diff --git a/samples/sample_binary.rs b/samples/sample_binary.rs index b42e8c8e6..6fb987eb6 100644 --- a/samples/sample_binary.rs +++ b/samples/sample_binary.rs @@ -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)] diff --git a/src/idl_gen_rust.cpp b/src/idl_gen_rust.cpp index 590de4c62..b6434c844 100644 --- a/src/idl_gen_rust.cpp +++ b/src/idl_gen_rust.cpp @@ -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. diff --git a/tests/generate_code.sh b/tests/generate_code.sh index d52d78ce4..bbba2a5fb 100755 --- a/tests/generate_code.sh +++ b/tests/generate_code.sh @@ -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 diff --git a/tests/include_test/include_test1_generated.rs b/tests/include_test/include_test1_generated.rs index 12b8b08b9..3c7b9bd8a 100644 --- a/tests/include_test/include_test1_generated.rs +++ b/tests/include_test/include_test1_generated.rs @@ -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() + } +} diff --git a/tests/include_test/sub/include_test2_generated.rs b/tests/include_test/sub/include_test2_generated.rs index 6cfebf2bb..892c652d0 100644 --- a/tests/include_test/sub/include_test2_generated.rs +++ b/tests/include_test/sub/include_test2_generated.rs @@ -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 diff --git a/tests/monster_test_generated.rs b/tests/monster_test_generated.rs index 809e67a61..b09253c0c 100644 --- a/tests/monster_test_generated.rs +++ b/tests/monster_test_generated.rs @@ -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::>(buf) diff --git a/tests/namespace_test/namespace_test1_generated.rs b/tests/namespace_test/namespace_test1_generated.rs index 98c51bbc6..dd735a60e 100644 --- a/tests/namespace_test/namespace_test1_generated.rs +++ b/tests/namespace_test/namespace_test1_generated.rs @@ -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 diff --git a/tests/namespace_test/namespace_test2_generated.rs b/tests/namespace_test/namespace_test2_generated.rs index c14f189c4..b1d84cf0a 100644 --- a/tests/namespace_test/namespace_test2_generated.rs +++ b/tests/namespace_test/namespace_test2_generated.rs @@ -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 diff --git a/tests/optional_scalars_generated.rs b/tests/optional_scalars_generated.rs index 15bf4e73f..793a8ac47 100644 --- a/tests/optional_scalars_generated.rs +++ b/tests/optional_scalars_generated.rs @@ -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::>(buf) diff --git a/tests/rust_usage_test/tests/integration_test.rs b/tests/rust_usage_test/tests/integration_test.rs index ba2f47bb3..df1ff6b97 100644 --- a/tests/rust_usage_test/tests/integration_test.rs +++ b/tests/rust_usage_test/tests/integration_test.rs @@ -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();