From 5a98d65e86bb57e0a34118902c2e4b03f1a38551 Mon Sep 17 00:00:00 2001 From: Lee Mracek Date: Sun, 8 Mar 2020 22:05:20 -0400 Subject: [PATCH] [Rust] Add gen-name-strings for Rust (#5757) * Add gen-name-strings for Rust * Clang format * Add tests and generate with gen-name-strings * Clang-format * Stop doing gen-name-strings with C++ code * Bring generate_code.bat up with generate_code.sh --- src/flatc.cpp | 2 +- src/idl_gen_rust.cpp | 19 +++++++++ tests/generate_code.bat | 4 +- tests/generate_code.sh | 4 +- tests/monster_test_generated.rs | 40 +++++++++++++++++++ .../rust_usage_test/tests/integration_test.rs | 12 ++++++ 6 files changed, 78 insertions(+), 3 deletions(-) diff --git a/src/flatc.cpp b/src/flatc.cpp index b2a6673d8..5cb2a80c4 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -100,7 +100,7 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const { " schemas the generated file depends on (C++ / Python).\n" " --gen-mutable Generate accessors that can mutate buffers in-place.\n" " --gen-onefile Generate single output file for C# and Go.\n" - " --gen-name-strings Generate type name functions for C++.\n" + " --gen-name-strings Generate type name functions for C++ and Rust.\n" " --gen-object-api Generate an additional object-based API.\n" " --gen-compare Generate operator== for object-based API types.\n" " --gen-nullable Add Clang _Nullable for C++ pointer. or @Nullable for Java\n" diff --git a/src/idl_gen_rust.cpp b/src/idl_gen_rust.cpp index 0b8c07d77..55b8439b6 100644 --- a/src/idl_gen_rust.cpp +++ b/src/idl_gen_rust.cpp @@ -1127,6 +1127,16 @@ class RustGenerator : public BaseGenerator { } } + // Generates a fully-qualified name getter for use with --gen-name-strings + void GenFullyQualifiedNameGetter(const StructDef &struct_def, + const std::string &name) { + code_ += " pub const fn get_fully_qualified_name() -> &'static str {"; + code_ += " \"" + + struct_def.defined_namespace->GetFullyQualifiedName(name) + "\""; + code_ += " }"; + code_ += ""; + } + // Generate an accessor struct, builder struct, and create function for a // table. void GenTable(const StructDef &struct_def) { @@ -1157,6 +1167,11 @@ class RustGenerator : public BaseGenerator { code_ += "}"; code_ += ""; code_ += "impl<'a> {{STRUCT_NAME}}<'a> {"; + + if (parser_.opts.generate_name_strings) { + GenFullyQualifiedNameGetter(struct_def, struct_def.name); + } + code_ += " #[inline]"; code_ += " pub fn init_from_table(table: flatbuffers::Table<'a>) -> " @@ -1728,6 +1743,10 @@ class RustGenerator : public BaseGenerator { code_ += " }"; code_ += " }"; + if (parser_.opts.generate_name_strings) { + GenFullyQualifiedNameGetter(struct_def, struct_def.name); + } + // Generate accessor methods for the struct. for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { diff --git a/tests/generate_code.bat b/tests/generate_code.bat index d8d18ce76..5d4db19f6 100644 --- a/tests/generate_code.bat +++ b/tests/generate_code.bat @@ -29,11 +29,13 @@ if NOT "%commandline%"=="%commandline:--cpp-std c++0x=%" ( set TEST_CPP_FLAGS=--gen-compare --cpp-ptr-type flatbuffers::unique_ptr %TEST_CPP_FLAGS% set TEST_CS_FLAGS=--cs-gen-json-serializer +set TEST_RUST_FLAGS=--gen-name-strings set TEST_BASE_FLAGS=--reflect-names --gen-mutable --gen-object-api set TEST_NOINCL_FLAGS=%TEST_BASE_FLAGS% --no-includes --no-fb-import -..\%buildtype%\flatc.exe --binary --cpp --java --kotlin --csharp --dart --go --lobster --lua --js --ts --php --rust --grpc ^ +..\%buildtype%\flatc.exe --binary --cpp --java --kotlin --csharp --dart --go --lobster --lua --js --ts --php --grpc ^ %TEST_NOINCL_FLAGS% %TEST_CPP_FLAGS% %TEST_CS_FLAGS% -I include_test monster_test.fbs monsterdata_test.json || goto FAIL +..\%buildtype%\flatc.exe --rust %TEST_NOINCL_FLAGS% %TEST_RUST_FLAGS% -I include_test monster_test.fbs monsterdata_test.json || goto FAIL ..\%buildtype%\flatc.exe --python %TEST_BASE_FLAGS% --no-fb-import -I include_test monster_test.fbs monsterdata_test.json || goto FAIL diff --git a/tests/generate_code.sh b/tests/generate_code.sh index a3a40b72c..e97334f0f 100755 --- a/tests/generate_code.sh +++ b/tests/generate_code.sh @@ -27,10 +27,12 @@ fi TEST_CPP_FLAGS="--gen-compare --cpp-ptr-type flatbuffers::unique_ptr $TEST_CPP_FLAGS" TEST_CS_FLAGS="--cs-gen-json-serializer" TEST_BASE_FLAGS="--reflect-names --gen-mutable --gen-object-api" +TEST_RUST_FLAGS="$TEST_BASE_FLAGS --gen-name-strings" TEST_NOINCL_FLAGS="$TEST_BASE_FLAGS --no-includes --no-fb-import" -../flatc --binary --cpp --java --kotlin --csharp --dart --go --lobster --lua --js --ts --php --rust --grpc \ +../flatc --binary --cpp --java --kotlin --csharp --dart --go --lobster --lua --js --ts --php --grpc \ $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS -I include_test monster_test.fbs monsterdata_test.json +../flatc --rust $TEST_RUST_FLAGS -I include_test monster_test.fbs monsterdata_test.json ../flatc --python $TEST_BASE_FLAGS -I include_test monster_test.fbs monsterdata_test.json diff --git a/tests/monster_test_generated.rs b/tests/monster_test_generated.rs index 22240b960..af275dbce 100644 --- a/tests/monster_test_generated.rs +++ b/tests/monster_test_generated.rs @@ -39,6 +39,10 @@ impl<'a> flatbuffers::Follow<'a> for InParentNamespace<'a> { } impl<'a> InParentNamespace<'a> { + pub const fn get_fully_qualified_name() -> &'static str { + "MyGame.InParentNamespace" + } + #[inline] pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { InParentNamespace { @@ -113,6 +117,10 @@ impl<'a> flatbuffers::Follow<'a> for Monster<'a> { } impl<'a> Monster<'a> { + pub const fn get_fully_qualified_name() -> &'static str { + "MyGame.Example2.Monster" + } + #[inline] pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { Monster { @@ -565,6 +573,10 @@ impl Test { padding0__: 0, } } + pub const fn get_fully_qualified_name() -> &'static str { + "MyGame.Example.Test" + } + pub fn a<'a>(&'a self) -> i16 { self.a_.from_little_endian() } @@ -640,6 +652,10 @@ impl Vec3 { padding2__: 0, } } + pub const fn get_fully_qualified_name() -> &'static str { + "MyGame.Example.Vec3" + } + pub fn x<'a>(&'a self) -> f32 { self.x_.from_little_endian() } @@ -713,6 +729,10 @@ impl Ability { } } + pub const fn get_fully_qualified_name() -> &'static str { + "MyGame.Example.Ability" + } + pub fn id<'a>(&'a self) -> u32 { self.id_.from_little_endian() } @@ -749,6 +769,10 @@ impl<'a> flatbuffers::Follow<'a> for TestSimpleTableWithEnum<'a> { } impl<'a> TestSimpleTableWithEnum<'a> { + pub const fn get_fully_qualified_name() -> &'static str { + "MyGame.Example.TestSimpleTableWithEnum" + } + #[inline] pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TestSimpleTableWithEnum { @@ -825,6 +849,10 @@ impl<'a> flatbuffers::Follow<'a> for Stat<'a> { } impl<'a> Stat<'a> { + pub const fn get_fully_qualified_name() -> &'static str { + "MyGame.Example.Stat" + } + #[inline] pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { Stat { @@ -925,6 +953,10 @@ impl<'a> flatbuffers::Follow<'a> for Referrable<'a> { } impl<'a> Referrable<'a> { + pub const fn get_fully_qualified_name() -> &'static str { + "MyGame.Example.Referrable" + } + #[inline] pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { Referrable { @@ -1012,6 +1044,10 @@ impl<'a> flatbuffers::Follow<'a> for Monster<'a> { } impl<'a> Monster<'a> { + pub const fn get_fully_qualified_name() -> &'static str { + "MyGame.Example.Monster" + } + #[inline] pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { Monster { @@ -1764,6 +1800,10 @@ impl<'a> flatbuffers::Follow<'a> for TypeAliases<'a> { } impl<'a> TypeAliases<'a> { + pub const fn get_fully_qualified_name() -> &'static str { + "MyGame.Example.TypeAliases" + } + #[inline] pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { TypeAliases { diff --git a/tests/rust_usage_test/tests/integration_test.rs b/tests/rust_usage_test/tests/integration_test.rs index cc3a2ee08..ae5c23432 100644 --- a/tests/rust_usage_test/tests/integration_test.rs +++ b/tests/rust_usage_test/tests/integration_test.rs @@ -2875,6 +2875,18 @@ mod copy_clone_traits { } } +#[cfg(test)] +mod fully_qualified_name { + #[test] + fn fully_qualified_name_generated() { + assert!(check_eq!(::my_game::example::Monster::get_fully_qualified_name(), "MyGame.Example.Monster").is_ok()); + assert!(check_eq!(::my_game::example_2::Monster::get_fully_qualified_name(), "MyGame.Example2.Monster").is_ok()); + + assert!(check_eq!(::my_game::example::Vec3::get_fully_qualified_name(), "MyGame.Example.Vec3").is_ok()); + assert!(check_eq!(::my_game::example::Ability::get_fully_qualified_name(), "MyGame.Example.Ability").is_ok()); + } +} + // this is not technically a test, but we want to always keep this generated // file up-to-date, and the simplest way to do that is to make sure that when // tests are run, the file is generated.