From 77db01a882ea1bb3299f9cae50e175ead6ef2be8 Mon Sep 17 00:00:00 2001 From: Joseph Dunne Date: Fri, 27 May 2016 18:23:00 +0100 Subject: [PATCH 1/7] Support for Rust programming language --- .gitignore | 3 + CMakeLists.txt | 1 + include/flatbuffers/idl.h | 53 +- readme.md | 2 +- rust/.gitignore | 2 + rust/Cargo.lock | 12 + rust/Cargo.toml | 25 + rust/src/bin/test.rs | 237 ++++ rust/src/bin/test/MyGame/Example/.#Color.rs | 1 + rust/src/bin/test/MyGame/Example/Any.rs | 61 + rust/src/bin/test/MyGame/Example/Color.rs | 35 + rust/src/bin/test/MyGame/Example/Monster.rs | 534 +++++++ rust/src/bin/test/MyGame/Example/Stat.rs | 157 ++ rust/src/bin/test/MyGame/Example/Test.rs | 49 + .../MyGame/Example/TestSimpleTableWithEnum.rs | 129 ++ rust/src/bin/test/MyGame/Example/Vec3.rs | 82 ++ rust/src/bin/test/MyGame/Example/mod.rs | 18 + rust/src/bin/test/MyGame/mod.rs | 5 + rust/src/builder.rs | 1109 +++++++++++++++ rust/src/iter.rs | 129 ++ rust/src/lib.rs | 25 + rust/src/table.rs | 225 +++ rust/src/types.rs | 19 + samples/monster_generated.h | 19 +- src/flatc.cpp | 8 + src/idl_gen_cpp.cpp | 2 +- src/idl_gen_general.cpp | 2 +- src/idl_gen_go.cpp | 2 +- src/idl_gen_php.cpp | 2 +- src/idl_gen_python.cpp | 2 +- src/idl_gen_rust.cpp | 1264 +++++++++++++++++ src/idl_gen_text.cpp | 6 +- src/idl_parser.cpp | 23 +- tests/GoTest.sh | 12 +- tests/MyGame/Example/Any.rs | 61 + tests/MyGame/Example/Color.rs | 35 + tests/MyGame/Example/Monster.rs | 534 +++++++ tests/MyGame/Example/Stat.rs | 157 ++ tests/MyGame/Example/Test.rs | 49 + .../MyGame/Example/TestSimpleTableWithEnum.rs | 129 ++ tests/MyGame/Example/Vec3.rs | 82 ++ tests/MyGame/Example/mod.rs | 18 + tests/MyGame/mod.rs | 5 + tests/RustTest.sh | 41 + 44 files changed, 5321 insertions(+), 45 deletions(-) create mode 100644 rust/.gitignore create mode 100644 rust/Cargo.lock create mode 100644 rust/Cargo.toml create mode 100644 rust/src/bin/test.rs create mode 120000 rust/src/bin/test/MyGame/Example/.#Color.rs create mode 100644 rust/src/bin/test/MyGame/Example/Any.rs create mode 100644 rust/src/bin/test/MyGame/Example/Color.rs create mode 100644 rust/src/bin/test/MyGame/Example/Monster.rs create mode 100644 rust/src/bin/test/MyGame/Example/Stat.rs create mode 100644 rust/src/bin/test/MyGame/Example/Test.rs create mode 100644 rust/src/bin/test/MyGame/Example/TestSimpleTableWithEnum.rs create mode 100644 rust/src/bin/test/MyGame/Example/Vec3.rs create mode 100644 rust/src/bin/test/MyGame/Example/mod.rs create mode 100644 rust/src/bin/test/MyGame/mod.rs create mode 100644 rust/src/builder.rs create mode 100644 rust/src/iter.rs create mode 100644 rust/src/lib.rs create mode 100644 rust/src/table.rs create mode 100644 rust/src/types.rs create mode 100644 src/idl_gen_rust.cpp create mode 100644 tests/MyGame/Example/Any.rs create mode 100644 tests/MyGame/Example/Color.rs create mode 100644 tests/MyGame/Example/Monster.rs create mode 100644 tests/MyGame/Example/Stat.rs create mode 100644 tests/MyGame/Example/Test.rs create mode 100644 tests/MyGame/Example/TestSimpleTableWithEnum.rs create mode 100644 tests/MyGame/Example/Vec3.rs create mode 100644 tests/MyGame/Example/mod.rs create mode 100644 tests/MyGame/mod.rs create mode 100755 tests/RustTest.sh diff --git a/.gitignore b/.gitignore index 6f3894d064..ef653ac3c7 100755 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ *.suo *.keystore **/bin/** +!rust/src/bin/** **/gen/** **/libs/** **/obj/** @@ -42,6 +43,7 @@ flatsampletext flatsampletext.exe snapshot.sh tests/go_gen +tests/rust_gen tests/monsterdata_java_wire.mon tests/monsterdata_go_wire.mon tests/monsterdata_javascript_wire.mon @@ -61,3 +63,4 @@ java/target build/VS2010/FlatBuffers.sdf build/VS2010/FlatBuffers.opensdf build/VS2010/ipch/**/*.ipch +.editorconfig diff --git a/CMakeLists.txt b/CMakeLists.txt index b1e56d6b0e..9cab7f16fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,6 +39,7 @@ set(FlatBuffers_Compiler_SRCS src/idl_gen_php.cpp src/idl_gen_python.cpp src/idl_gen_fbs.cpp + src/idl_gen_rust.cpp src/flatc.cpp ) diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index dc385efa35..26f37864f5 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -35,24 +35,24 @@ namespace flatbuffers { // Additionally, Parser::ParseType assumes bool..string is a contiguous range // of type tokens. #define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \ - TD(NONE, "", uint8_t, byte, byte, byte, uint8) \ - TD(UTYPE, "", uint8_t, byte, byte, byte, uint8) /* begin scalar/int */ \ - TD(BOOL, "bool", uint8_t, boolean,byte, bool, bool) \ - TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8) \ - TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8) \ - TD(SHORT, "short", int16_t, short, int16, short, int16) \ - TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16) \ - TD(INT, "int", int32_t, int, int32, int, int32) \ - TD(UINT, "uint", uint32_t, int, uint32, uint, uint32) \ - TD(LONG, "long", int64_t, long, int64, long, int64) \ - TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64) /* end int */ \ - TD(FLOAT, "float", float, float, float32, float, float32) /* begin float */ \ - TD(DOUBLE, "double", double, double, float64, double, float64) /* end float/scalar */ + TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8) \ + TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8) /* begin scalar/int */ \ + TD(BOOL, "bool", uint8_t, boolean,byte, bool, bool, bool) \ + TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8) \ + TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, u8, u8) \ + TD(SHORT, "short", int16_t, short, int16, short, i16, i16) \ + TD(USHORT, "ushort", uint16_t, short, uint16, ushort, u16, u16) \ + TD(INT, "int", int32_t, int, int32, int, i32, i32) \ + TD(UINT, "uint", uint32_t, int, uint32, uint, u32, u32) \ + TD(LONG, "long", int64_t, long, int64, long, i64, i64) \ + TD(ULONG, "ulong", uint64_t, long, uint64, ulong, u64, u64) /* end int */ \ + TD(FLOAT, "float", float, float, float32, float, f32, f32) /* begin float */ \ + TD(DOUBLE, "double", double, double, float64, double, f64, f64) /* end float/scalar */ #define FLATBUFFERS_GEN_TYPES_POINTER(TD) \ - TD(STRING, "string", Offset, int, int, StringOffset, int) \ - TD(VECTOR, "", Offset, int, int, VectorOffset, int) \ - TD(STRUCT, "", Offset, int, int, int, int) \ - TD(UNION, "", Offset, int, int, int, int) + TD(STRING, "string", Offset, int, int, StringOffset, int, i32) \ + TD(VECTOR, "", Offset, int, int, VectorOffset, int, i32) \ + TD(STRUCT, "", Offset, int, int, int, int, i32) \ + TD(UNION, "", Offset, int, int, int, int, i32) // The fields are: // - enum @@ -62,12 +62,13 @@ namespace flatbuffers { // - Go type. // - C# / .Net type. // - Python type. +// - Rust type. // using these macros, we can now write code dealing with types just once, e.g. /* switch (type) { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ case BASE_TYPE_ ## ENUM: \ // do something specific to CTYPE here FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) @@ -84,13 +85,13 @@ switch (type) { __extension__ // Stop GCC complaining about trailing comma with -Wpendantic. #endif enum BaseType { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ +#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ BASE_TYPE_ ## ENUM, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD }; -#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ +#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \ "define largest_scalar_t as " #CTYPE); FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) @@ -198,7 +199,8 @@ struct Namespace { // With max_components you can request less than the number of components // the current namespace has. std::string GetFullyQualifiedName(const std::string &name, - size_t max_components = 1000) const; + size_t max_components = 1000, + const std::string &sep = ".") const; }; // Base class for all definition types (fields, structs_, enums_). @@ -337,6 +339,7 @@ struct IDLOptions { bool generate_all; bool skip_unexpected_fields_in_json; bool generate_name_strings; + bool strict_rust; // Possible options for the more general generator below. enum Language { kJava, kCSharp, kGo, kMAX }; @@ -356,6 +359,7 @@ struct IDLOptions { generate_all(false), skip_unexpected_fields_in_json(false), generate_name_strings(false), + strict_rust(false), lang(IDLOptions::kJava) {} }; @@ -633,6 +637,13 @@ extern bool GenerateGeneral(const Parser &parser, const std::string &path, const std::string &file_name); +// Generate Rust files from the definitions in the Parser object. +// See idl_gen_rust.cpp. +extern bool GenerateRust(const Parser &parser, + const std::string &path, + const std::string &file_name); + + // Generate a schema file from the internal representation, useful after // parsing a .proto schema. extern std::string GenerateFBS(const Parser &parser, diff --git a/readme.md b/readme.md index 15dd41b111..d6d89f142c 100755 --- a/readme.md +++ b/readme.md @@ -21,7 +21,7 @@ unpacking/parsing it first, while still having great forwards/backwards compatib * JavaScript * PHP * Python - +* Rust *and many more in progress...* ## Contribution diff --git a/rust/.gitignore b/rust/.gitignore new file mode 100644 index 0000000000..a9d37c560c --- /dev/null +++ b/rust/.gitignore @@ -0,0 +1,2 @@ +target +Cargo.lock diff --git a/rust/Cargo.lock b/rust/Cargo.lock new file mode 100644 index 0000000000..bc75cc791c --- /dev/null +++ b/rust/Cargo.lock @@ -0,0 +1,12 @@ +[root] +name = "flatbuffers" +version = "0.1.0" +dependencies = [ + "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "byteorder" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + diff --git a/rust/Cargo.toml b/rust/Cargo.toml new file mode 100644 index 0000000000..e479e44da2 --- /dev/null +++ b/rust/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "flatbuffers" +version = "0.1.0" +authors = ["Joseph Dunne "] +description = "Memory Efficient Serialization Library. Flatbuffers runtime for Rust." +keywords = ["flatbuffers", "serialization", "deserialization"] +readme = "../readme.md" +license = "Apache-2.0" +homepage = "http://google.github.io/flatbuffers/index.html" +repository = "https://github.com/josephDunne/flatbuffers" + +[lib] +name = "flatbuffers" + +[[bin]] +name = "test" + +[dependencies] +byteorder = "0.5.*" + +[features] +default = [] +# Test the idl_gen_rust cpp code. +test_idl_gen = [] + diff --git a/rust/src/bin/test.rs b/rust/src/bin/test.rs new file mode 100644 index 0000000000..2668e99500 --- /dev/null +++ b/rust/src/bin/test.rs @@ -0,0 +1,237 @@ +extern crate flatbuffers; + +fn main() { + +} + +#[cfg(test)] +#[cfg(feature = "test_idl_gen")] +mod test { + #[allow(non_snake_case,dead_code,unused_imports, non_camel_case_types)] + mod MyGame; + + extern crate flatbuffers; + + use flatbuffers::*; + use self::MyGame::*; + + #[test] + fn manual_monster_build() { + let mut b = Builder::with_capacity(0); + let str = b.create_string("MyMonster"); + + b.start_vector(1, 5, 1); + b.add_u8(4); + b.add_u8(3); + b.add_u8(2); + b.add_u8(1); + b.add_u8(0); + let inv = b.end_vector(); + + b.start_object(13); + b.add_slot_i16(2, 20, 100); + let mon2 = b.end_object(); + + // Test4Vector + b.start_vector(4, 2, 1); + + // Test 0 + b.prep(2, 4); + b.pad(1); + b.add_i8(20); + b.add_i16(10); + + // Test 1 + b.prep(2, 4); + b.pad(1); + b.add_i8(40); + b.add_i16(30); + + // end testvector + let test4 = b.end_vector(); + + b.start_object(13); + + // a vec3 + b.prep(16, 32); + b.pad(2); + b.prep(2, 4); + b.pad(1); + b.add_u8(6); + b.add_i16(5); + b.pad(1); + b.add_u8(4); + b.add_f64(3.0); + b.pad(4); + b.add_f32(3.0); + b.add_f32(2.0); + b.add_f32(1.0); + let vec3_loc = b.offset(); + // end vec3 + + b.add_slot_struct(0, vec3_loc as u32, 0); // vec3. noop + b.add_slot_i16(2, 80, 100); // hp + b.add_slot_uoffset(3, str as u32, 0); + b.add_slot_uoffset(5, inv as u32, 0); // inventory + b.add_slot_u8(7, 1, 0); + b.add_slot_uoffset(8, mon2 as u32, 0); + b.add_slot_uoffset(9, test4 as u32, 0); + let mon = b.end_object(); + + b.finish(mon); + } + + fn build_monster() { + let mut b = example::monster::Builder::with_capacity(0); + let name = b.create_string("MyMonster"); + let test1 = b.create_string("test1"); + let test2 = b.create_string("test2"); + let fred = b.create_string("Fred"); + b.start_inventory_vector(5); + b.add_u8(4); + b.add_u8(3); + b.add_u8(2); + b.add_u8(1); + b.add_u8(0); + let inv = b.end_vector(); + + b.start(); + b.add_name(fred); + let mon2 = b.end(); + + b.start_test4_vector(2); + b.build_test(10, 20); + b.build_test(30, 40); + let test4 = b.end_vector(); + + b.start_testarrayofstring_vector(2); + b.add_uoffset(test2); + b.add_uoffset(test1); + let test_array = b.end_vector(); + + let mut stat = example::stat::Builder::from_other(b); + let stat_id = stat.create_string("way out..statistical"); + stat.start(); + stat.add_id(stat_id); + stat.add_val(20); + stat.add_count(0); + let stat_offset = stat.end(); + + b = example::monster::Builder::from_other(stat); + + b.start(); + let pos = b.build_vec3(1.0, 2.0, 3.0, 3.0, 2, 5, 6); + b.add_pos(pos); + + b.add_hp(80); + b.add_name(name); + b.add_inventory(inv); + b.add_test_type(1); + b.add_test(mon2); + b.add_test4(test4); + b.add_testempty(stat_offset); + b.add_testarrayofstring(test_array); + let mon = b.end(); + + b.finish(mon); + } + + #[test] + fn build_monster_with_generated() { + build_monster(); + } + + #[test] + fn can_read_monster() { + use std::env; + use std::path::Path; + use std::io::{Read, BufReader}; + use std::fs::File; + let mut data_path = env::current_exe().unwrap(); + data_path.pop(); + data_path.pop(); + data_path.pop(); //create root + data_path.push(Path::new("monsterdata_test.mon")); + let f1 = File::open(data_path).unwrap(); + let mut reader = BufReader::new(f1); + let mut buf: Vec = Vec::new(); + reader.read_to_end(&mut buf).unwrap(); + let monster = example::monster::Monster::new(&buf, 0); + let got = monster.hp(); + assert!(got == 80, "bad {}: want {:?} got {:?}", "HP", 80, got); + let got = monster.mana(); + assert!(got == 150, "bad {}: want {:?} got {:?}", "Mana", 150, got); + let got = monster.name(); + assert!(got == "MyMonster", "bad {}: want {:?} got {:?}", "Name", "MyMonster", got); + let vec3 = monster.pos(); + assert!(vec3.is_some(), "bad {}: want {:?} got {:?}", "Pos", "Vec3", "None"); + // verify the properties of the Vec3 + let vec3 = vec3.unwrap(); + let got = vec3.x(); + assert!(got == 1.0, "bad {}: want {:?} got {:?}", "Vec3.x", "1.0", got); + let got = vec3.y(); + assert!(got == 2.0, "bad {}: want {:?} got {:?}", "Vec3.x", "2.0", got); + let got = vec3.z(); + assert!(got == 3.0, "bad {}: want {:?} got {:?}", "Vec3.x", "3.0", got); + let got = vec3.test1(); + assert!(got == 3.0, "bad {}: want {:?} got {:?}", "Vec3.test1", "3.0", got); + let got = vec3.test2(); + assert!(got == example::Color::Green, "bad {}: want {:?} got {:?}", + "Vec3.test2", "Color::Green", got); + // Verify properties of test3 + let test3 = vec3.test3(); + let got = test3.a(); + assert!(got == 5, "bad {}: want {:?} got {:?}", "Test.a", "5", got); + let got = test3.b(); + assert!(got == 6, "bad {}: want {:?} got {:?}", "Test.b", "6", got); + // Verify test type + let got = monster.test_type(); + assert!(got == example::Any::Monster, "bad {}: want {:?} got {:?}", "TestType", "Monster", got); + // initialize a Table from a union field + let got = monster.test(); + if let example::AnyUnion::Monster(monster2) = got { + let got = monster2.name(); + assert!(got == "Fred", "bad {}: want {:?} got {:?}", "Name", "Fred", got); + } else { + panic!( "bad {}: want {:?} got {:?}", "Test", "Monster Union", got) + } + let got = monster.inventory(); + assert!(got.len() == 5, "bad {}: want {:?} got {:?}", + "Inventory", "Byte Vector of length 5", got); + use std::ops::Add; + let got: u8 = got.iter().fold(0, Add::add); + assert!(got == 10, "bad {}: want {:?} got {:?}", "Inventory Sum", "10", got); + // Test4 + let mut got = monster.test4(); + assert!(got.len() == 2, "bad {}: want {:?} got {:?}", "Test4 vector length", "4", got.len()); + let test1 = got.next().unwrap(); + let test2 = got.next().unwrap(); + assert!(test1.a() == 10, "bad {}: want {:?} got {:?}", "Test4 array test1.a", "10", test1.a()); + assert!(test1.b() == 20, "bad {}: want {:?} got {:?}", "Test4 array test1.b", "20", test1.b()); + assert!(test2.a() == 30, "bad {}: want {:?} got {:?}", "Test4 array test2.a", "30", test2.a()); + assert!(test2.b() == 40, "bad {}: want {:?} got {:?}", "Test4 array test2.b", "40", test2.b()); + // Test Array of string + let mut got = monster.testarrayofstring(); + assert!(got.len() == 2, "bad {}: want {:?} got {:?}", "Test4 string vector length", "2", got.len()); + let str1 = got.next().unwrap(); + let str2 = got.next().unwrap(); + assert!(str1 == "test1", "bad {}: want {:?} got {:?}", "Test string array 1", "test1", str1); + assert!(str2 == "test2", "bad {}: want {:?} got {:?}", "Test string array 2", "test2", str2); + // array of tables + let got = monster.testarrayoftables(); + assert_eq!(got.len(),0); + } + + + + // until benchmark tests are stablized in Rust... + #[test] + fn bench_build() { + use std::time::Instant; + let now = Instant::now(); + for _ in 1..10000 { + build_monster() + } + println!("Building 1000 took {:?}", now.elapsed()); + } +} diff --git a/rust/src/bin/test/MyGame/Example/.#Color.rs b/rust/src/bin/test/MyGame/Example/.#Color.rs new file mode 120000 index 0000000000..1bbcfe1b33 --- /dev/null +++ b/rust/src/bin/test/MyGame/Example/.#Color.rs @@ -0,0 +1 @@ +jo@MULTIVAC.local.11340 \ No newline at end of file diff --git a/rust/src/bin/test/MyGame/Example/Any.rs b/rust/src/bin/test/MyGame/Example/Any.rs new file mode 100644 index 0000000000..24cc67be6f --- /dev/null +++ b/rust/src/bin/test/MyGame/Example/Any.rs @@ -0,0 +1,61 @@ +//! Automatically generated, do not modify. + +use flatbuffers; +use super::*; + +#[derive(PartialEq, Eq, Clone, Debug, Hash)] +#[repr(u8)] +pub enum Any { + NONE = 0, + Monster = 1, + TestSimpleTableWithEnum = 2, +} + +/// A List of all `Any` enum variants. +pub const ANY_LIST: [Any;3] = [Any::NONE,Any::Monster,Any::TestSimpleTableWithEnum,]; + +impl Any { + /// Returns a `str` representation of a `Any` enum. + pub fn name(&self) -> &'static str { + match *self { + Any::NONE => "NONE", + Any::Monster => "Monster", + Any::TestSimpleTableWithEnum => "TestSimpleTableWithEnum", + } + } +} + +impl From for Any { + fn from(value: u8) -> Any { + match value { + 0 => Any::NONE, + 1 => Any::Monster, + 2 => Any::TestSimpleTableWithEnum, + _ => unreachable!("Unable to create a `Any` from value {} ", value), + } + } +} + +#[derive(Debug)] +pub enum AnyUnion<'a> { + None, + Monster(Monster<'a>), + TestSimpleTableWithEnum(TestSimpleTableWithEnum<'a>), +} + +impl<'a> AnyUnion<'a> { + pub fn from_type(table: &'a flatbuffers::Table, t: Any, offset: usize) -> AnyUnion<'a> { + match t { + Any::NONE => { + AnyUnion::None + } + Any::Monster => { + AnyUnion::Monster(table.get_root(offset as u32).into()) + } + Any::TestSimpleTableWithEnum => { + AnyUnion::TestSimpleTableWithEnum(table.get_root(offset as u32).into()) + } + } + } +} + diff --git a/rust/src/bin/test/MyGame/Example/Color.rs b/rust/src/bin/test/MyGame/Example/Color.rs new file mode 100644 index 0000000000..d60b7ac5cb --- /dev/null +++ b/rust/src/bin/test/MyGame/Example/Color.rs @@ -0,0 +1,35 @@ +//! Automatically generated, do not modify. + +#[derive(PartialEq, Eq, Clone, Debug, Hash)] +#[repr(i8)] +pub enum Color { + Red = 1, + Green = 2, + Blue = 8, +} + +/// A List of all `Color` enum variants. +pub const COLOR_LIST: [Color;3] = [Color::Red,Color::Green,Color::Blue,]; + +impl Color { + /// Returns a `str` representation of a `Color` enum. + pub fn name(&self) -> &'static str { + match *self { + Color::Red => "Red", + Color::Green => "Green", + Color::Blue => "Blue", + } + } +} + +impl From for Color { + fn from(value: i8) -> Color { + match value { + 1 => Color::Red, + 2 => Color::Green, + 8 => Color::Blue, + _ => unreachable!("Unable to create a `Color` from value {} ", value), + } + } +} + diff --git a/rust/src/bin/test/MyGame/Example/Monster.rs b/rust/src/bin/test/MyGame/Example/Monster.rs new file mode 100644 index 0000000000..f89ff78d26 --- /dev/null +++ b/rust/src/bin/test/MyGame/Example/Monster.rs @@ -0,0 +1,534 @@ +//! Automatically generated, do not modify. + +use flatbuffers; +use super::*; + +/// an example documentation comment: monster object +#[derive(Debug)] +pub struct Monster<'a> { + table: flatbuffers::Table<'a>, +} + +enum VT { + POS = 4, + MANA = 6, + HP = 8, + NAME = 10, + INVENTORY = 14, + COLOR = 16, + TEST_TYPE = 18, + TEST = 20, + TEST4 = 22, + TESTARRAYOFSTRING = 24, + TESTARRAYOFTABLES = 26, + ENEMY = 28, + TESTNESTEDFLATBUFFER = 30, + TESTEMPTY = 32, + TESTBOOL = 34, + TESTHASHS32_FNV1 = 36, + TESTHASHU32_FNV1 = 38, + TESTHASHS64_FNV1 = 40, + TESTHASHU64_FNV1 = 42, + TESTHASHS32_FNV1A = 44, + TESTHASHU32_FNV1A = 46, + TESTHASHS64_FNV1A = 48, + TESTHASHU64_FNV1A = 50, + TESTARRAYOFBOOLS = 52, + TESTF = 54, + TESTF2 = 56, + TESTF3 = 58, +} + +impl<'a> Monster<'a> { + pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> Monster { + Monster { + table: flatbuffers::Table::from_offset(buf, offset), + } + } + + pub fn pos(&self) -> Option { + let offset = self.table.field_offset(VT::POS as u16); + if offset != 0 { + return Some(self.table.get_struct::(offset)) + }; + None + } + + pub fn mana(&self) -> i16 { + let offset = self.table.field_offset(VT::MANA as u16); + if offset != 0 { + return self.table.get_i16(offset) + } + 150 + } + + pub fn hp(&self) -> i16 { + let offset = self.table.field_offset(VT::HP as u16); + if offset != 0 { + return self.table.get_i16(offset) + } + 100 + } + + pub fn name(&self) -> &str { + let offset = self.table.field_offset(VT::NAME as u16); + if offset != 0 { + return self.table.get_str(offset) + } + "" + } + + pub fn inventory(&self) -> &[u8] { + let offset = self.table.field_offset(VT::INVENTORY as u16); + if offset != 0 { + return self.table.byte_vector(offset); + } + &[] + } + + pub fn color(&self) -> Color { + let offset = self.table.field_offset(VT::COLOR as u16); + if offset != 0 { + return self.table.get_i8(offset).into() + } + 8.into() + } + + pub fn test_type(&self) -> Any { + let offset = self.table.field_offset(VT::TEST_TYPE as u16); + if offset != 0 { + return self.table.get_u8(offset).into() + } + 0.into() + } + + pub fn test(&self) -> AnyUnion { + let offset = self.table.field_offset(VT::TEST as u16); + if offset != 0 { + let t = self.test_type(); + return AnyUnion::from_type(&self.table, t, offset as usize); + } + AnyUnion::None + } + + pub fn test4(&self) -> flatbuffers::Iterator { + let offset = self.table.field_offset(VT::TEST4 as u16); + if offset != 0 { + return self.table.struct_vector(offset) + } + flatbuffers::empty_iterator(&self.table) + } + + pub fn testarrayofstring(&self) -> flatbuffers::Iterator<&str> { + let offset = self.table.field_offset(VT::TESTARRAYOFSTRING as u16); + if offset != 0 { + return self.table.str_vector(offset); + } + flatbuffers::empty_iterator(&self.table) } + + /// an example documentation comment: this will end up in the generated code + /// multiline too + pub fn testarrayoftables(&self) -> flatbuffers::Iterator { + let offset = self.table.field_offset(VT::TESTARRAYOFTABLES as u16); + if offset != 0 { + return self.table.table_vector(offset) + } + flatbuffers::empty_iterator(&self.table) + } + + pub fn enemy(&self) -> Option { + let offset = self.table.field_offset(VT::ENEMY as u16); + if offset != 0 { + return Some(self.table.get_indirect_root(offset).into()) + }; + None + } + + pub fn testnestedflatbuffer(&self) -> &[u8] { + let offset = self.table.field_offset(VT::TESTNESTEDFLATBUFFER as u16); + if offset != 0 { + return self.table.byte_vector(offset); + } + &[] + } + + pub fn testempty(&self) -> Option { + let offset = self.table.field_offset(VT::TESTEMPTY as u16); + if offset != 0 { + return Some(self.table.get_indirect_root(offset).into()) + }; + None + } + + pub fn testbool(&self) -> bool { + let offset = self.table.field_offset(VT::TESTBOOL as u16); + if offset != 0 { + return self.table.get_bool(offset) + } + false + } + + pub fn testhashs32_fnv1(&self) -> i32 { + let offset = self.table.field_offset(VT::TESTHASHS32_FNV1 as u16); + if offset != 0 { + return self.table.get_i32(offset) + } + 0 + } + + pub fn testhashu32_fnv1(&self) -> u32 { + let offset = self.table.field_offset(VT::TESTHASHU32_FNV1 as u16); + if offset != 0 { + return self.table.get_u32(offset) + } + 0 + } + + pub fn testhashs64_fnv1(&self) -> i64 { + let offset = self.table.field_offset(VT::TESTHASHS64_FNV1 as u16); + if offset != 0 { + return self.table.get_i64(offset) + } + 0 + } + + pub fn testhashu64_fnv1(&self) -> u64 { + let offset = self.table.field_offset(VT::TESTHASHU64_FNV1 as u16); + if offset != 0 { + return self.table.get_u64(offset) + } + 0 + } + + pub fn testhashs32_fnv1a(&self) -> i32 { + let offset = self.table.field_offset(VT::TESTHASHS32_FNV1A as u16); + if offset != 0 { + return self.table.get_i32(offset) + } + 0 + } + + pub fn testhashu32_fnv1a(&self) -> u32 { + let offset = self.table.field_offset(VT::TESTHASHU32_FNV1A as u16); + if offset != 0 { + return self.table.get_u32(offset) + } + 0 + } + + pub fn testhashs64_fnv1a(&self) -> i64 { + let offset = self.table.field_offset(VT::TESTHASHS64_FNV1A as u16); + if offset != 0 { + return self.table.get_i64(offset) + } + 0 + } + + pub fn testhashu64_fnv1a(&self) -> u64 { + let offset = self.table.field_offset(VT::TESTHASHU64_FNV1A as u16); + if offset != 0 { + return self.table.get_u64(offset) + } + 0 + } + + pub fn testarrayofbools(&self) -> &[bool] { + let offset = self.table.field_offset(VT::TESTARRAYOFBOOLS as u16); + if offset != 0 { + return self.table.bool_vector(offset); + } + &[] + } + + pub fn testf(&self) -> f32 { + let offset = self.table.field_offset(VT::TESTF as u16); + if offset != 0 { + return self.table.get_f32(offset) + } + 3.14159 + } + + pub fn testf2(&self) -> f32 { + let offset = self.table.field_offset(VT::TESTF2 as u16); + if offset != 0 { + return self.table.get_f32(offset) + } + 3.0 + } + + pub fn testf3(&self) -> f32 { + let offset = self.table.field_offset(VT::TESTF3 as u16); + if offset != 0 { + return self.table.get_f32(offset) + } + 0.0 + } + +} + +impl<'a> From> for Monster<'a> { + fn from(table: flatbuffers::Table) -> Monster { + Monster{ + table: table, + } + } +} + +/// Builder Object for `Monster` tables. +pub struct Builder { + inner: flatbuffers::Builder, +} + +impl Builder { + /// Create a new builder. + pub fn with_capacity(size: usize) -> Self { + Builder { + inner: flatbuffers::Builder::with_capacity(size), + } + } + + /// Initialize a new `Builder` for a `Monster` table. + pub fn start(&mut self) { + self.inner.start_object(28); + } + + /// Finalize the current object and return the offset. + pub fn end(&mut self) -> flatbuffers::UOffsetT { + return self.inner.end_object() + } + + /// Set the value for field `pos`. + pub fn add_pos(&mut self, pos: flatbuffers::UOffsetT) { + self.inner.add_slot_struct(0, pos, 0) + } + + /// Set the value for field `mana`. + pub fn add_mana(&mut self, mana: i16) { + self.inner.add_slot_i16(1, mana, 150) + } + + /// Set the value for field `hp`. + pub fn add_hp(&mut self, hp: i16) { + self.inner.add_slot_i16(2, hp, 100) + } + + /// Set the value for field `name`. + pub fn add_name(&mut self, name: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(3, name, 0) + } + + /// Set the value for field `inventory`. + pub fn add_inventory(&mut self, inventory: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(5, inventory, 0) + } + + /// Initializes bookkeeping for writing a new `inventory` vector. + pub fn start_inventory_vector(&mut self, numElems: usize) { + self.inner.start_vector(1, numElems, 1) + } + + /// Set the value for field `color`. + pub fn add_color(&mut self, color: i8) { + self.inner.add_slot_i8(6, color, 8) + } + + /// Set the value for field `test_type`. + pub fn add_test_type(&mut self, test_type: u8) { + self.inner.add_slot_u8(7, test_type, 0) + } + + /// Set the value for field `test`. + pub fn add_test(&mut self, test: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(8, test, 0) + } + + /// Set the value for field `test4`. + pub fn add_test4(&mut self, test4: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(9, test4, 0) + } + + /// Initializes bookkeeping for writing a new `test4` vector. + pub fn start_test4_vector(&mut self, numElems: usize) { + self.inner.start_vector(4, numElems, 2) + } + + /// Set the value for field `testarrayofstring`. + pub fn add_testarrayofstring(&mut self, testarrayofstring: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(10, testarrayofstring, 0) + } + + /// Initializes bookkeeping for writing a new `testarrayofstring` vector. + pub fn start_testarrayofstring_vector(&mut self, numElems: usize) { + self.inner.start_vector(4, numElems, 4) + } + + /// Set the value for field `testarrayoftables`. + pub fn add_testarrayoftables(&mut self, testarrayoftables: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(11, testarrayoftables, 0) + } + + /// Initializes bookkeeping for writing a new `testarrayoftables` vector. + pub fn start_testarrayoftables_vector(&mut self, numElems: usize) { + self.inner.start_vector(4, numElems, 4) + } + + /// Set the value for field `enemy`. + pub fn add_enemy(&mut self, enemy: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(12, enemy, 0) + } + + /// Set the value for field `testnestedflatbuffer`. + pub fn add_testnestedflatbuffer(&mut self, testnestedflatbuffer: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(13, testnestedflatbuffer, 0) + } + + /// Initializes bookkeeping for writing a new `testnestedflatbuffer` vector. + pub fn start_testnestedflatbuffer_vector(&mut self, numElems: usize) { + self.inner.start_vector(1, numElems, 1) + } + + /// Set the value for field `testempty`. + pub fn add_testempty(&mut self, testempty: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(14, testempty, 0) + } + + /// Set the value for field `testbool`. + pub fn add_testbool(&mut self, testbool: bool) { + self.inner.add_slot_bool(15, testbool, false) + } + + /// Set the value for field `testhashs32_fnv1`. + pub fn add_testhashs32_fnv1(&mut self, testhashs32_fnv1: i32) { + self.inner.add_slot_i32(16, testhashs32_fnv1, 0) + } + + /// Set the value for field `testhashu32_fnv1`. + pub fn add_testhashu32_fnv1(&mut self, testhashu32_fnv1: u32) { + self.inner.add_slot_u32(17, testhashu32_fnv1, 0) + } + + /// Set the value for field `testhashs64_fnv1`. + pub fn add_testhashs64_fnv1(&mut self, testhashs64_fnv1: i64) { + self.inner.add_slot_i64(18, testhashs64_fnv1, 0) + } + + /// Set the value for field `testhashu64_fnv1`. + pub fn add_testhashu64_fnv1(&mut self, testhashu64_fnv1: u64) { + self.inner.add_slot_u64(19, testhashu64_fnv1, 0) + } + + /// Set the value for field `testhashs32_fnv1a`. + pub fn add_testhashs32_fnv1a(&mut self, testhashs32_fnv1a: i32) { + self.inner.add_slot_i32(20, testhashs32_fnv1a, 0) + } + + /// Set the value for field `testhashu32_fnv1a`. + pub fn add_testhashu32_fnv1a(&mut self, testhashu32_fnv1a: u32) { + self.inner.add_slot_u32(21, testhashu32_fnv1a, 0) + } + + /// Set the value for field `testhashs64_fnv1a`. + pub fn add_testhashs64_fnv1a(&mut self, testhashs64_fnv1a: i64) { + self.inner.add_slot_i64(22, testhashs64_fnv1a, 0) + } + + /// Set the value for field `testhashu64_fnv1a`. + pub fn add_testhashu64_fnv1a(&mut self, testhashu64_fnv1a: u64) { + self.inner.add_slot_u64(23, testhashu64_fnv1a, 0) + } + + /// Set the value for field `testarrayofbools`. + pub fn add_testarrayofbools(&mut self, testarrayofbools: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(24, testarrayofbools, 0) + } + + /// Initializes bookkeeping for writing a new `testarrayofbools` vector. + pub fn start_testarrayofbools_vector(&mut self, numElems: usize) { + self.inner.start_vector(1, numElems, 1) + } + + /// Set the value for field `testf`. + pub fn add_testf(&mut self, testf: f32) { + self.inner.add_slot_f32(25, testf, 3.14159) + } + + /// Set the value for field `testf2`. + pub fn add_testf2(&mut self, testf2: f32) { + self.inner.add_slot_f32(26, testf2, 3.0) + } + + /// Set the value for field `testf3`. + pub fn add_testf3(&mut self, testf3: f32) { + self.inner.add_slot_f32(27, testf3, 0.0) + } + + pub fn build_vec3(&mut self , x: f32, y: f32, z: f32, test1: f64, test2: i8, test3_a: i16, test3_b: i8) -> flatbuffers::UOffsetT { + vec3::build_vec3(&mut self.inner, x, y, z, test1, test2, test3_a, test3_b) + } + + pub fn build_test(&mut self , a: i16, b: i8) -> flatbuffers::UOffsetT { + test::build_test(&mut self.inner, a, b) + } + + /// Finish the buffer. + pub fn finish(&mut self, r: flatbuffers::UOffsetT) { + return self.inner.finish(r) + } + + pub fn create_string(&mut self, v: &str) -> flatbuffers::UOffsetT { self.inner.create_string(v) } + pub fn get_bytes(&self) -> &[u8] { self.inner.get_bytes() } + pub fn len(&self) -> usize { self.inner.len() } + pub fn offset(&self) -> usize { self.inner.offset() } + pub fn reset(&mut self) { self.inner.reset() } + pub fn prep(&mut self, s:usize, a: usize) { self.inner.prep(s,a) } + pub fn pad(&mut self, n:usize) { self.inner.pad(n) } + pub fn end_vector(&mut self) -> flatbuffers::UOffsetT { self.inner.end_vector() } + pub fn add_bool(&mut self, v:bool) { self.inner.add_bool(v) } + pub fn add_u8(&mut self, v:u8) { self.inner.add_u8(v) } + pub fn add_i8(&mut self, v:i8) { self.inner.add_i8(v) } + pub fn add_u16(&mut self, v:u16) { self.inner.add_u16(v) } + pub fn add_i16(&mut self, v:i16) { self.inner.add_i16(v) } + pub fn add_u32(&mut self, v:u32) { self.inner.add_u32(v) } + pub fn add_i32(&mut self, v:i32) { self.inner.add_i32(v) } + pub fn add_u64(&mut self, v:u64) { self.inner.add_u64(v) } + pub fn add_i64(&mut self, v:i64) { self.inner.add_i64(v) } + pub fn add_f32(&mut self, v:f32) { self.inner.add_f32(v) } + pub fn add_f64(&mut self, v:f64) { self.inner.add_f64(v) } + pub fn add_uoffset(&mut self, v: flatbuffers::UOffsetT) { self.inner.add_uoffset(v) } + pub fn add_slot_bool(&mut self, o: usize, v: bool, d: bool) { self.inner.add_slot_bool(o,v,d) } + pub fn add_slot_u8(&mut self, o: usize, v: u8, d: u8) { self.inner.add_slot_u8(o,v,d) } + pub fn add_slot_i8(&mut self, o: usize, v: i8, d: i8) { self.inner.add_slot_i8(o,v,d) } + pub fn add_slot_u16(&mut self, o: usize, v: u16, d: u16) { self.inner.add_slot_u16(o,v,d) } + pub fn add_slot_i16(&mut self, o: usize, v: i16, d: i16) { self.inner.add_slot_i16(o,v,d) } + pub fn add_slot_i32(&mut self, o: usize, v: i32, d: i32) { self.inner.add_slot_i32(o,v,d) } + pub fn add_slot_u32(&mut self, o: usize, v: u32, d: u32) { self.inner.add_slot_u32(o,v,d) } + pub fn add_slot_u64(&mut self, o: usize, v: u64, d: u64) { self.inner.add_slot_u64(o,v,d) } + pub fn add_slot_i64(&mut self, o: usize, v: i64, d: i64) { self.inner.add_slot_i64(o,v,d) } + pub fn add_slot_f32(&mut self, o: usize, v: f32, d: f32) { self.inner.add_slot_f32(o,v,d) } + pub fn add_slot_f64(&mut self, o: usize, v: f64, d: f64) { self.inner.add_slot_f64(o,v,d) } + pub fn add_slot_uoffset(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_uoffset(o,v,d) } + pub fn add_slot_struct(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_struct(o,v,d) } +} + +impl Default for Builder { + fn default() -> Builder { + Builder::with_capacity(1024) + } +} + +impl From for Builder { + fn from(b: flatbuffers::Builder) -> Builder { + Builder { + inner: b, + } + } +} + +impl Into for Builder { + fn into(self) -> flatbuffers::Builder { + self.inner + } +} + +impl flatbuffers::ObjectBuilder for Builder {} + diff --git a/rust/src/bin/test/MyGame/Example/Stat.rs b/rust/src/bin/test/MyGame/Example/Stat.rs new file mode 100644 index 0000000000..4bccf31436 --- /dev/null +++ b/rust/src/bin/test/MyGame/Example/Stat.rs @@ -0,0 +1,157 @@ +//! Automatically generated, do not modify. + +use flatbuffers; +use super::*; + +#[derive(Debug)] +pub struct Stat<'a> { + table: flatbuffers::Table<'a>, +} + +enum VT { + ID = 4, + VAL = 6, + COUNT = 8, +} + +impl<'a> Stat<'a> { + pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> Stat { + Stat { + table: flatbuffers::Table::from_offset(buf, offset), + } + } + + pub fn id(&self) -> &str { + let offset = self.table.field_offset(VT::ID as u16); + if offset != 0 { + return self.table.get_str(offset) + } + "" + } + + pub fn val(&self) -> i64 { + let offset = self.table.field_offset(VT::VAL as u16); + if offset != 0 { + return self.table.get_i64(offset) + } + 0 + } + + pub fn count(&self) -> u16 { + let offset = self.table.field_offset(VT::COUNT as u16); + if offset != 0 { + return self.table.get_u16(offset) + } + 0 + } + +} + +impl<'a> From> for Stat<'a> { + fn from(table: flatbuffers::Table) -> Stat { + Stat{ + table: table, + } + } +} + +/// Builder Object for `Stat` tables. +pub struct Builder { + inner: flatbuffers::Builder, +} + +impl Builder { + /// Create a new builder. + pub fn with_capacity(size: usize) -> Self { + Builder { + inner: flatbuffers::Builder::with_capacity(size), + } + } + + /// Initialize a new `Builder` for a `Stat` table. + pub fn start(&mut self) { + self.inner.start_object(3); + } + + /// Finalize the current object and return the offset. + pub fn end(&mut self) -> flatbuffers::UOffsetT { + return self.inner.end_object() + } + + /// Set the value for field `id`. + pub fn add_id(&mut self, id: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(0, id, 0) + } + + /// Set the value for field `val`. + pub fn add_val(&mut self, val: i64) { + self.inner.add_slot_i64(1, val, 0) + } + + /// Set the value for field `count`. + pub fn add_count(&mut self, count: u16) { + self.inner.add_slot_u16(2, count, 0) + } + + /// Finish the buffer. + pub fn finish(&mut self, r: flatbuffers::UOffsetT) { + return self.inner.finish(r) + } + + pub fn create_string(&mut self, v: &str) -> flatbuffers::UOffsetT { self.inner.create_string(v) } + pub fn get_bytes(&self) -> &[u8] { self.inner.get_bytes() } + pub fn len(&self) -> usize { self.inner.len() } + pub fn offset(&self) -> usize { self.inner.offset() } + pub fn reset(&mut self) { self.inner.reset() } + pub fn prep(&mut self, s:usize, a: usize) { self.inner.prep(s,a) } + pub fn pad(&mut self, n:usize) { self.inner.pad(n) } + pub fn end_vector(&mut self) -> flatbuffers::UOffsetT { self.inner.end_vector() } + pub fn add_bool(&mut self, v:bool) { self.inner.add_bool(v) } + pub fn add_u8(&mut self, v:u8) { self.inner.add_u8(v) } + pub fn add_i8(&mut self, v:i8) { self.inner.add_i8(v) } + pub fn add_u16(&mut self, v:u16) { self.inner.add_u16(v) } + pub fn add_i16(&mut self, v:i16) { self.inner.add_i16(v) } + pub fn add_u32(&mut self, v:u32) { self.inner.add_u32(v) } + pub fn add_i32(&mut self, v:i32) { self.inner.add_i32(v) } + pub fn add_u64(&mut self, v:u64) { self.inner.add_u64(v) } + pub fn add_i64(&mut self, v:i64) { self.inner.add_i64(v) } + pub fn add_f32(&mut self, v:f32) { self.inner.add_f32(v) } + pub fn add_f64(&mut self, v:f64) { self.inner.add_f64(v) } + pub fn add_uoffset(&mut self, v: flatbuffers::UOffsetT) { self.inner.add_uoffset(v) } + pub fn add_slot_bool(&mut self, o: usize, v: bool, d: bool) { self.inner.add_slot_bool(o,v,d) } + pub fn add_slot_u8(&mut self, o: usize, v: u8, d: u8) { self.inner.add_slot_u8(o,v,d) } + pub fn add_slot_i8(&mut self, o: usize, v: i8, d: i8) { self.inner.add_slot_i8(o,v,d) } + pub fn add_slot_u16(&mut self, o: usize, v: u16, d: u16) { self.inner.add_slot_u16(o,v,d) } + pub fn add_slot_i16(&mut self, o: usize, v: i16, d: i16) { self.inner.add_slot_i16(o,v,d) } + pub fn add_slot_i32(&mut self, o: usize, v: i32, d: i32) { self.inner.add_slot_i32(o,v,d) } + pub fn add_slot_u32(&mut self, o: usize, v: u32, d: u32) { self.inner.add_slot_u32(o,v,d) } + pub fn add_slot_u64(&mut self, o: usize, v: u64, d: u64) { self.inner.add_slot_u64(o,v,d) } + pub fn add_slot_i64(&mut self, o: usize, v: i64, d: i64) { self.inner.add_slot_i64(o,v,d) } + pub fn add_slot_f32(&mut self, o: usize, v: f32, d: f32) { self.inner.add_slot_f32(o,v,d) } + pub fn add_slot_f64(&mut self, o: usize, v: f64, d: f64) { self.inner.add_slot_f64(o,v,d) } + pub fn add_slot_uoffset(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_uoffset(o,v,d) } + pub fn add_slot_struct(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_struct(o,v,d) } +} + +impl Default for Builder { + fn default() -> Builder { + Builder::with_capacity(1024) + } +} + +impl From for Builder { + fn from(b: flatbuffers::Builder) -> Builder { + Builder { + inner: b, + } + } +} + +impl Into for Builder { + fn into(self) -> flatbuffers::Builder { + self.inner + } +} + +impl flatbuffers::ObjectBuilder for Builder {} + diff --git a/rust/src/bin/test/MyGame/Example/Test.rs b/rust/src/bin/test/MyGame/Example/Test.rs new file mode 100644 index 0000000000..55f3baf290 --- /dev/null +++ b/rust/src/bin/test/MyGame/Example/Test.rs @@ -0,0 +1,49 @@ +//! Automatically generated, do not modify. + +use flatbuffers; +use super::*; + +#[derive(Debug)] +pub struct Test<'a> { + table: flatbuffers::Table<'a>, +} + +enum VT { + A = 0, + B = 2,// Padding1 +} + +impl<'a> Test<'a> { + pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> Test { + Test { + table: flatbuffers::Table::with_pos(buf, offset), + } + } + + pub fn a(&self) -> i16 { + let offset = VT::A as u32; + return self.table.get_i16(offset) + } + + pub fn b(&self) -> i8 { + let offset = VT::B as u32; + return self.table.get_i8(offset) + } + +} + +impl<'a> From> for Test<'a> { + fn from(table: flatbuffers::Table) -> Test { + Test{ + table: table, + } + } +} + +pub fn build_test(builder: &mut flatbuffers::Builder, a: i16, b: i8) -> flatbuffers::UOffsetT { + builder.prep(2, 4); + builder.pad(1); + builder.add_i8(b); + builder.add_i16(a); + builder.offset() as flatbuffers::UOffsetT +} diff --git a/rust/src/bin/test/MyGame/Example/TestSimpleTableWithEnum.rs b/rust/src/bin/test/MyGame/Example/TestSimpleTableWithEnum.rs new file mode 100644 index 0000000000..b6ccba8914 --- /dev/null +++ b/rust/src/bin/test/MyGame/Example/TestSimpleTableWithEnum.rs @@ -0,0 +1,129 @@ +//! Automatically generated, do not modify. + +use flatbuffers; +use super::*; + +#[derive(Debug)] +pub struct TestSimpleTableWithEnum<'a> { + table: flatbuffers::Table<'a>, +} + +enum VT { + COLOR = 4, +} + +impl<'a> TestSimpleTableWithEnum<'a> { + pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> TestSimpleTableWithEnum { + TestSimpleTableWithEnum { + table: flatbuffers::Table::from_offset(buf, offset), + } + } + + pub fn color(&self) -> Color { + let offset = self.table.field_offset(VT::COLOR as u16); + if offset != 0 { + return self.table.get_i8(offset).into() + } + 2.into() + } + +} + +impl<'a> From> for TestSimpleTableWithEnum<'a> { + fn from(table: flatbuffers::Table) -> TestSimpleTableWithEnum { + TestSimpleTableWithEnum{ + table: table, + } + } +} + +/// Builder Object for `TestSimpleTableWithEnum` tables. +pub struct Builder { + inner: flatbuffers::Builder, +} + +impl Builder { + /// Create a new builder. + pub fn with_capacity(size: usize) -> Self { + Builder { + inner: flatbuffers::Builder::with_capacity(size), + } + } + + /// Initialize a new `Builder` for a `TestSimpleTableWithEnum` table. + pub fn start(&mut self) { + self.inner.start_object(1); + } + + /// Finalize the current object and return the offset. + pub fn end(&mut self) -> flatbuffers::UOffsetT { + return self.inner.end_object() + } + + /// Set the value for field `color`. + pub fn add_color(&mut self, color: i8) { + self.inner.add_slot_i8(0, color, 2) + } + + /// Finish the buffer. + pub fn finish(&mut self, r: flatbuffers::UOffsetT) { + return self.inner.finish(r) + } + + pub fn create_string(&mut self, v: &str) -> flatbuffers::UOffsetT { self.inner.create_string(v) } + pub fn get_bytes(&self) -> &[u8] { self.inner.get_bytes() } + pub fn len(&self) -> usize { self.inner.len() } + pub fn offset(&self) -> usize { self.inner.offset() } + pub fn reset(&mut self) { self.inner.reset() } + pub fn prep(&mut self, s:usize, a: usize) { self.inner.prep(s,a) } + pub fn pad(&mut self, n:usize) { self.inner.pad(n) } + pub fn end_vector(&mut self) -> flatbuffers::UOffsetT { self.inner.end_vector() } + pub fn add_bool(&mut self, v:bool) { self.inner.add_bool(v) } + pub fn add_u8(&mut self, v:u8) { self.inner.add_u8(v) } + pub fn add_i8(&mut self, v:i8) { self.inner.add_i8(v) } + pub fn add_u16(&mut self, v:u16) { self.inner.add_u16(v) } + pub fn add_i16(&mut self, v:i16) { self.inner.add_i16(v) } + pub fn add_u32(&mut self, v:u32) { self.inner.add_u32(v) } + pub fn add_i32(&mut self, v:i32) { self.inner.add_i32(v) } + pub fn add_u64(&mut self, v:u64) { self.inner.add_u64(v) } + pub fn add_i64(&mut self, v:i64) { self.inner.add_i64(v) } + pub fn add_f32(&mut self, v:f32) { self.inner.add_f32(v) } + pub fn add_f64(&mut self, v:f64) { self.inner.add_f64(v) } + pub fn add_uoffset(&mut self, v: flatbuffers::UOffsetT) { self.inner.add_uoffset(v) } + pub fn add_slot_bool(&mut self, o: usize, v: bool, d: bool) { self.inner.add_slot_bool(o,v,d) } + pub fn add_slot_u8(&mut self, o: usize, v: u8, d: u8) { self.inner.add_slot_u8(o,v,d) } + pub fn add_slot_i8(&mut self, o: usize, v: i8, d: i8) { self.inner.add_slot_i8(o,v,d) } + pub fn add_slot_u16(&mut self, o: usize, v: u16, d: u16) { self.inner.add_slot_u16(o,v,d) } + pub fn add_slot_i16(&mut self, o: usize, v: i16, d: i16) { self.inner.add_slot_i16(o,v,d) } + pub fn add_slot_i32(&mut self, o: usize, v: i32, d: i32) { self.inner.add_slot_i32(o,v,d) } + pub fn add_slot_u32(&mut self, o: usize, v: u32, d: u32) { self.inner.add_slot_u32(o,v,d) } + pub fn add_slot_u64(&mut self, o: usize, v: u64, d: u64) { self.inner.add_slot_u64(o,v,d) } + pub fn add_slot_i64(&mut self, o: usize, v: i64, d: i64) { self.inner.add_slot_i64(o,v,d) } + pub fn add_slot_f32(&mut self, o: usize, v: f32, d: f32) { self.inner.add_slot_f32(o,v,d) } + pub fn add_slot_f64(&mut self, o: usize, v: f64, d: f64) { self.inner.add_slot_f64(o,v,d) } + pub fn add_slot_uoffset(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_uoffset(o,v,d) } + pub fn add_slot_struct(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_struct(o,v,d) } +} + +impl Default for Builder { + fn default() -> Builder { + Builder::with_capacity(1024) + } +} + +impl From for Builder { + fn from(b: flatbuffers::Builder) -> Builder { + Builder { + inner: b, + } + } +} + +impl Into for Builder { + fn into(self) -> flatbuffers::Builder { + self.inner + } +} + +impl flatbuffers::ObjectBuilder for Builder {} + diff --git a/rust/src/bin/test/MyGame/Example/Vec3.rs b/rust/src/bin/test/MyGame/Example/Vec3.rs new file mode 100644 index 0000000000..f1714a9fdc --- /dev/null +++ b/rust/src/bin/test/MyGame/Example/Vec3.rs @@ -0,0 +1,82 @@ +//! Automatically generated, do not modify. + +use flatbuffers; +use super::*; + +#[derive(Debug)] +pub struct Vec3<'a> { + table: flatbuffers::Table<'a>, +} + +enum VT { + X = 0, + Y = 4, + Z = 8,// Padding4 + TEST1 = 16, + TEST2 = 24,// Padding1 + TEST3 = 26,// Padding2 +} + +impl<'a> Vec3<'a> { + pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> Vec3 { + Vec3 { + table: flatbuffers::Table::with_pos(buf, offset), + } + } + + pub fn x(&self) -> f32 { + let offset = VT::X as u32; + return self.table.get_f32(offset) + } + + pub fn y(&self) -> f32 { + let offset = VT::Y as u32; + return self.table.get_f32(offset) + } + + pub fn z(&self) -> f32 { + let offset = VT::Z as u32; + return self.table.get_f32(offset) + } + + pub fn test1(&self) -> f64 { + let offset = VT::TEST1 as u32; + return self.table.get_f64(offset) + } + + pub fn test2(&self) -> Color { + let offset = VT::TEST2 as u32; + return self.table.get_i8(offset).into() + } + + pub fn test3(&self) -> Test { + let offset = VT::TEST3 as u32; + return self.table.get_struct::(offset) + } + +} + +impl<'a> From> for Vec3<'a> { + fn from(table: flatbuffers::Table) -> Vec3 { + Vec3{ + table: table, + } + } +} + +pub fn build_vec3(builder: &mut flatbuffers::Builder, x: f32, y: f32, z: f32, test1: f64, test2: i8, test3_a: i16, test3_b: i8) -> flatbuffers::UOffsetT { + builder.prep(16, 32); + builder.pad(2); + builder.prep(2, 4); + builder.pad(1); + builder.add_i8(test3_b); + builder.add_i16(test3_a); + builder.pad(1); + builder.add_i8(test2); + builder.add_f64(test1); + builder.pad(4); + builder.add_f32(z); + builder.add_f32(y); + builder.add_f32(x); + builder.offset() as flatbuffers::UOffsetT +} diff --git a/rust/src/bin/test/MyGame/Example/mod.rs b/rust/src/bin/test/MyGame/Example/mod.rs new file mode 100644 index 0000000000..657a1baab1 --- /dev/null +++ b/rust/src/bin/test/MyGame/Example/mod.rs @@ -0,0 +1,18 @@ +//! Automatically generated, do not modify +//! +//! Flatbuffer definitions for the Example namespace. +mod color; +mod any; +pub mod test; +pub mod testsimpletablewithenum; +pub mod vec3; +pub mod stat; +pub mod monster; + +pub use self::color::*; +pub use self::any::*; +pub use self::test::{Test, build_test}; +pub use self::testsimpletablewithenum::TestSimpleTableWithEnum; +pub use self::vec3::{Vec3, build_vec3}; +pub use self::stat::Stat; +pub use self::monster::Monster; diff --git a/rust/src/bin/test/MyGame/mod.rs b/rust/src/bin/test/MyGame/mod.rs new file mode 100644 index 0000000000..b305cc9d96 --- /dev/null +++ b/rust/src/bin/test/MyGame/mod.rs @@ -0,0 +1,5 @@ +//! Automatically generated, do not modify +//! +//! Flatbuffer definitions for the MyGame namespace. + +pub mod example; diff --git a/rust/src/builder.rs b/rust/src/builder.rs new file mode 100644 index 0000000000..0f497a8d39 --- /dev/null +++ b/rust/src/builder.rs @@ -0,0 +1,1109 @@ +//! Flatbuffer Builder. +//! +//! Builder is a state machine for creating FlatBuffer objects. +//! Use a Builder to construct object(s) starting from leaf nodes. +use std::mem; +use byteorder::{ByteOrder, LittleEndian}; + +use types::*; + +/// Flatbuffer builder. +/// +/// A Builder constructs byte buffers in a last-first manner for simplicity and +/// performance. +#[derive(Debug)] +pub struct Builder { + // Where the FlatBuffer is constructed. + bytes: Vec, + // Minimum alignment encountered so far. + min_align: usize, + // Starting offset of the current struct/table. + object_start: usize, + // Whether we are currently serializing a table. + nested: bool, + // Whether the buffer is finished. + finished: bool, + // The vtable for the current table. + vtable: Vec, + // The number of vtable slots required by the current object. + vtable_in_use: usize, + // Offsets of other Vtables in the buffer. + vtables: Vec, + // Unused space in the buffer. Size from beggining of buffer to first vtable + space: usize, + // Number of elements in the current vector + vector_len: usize, +} + +impl Builder { + /// Start a new FlatBuffer `Builder` backed by a buffer with an + /// initial capacity of `size`. + pub fn with_capacity(size: usize) -> Self { + let mut bytes = Vec::with_capacity(size); + unsafe { bytes.set_len(size) }; + Builder { + bytes: bytes, + min_align: 1, + object_start: 0, + nested: false, + finished: false, + vtable_in_use: 0, + vtable: Vec::with_capacity(16), + vtables: Vec::with_capacity(16), + space: size, + vector_len: 0, + } + } + + /// Start encoding a new object in the buffer. + pub fn start_object(&mut self, num_fields: usize) { + self.assert_not_nested(); + self.nested = true; + self.finished = false; + self.vtable.clear(); + self.vtable.resize(num_fields, 0); + self.vtable_in_use = num_fields; + self.object_start = self.offset(); + self.min_align = 1; + } + + /// finish off writing the object that is under construction. + /// + /// Returns the offset of the object in the inside the buffer. + pub fn end_object(&mut self) -> UOffsetT { + self.assert_nested(); + self.nested = false; + self.write_vtable() + } + + /// Initializes bookkeeping for writing a new vector. + pub fn start_vector(&mut self, elem_size: usize, num_elems: usize, alignment: usize) { + self.assert_not_nested(); + self.nested = true; + self.finished = false; + self.vector_len = num_elems; + self.prep(UOFFSETT_SIZE, elem_size * num_elems); + self.prep(alignment, elem_size * num_elems); + } + + /// finish off writing the current vector. + pub fn end_vector(&mut self) -> UOffsetT { + self.assert_nested(); + + let len = self.vector_len; + self.put_u32(len as u32); + + self.nested = false; + self.offset() as UOffsetT + } + + /// Create a string in the buffer from an already encoded UTF-8 `String`. + pub fn create_string(&mut self, value: &str) -> UOffsetT { + let len = value.len(); + self.add_u8(0); + self.start_vector(1, len, 1); + self.space -= len; + for (i, c) in value.bytes().enumerate() { + let pos = self.space + i; + self.place_u8(pos, c); + } + self.end_vector() + } + + /// Finalize a buffer, pointing to the given `root_table`. + pub fn finish(&mut self, root_table: UOffsetT) { + if !self.finished { + self.assert_not_nested(); + let align = self.min_align; + self.prep(align, UOFFSETT_SIZE); + self.add_uoffset(root_table); + self.finished = true; + } + } + + /// Consume the builder and return the finished flatbuffer. + pub fn get_bytes(&self) -> &[u8] { + assert!(self.finished, "Flatbuffer is not been finished"); + &self.bytes + } + + /// Returns the length of the buffer. + pub fn len(&self) -> usize { + self.bytes.len() + } + + /// Returns the current finished buffer and replaces it with + /// a `new_buffer`. + /// + /// Thie function facilitates some reuse of the `Builder` object. + /// Use `into()` if the `Builder` is no longer required. + pub fn swap_out(&mut self, mut new_buffer: Vec) -> Vec { + mem::swap(&mut self.bytes, &mut new_buffer); + self.reset(); + new_buffer + } + + /// Resets the builder. + /// + /// Clears the buffer without resizing. This allows for reuse + /// without allocating new memeory. + pub fn reset(&mut self) { + self.min_align = 1; + self.object_start = 0; + self.nested = false; + self.finished = false; + self.vtable_in_use = 0; + unsafe { + self.vtable.set_len(0); + self.vtables.set_len(0); + } + self.space = self.bytes.capacity(); + self.vector_len = 0; + } + + /// Offset relative to the end of the buffer + #[inline(always)] + pub fn offset(&self) -> usize { + self.bytes.len() - self.space + } + + /// prepare to write an element of `size` after `additional_bytes` + /// have been written. + pub fn prep(&mut self, size: usize, additional_bytes: usize) { + if size > self.min_align { + self.min_align = size + } + let align_size = self.offset() + additional_bytes + 1; + let align_size = ((align_size ^ 1)) & (size - 1); + while self.space <= align_size + size + additional_bytes { + self.grow(); + } + self.pad(align_size) + } + + /// pad places zeros at the current offset. + pub fn pad(&mut self, n: usize) { + for _ in 0..n { + self.space -= 1; + let pos = self.space; + self.place_u8(pos, 0) + } + } +} + +impl Builder { + /// Add a `bool` to the buffer, backwards from the current location. + /// Doesn't align nor check for space. + pub fn put_bool(&mut self, boolean: bool) { + self.space -= 1; + let head = self.space; + self.bytes[head] = if boolean { + 1 + } else { + 0 + }; + } + + /// Add a `byte` to the buffer, backwards from the current location. + /// Doesn't align nor check for space. + pub fn put_u8(&mut self, byte: u8) { + self.space -= 1; + let head = self.space; + self.bytes[head] = byte; + } + + /// Add a `value` of type `i8` to the buffer, backwards from the current + /// location. Doesn't align nor check for space. + pub fn put_i8(&mut self, value: i8) { + self.put_u8(value as u8) + } + + /// Add a `value` of type `u16` to the buffer, backwards from the current + /// location. Doesn't align nor check for space. + pub fn put_u16(&mut self, value: u16) { + self.space -= 2; + let head = self.space; + LittleEndian::write_u16(&mut self.bytes[head..head + 2], value); + } + + /// Add a `value` of type `i16` to the buffer, backwards from the current + /// location. Doesn't align nor check for space. + pub fn put_i16(&mut self, value: i16) { + self.put_u16(value as u16) + } + + /// Add a `value` of type `u32` to the buffer, backwards from the current + /// location. Doesn't align nor check for space. + pub fn put_u32(&mut self, value: u32) { + self.space -= 4; + let head = self.space; + LittleEndian::write_u32(&mut self.bytes[head..head + 4], value); + } + + /// Add a `value` of type `i32` to the buffer, backwards from the current + /// location. Doesn't align nor check for space. + pub fn put_i32(&mut self, value: i32) { + self.put_u32(value as u32) + } + + /// Add a `value` of type `u64` to the buffer, backwards from the current + /// location. Doesn't align nor check for space. + pub fn put_u64(&mut self, value: u64) { + self.space -= 8; + let head = self.space; + LittleEndian::write_u64(&mut self.bytes[head..head + 8], value); + + } + + /// Add a `value` of type `i64` to the buffer, backwards from the current + /// location. Doesn't align nor check for space. + pub fn put_i64(&mut self, value: i64) { + self.put_u64(value as u64) + } + + /// Add a `value` of type `f32` to the buffer, backwards from the current + /// location. Doesn't align nor check for space. + pub fn put_f32(&mut self, value: f32) { + self.space -= 4; + let head = self.space; + LittleEndian::write_f32(&mut self.bytes[head..head + 4], value); + } + + /// Add a `value` of type `f64` to the buffer, backwards from the current + /// location. Doesn't align nor check for space. + pub fn put_f64(&mut self, value: f64) { + self.space -= 8; + let head = self.space; + LittleEndian::write_f64(&mut self.bytes[head..head + 8], value); + } + + /// Add a `value` of type `UOffsetT` to the buffer, backwards from the + /// current location. Doesn't align nor check for space. + pub fn put_uoffset(&mut self, value: UOffsetT) { + self.space -= 4; + let head = self.space; + LittleEndian::write_u32(&mut self.bytes[head..head + 4], value); + } + + /// Add a `bool` to the buffer, properly aligned, and grows the + /// buffer (if necessary). + pub fn add_bool(&mut self, value: bool) { + self.prep(1, 0); + self.put_bool(value); + } + + /// Add a value of type `u8` to the buffer, properly aligned, and grows the + /// buffer (if necessary). + pub fn add_u8(&mut self, value: u8) { + self.prep(1, 0); + self.put_u8(value); + } + + /// Add a value of type `i8` to the buffer, properly aligned, and grows the + /// buffer (if necessary). + pub fn add_i8(&mut self, value: i8) { + self.add_u8(value as u8); + } + + /// Add a value of type `u16` to the buffer, properly aligned, and grows the + /// buffer (if necessary). + pub fn add_u16(&mut self, value: u16) { + self.prep(2, 0); + self.put_u16(value); + } + + /// Add a value of type `i16` to the buffer, properly aligned, and grows the + /// buffer (if necessary). + pub fn add_i16(&mut self, value: i16) { + self.add_u16(value as u16); + } + + /// Add a value of type `u32` to the buffer, properly aligned, and grows the + /// buffer (if necessary). + pub fn add_u32(&mut self, value: u32) { + self.prep(4, 0); + self.put_u32(value); + } + + /// Add a value of type `i32` to the buffer, properly aligned, and grows the + /// buffer (if necessary). + pub fn add_i32(&mut self, value: i32) { + self.add_u32(value as u32); + } + + /// Add a value of type `u64` to the buffer, properly aligned, and grows the + /// buffer (if necessary). + pub fn add_u64(&mut self, value: u64) { + self.prep(8, 0); + self.put_u64(value); + } + + /// Add a value of type `i64` to the buffer, properly aligned, and grows the + /// buffer (if necessary). + pub fn add_i64(&mut self, value: i64) { + self.add_u64(value as u64); + } + + /// Add a value of type `f32` to the buffer, properly aligned, and grows the + /// buffer (if necessary). + pub fn add_f32(&mut self, value: f32) { + self.prep(4, 0); + self.put_f32(value); + } + + /// Add a value of type `f64` to the buffer, properly aligned, and grows the + /// buffer (if necessary). + pub fn add_f64(&mut self, value: f64) { + self.prep(8, 0); + self.put_f64(value); + } + + /// Add a value of type `f64` to the buffer, properly aligned, and grows the + /// buffer (if necessary). + /// prepends an UOffsetT, relative to where it will be written. + pub fn add_uoffset(&mut self, value: UOffsetT) { + self.prep(UOFFSETT_SIZE, 0); + assert!(value <= self.offset() as UOffsetT, "unreachable: off <= boffset();"); + let relative = self.offset() as u32 - value as u32 + UOFFSETT_SIZE as u32; + self.put_uoffset(relative); + } + + /// Slot sets the vtable key `voffset` to the current location in the buffer. + pub fn slot(&mut self, slot: usize) { + self.vtable[slot] = self.offset() as UOffsetT; + } + + /// Add a `bool` onto the object at vtable slot `o`. If value `x` equals + /// default `d`, then the slot will be set to zero and no other data + /// will be written. + pub fn add_slot_bool(&mut self, o: usize, value: bool, d: bool) { + if value != d { + self.add_bool(value); + self.slot(o) + } + } + + /// Add a value of type `u8` onto the object at vtable slot `o`. If value + /// `x` equals default `d`, then the slot will be set to zero and no other + /// data will be written. + pub fn add_slot_u8(&mut self, o: usize, value: u8, d: u8) { + if value != d { + self.add_u8(value); + self.slot(o) + } + } + + /// Add a value of type `i8` onto the object at vtable slot `o`. If value + /// `x` equals default `d`, then the slot will be set to zero and no other + /// data will be written. + pub fn add_slot_i8(&mut self, o: usize, value: i8, d: i8) { + self.add_slot_u8(o, value as u8, d as u8); + } + + /// Add a value of type `u16` onto the object at vtable slot `o`. If value + /// `x` equals default `d`, then the slot will be set to zero and no other + /// data will be written. + pub fn add_slot_u16(&mut self, o: usize, value: u16, d: u16) { + if value != d { + self.add_u16(value); + self.slot(o) + } + } + + /// Add a value of type `i16` onto the object at vtable slot `o`. If value + /// `x` equals default `d`, then the slot will be set to zero and no other + /// data will be written. + pub fn add_slot_i16(&mut self, o: usize, value: i16, d: i16) { + self.add_slot_u16(o, value as u16, d as u16); + } + + /// Add a value of type `u32` onto the object at vtable slot `o`. If value + /// `x` equals default `d`, then the slot will be set to zero and no other + /// data will be written. + pub fn add_slot_u32(&mut self, o: usize, value: u32, d: u32) { + if value != d { + self.add_u32(value); + self.slot(o) + } + } + + /// Add a value of type `i32` onto the object at vtable slot `o`. If value + /// `x` equals default `d`, then the slot will be set to zero and no other + /// data will be written. + pub fn add_slot_i32(&mut self, o: usize, value: i32, d: i32) { + self.add_slot_u32(o, value as u32, d as u32); + } + + /// Add a value of type `u64` onto the object at vtable slot `o`. If value + /// `x` equals default `d`, then the slot will be set to zero and no other + /// data will be written. + pub fn add_slot_u64(&mut self, o: usize, value: u64, d: u64) { + if value != d { + self.add_u64(value); + self.slot(o) + } + } + + /// Add a value of type `i64` onto the object at vtable slot `o`. If value + /// `x` equals default `d`, then the slot will be set to zero and no other + /// data will be written. + pub fn add_slot_i64(&mut self, o: usize, value: i64, d: i64) { + self.add_slot_u64(o, value as u64, d as u64); + } + + /// Add a value of type `f32` onto the object at vtable slot `o`. If value + /// `x` equals default `d`, then the slot will be set to zero and no other + /// data will be written. + pub fn add_slot_f32(&mut self, o: usize, value: f32, d: f32) { + if value != d { + self.add_f32(value); + self.slot(o) + } + } + + /// Add a value of type `f64` onto the object at vtable slot `o`. If value + /// `x` equals default `d`, then the slot will be set to zero and no other + /// data will be written. + pub fn add_slot_f64(&mut self, o: usize, value: f64, d: f64) { + if value != d { + self.add_f64(value); + self.slot(o) + } + } + + /// Add a value of type `UOffsetT` onto the object at vtable slot `o`. If + /// value `x` equals default `d`, then the slot will be set to zero and no + /// other data will be written. + /// + /// prepends an UOffsetT, relative to where it will be written. + pub fn add_slot_uoffset(&mut self, o: usize, value: UOffsetT, d: UOffsetT) { + if value != d { + self.add_uoffset(value); + self.slot(o) + } + } + + /// PrependStructSlot prepends a struct onto the object at vtable slot `o`. + /// Structs are stored inline, so nothing additional is being added. + /// In generated code, `d` is always 0. + pub fn add_slot_struct(&mut self, o: usize, value: UOffsetT, d: UOffsetT) { + if value != d { + self.assert_nested(); + assert!(value == self.offset() as u32, "Inline data write outside of object"); + self.slot(o) + } + } + + // helper method to read a VOffsetT + fn get_u16(&self, pos: usize) -> VOffsetT { + LittleEndian::read_u16(&self.bytes[pos..pos + 2]) + } +} + +impl Builder { + // WriteVtable serializes the vtable for the current object. + // + // Before writing out the vtable, this checks pre-existing vtables for + // equality to this one. If an equal vtable is found, point the object to + // the existing vtable and return. + // + // Because vtable values are sensitive to alignment of object data, not all + // logically-equal vtables will be deduplicated. + fn write_vtable(&mut self) -> UOffsetT { + self.add_uoffset(0); + let vtableloc = self.offset(); + // Write out the current vtable. + for i in (0..self.vtable_in_use).rev() { + // Offset relative to the start of the table. + let offset = if self.vtable[i] != 0 { + vtableloc - self.vtable[i] as usize + } else { + 0 + }; + self.add_u16(offset as u16); + } + // write the metadata + let total_obj_size = vtableloc - self.object_start; + let vtable_size = (self.vtable_in_use + VTABLE_METADATA_FIEDS) * VOFFSETT_SIZE; + self.add_u16(total_obj_size as u16); + self.add_u16(vtable_size as u16); + // check for identical vtable + let mut existing_vt = 0; + let mut this_vt = self.space; + 'outer: for (i, vt_offset) in self.vtables.iter().rev().enumerate() { + let vt_start = self.bytes.capacity() - *vt_offset as usize; + let vt_len = self.get_u16(vt_start); + if vt_len != self.get_u16(this_vt) { + continue; + } + let vt_end = vt_start + vt_len as usize; + let vt_bytes = &self.bytes[vt_start + VTABLE_METADATA_SIZE..vt_end]; + for (j, chunk) in vt_bytes.chunks(2).enumerate() { + + let this_start = this_vt + (j * VOFFSETT_SIZE) as usize; + let this_end = this_start + VOFFSETT_SIZE; + let this_chunk = &self.bytes[this_start..this_end]; + if chunk != this_chunk { + continue 'outer; + } + } + existing_vt = self.vtables[i] as usize; + break 'outer; + } + + if existing_vt != 0 { + // found a match + self.space = self.bytes.capacity() - vtableloc; + let pos = self.space; + self.place_u32(pos, (existing_vt - vtableloc) as u32); + } else { + // no match + this_vt = self.offset(); + self.vtables.push(this_vt as u32); + let capacity = self.bytes.capacity(); + self.place_u32(capacity - vtableloc, (this_vt - vtableloc) as u32); + } + vtableloc as UOffsetT + } + + /// Doubles the size of the buffer. + /// + /// copies the old data towards the end of the new buffer (since we build + /// the buffer backwards). + pub fn grow(&mut self) { + let old_capacity = if self.bytes.capacity() == 0 { + 1 + } else { + self.bytes.capacity() + }; + let size_test = old_capacity & 0xC0000000; + assert!(size_test == 0, + "FlatBuffers: cannot grow buffer beyond 2 gigabytes."); + let new_capacity = old_capacity << 1; + let mut nbytes = Vec::with_capacity(new_capacity); + for _ in 0..old_capacity { + nbytes.push(0) + } + self.space = new_capacity - self.offset(); + nbytes.extend_from_slice(&self.bytes); + unsafe { nbytes.set_len(new_capacity) }; + self.bytes = nbytes; + } + + + fn place_u8(&mut self, pos: usize, value: u8) { + self.bytes[pos] = value; + } + + fn place_u32(&mut self, pos: usize, value: u32) { + LittleEndian::write_u32(&mut self.bytes[pos..pos + 4], value); + } + + fn assert_not_nested(&self) { + assert!(!self.nested, + "FlatBuffers: object serialization must not be nested."); + } + + fn assert_nested(&self) { + assert!(self.nested, + "FlatBuffers: struct must be serialized inline."); + } +} + +impl Default for Builder { + fn default() -> Builder { + Builder::with_capacity(1024) + } +} + +impl Into> for Builder { + fn into(self) -> Vec { + self.bytes + } +} + +/// A trait used by generated object builders to facilitate +/// using the same flatbuffer `Builder`. +pub trait ObjectBuilder: Into + From { + /// Convert from one `ObjectBuilder` instance to another. + #[inline(always)] + fn from_other(x: T) -> Self { + x.into().into() + } +} + +#[cfg(test)] +mod test { + use super::Builder; + + #[test] + fn grow_buffer() { + let mut b = Builder::with_capacity(0); + b.grow(); + assert_eq!(b.space, 2); + assert_eq!(b.offset(), 0); + assert_eq!(b.len(), 2); + + let mut b = Builder::with_capacity(1); + b.grow(); + assert_eq!(b.space, 2); + assert_eq!(b.offset(), 0); + assert_eq!(b.len(), 2); + + let mut b = Builder::with_capacity(2); + b.grow(); + assert_eq!(b.space, 4); + assert_eq!(b.offset(), 0); + assert_eq!(b.len(), 4); + } + + #[test] + fn grow_buffer2() { + let mut builder = Builder::with_capacity(2); + builder.add_u8(4); + builder.add_u8(2); + let old_capacity = builder.bytes.capacity(); + builder.grow(); + // capacity doubled + assert_eq!(builder.bytes.capacity(), old_capacity * 2); + assert_eq!(builder.bytes.len(), old_capacity * 2); + // bytes moved to end of new buffer + assert_eq!(builder.bytes[(old_capacity * 2) - 2], 2u8); + assert_eq!(builder.bytes[(old_capacity * 2) - 1], 4u8); + } + + #[test] + fn check_bytes() { + fn check(b: &Builder, i: u8, want: &[u8]) { + let got = &b.bytes; + assert!(got.ends_with(want), + "case {}: want\n{:?}\nbut got\n{:?}\n", + i, + want, + got) + }; + let mut b = Builder::with_capacity(0); + check(&b, 1, &[]); + + b.add_bool(true); + check(&b, 2, &[1]); + b.add_i8(-127); + check(&b, 3, &[129, 1]); + b.add_u8(255); + check(&b, 4, &[255, 129, 1]); + b.add_i16(-32222); + check(&b, 5, &[0x22, 0x82, 0, 255, 129, 1]); // first pad + b.add_u16(0xFEEE); + check(&b, 6, &[0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1]); // no pad this time + b.add_i32(-53687092); + check(&b, + 7, + &[204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, 1]); + b.add_u32(0x98765432); + check(&b, + 8, + &[0x32, 0x54, 0x76, 0x98, 204, 204, 204, 252, 0xEE, 0xFE, 0x22, 0x82, 0, 255, 129, + 1]); + + b = Builder::with_capacity(0); + b.add_u64(0x1122334455667788); + check(&b, 9, &[0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11]); + + // test 2: 1xbyte vector + b = Builder::with_capacity(0); + check(&b, 10, &[]); + b.start_vector(1, 1, 1); + check(&b, 11, &[0, 0, 0]); // align to 4bytes + b.add_u8(1); + check(&b, 12, &[1, 0, 0, 0]); + b.end_vector(); + check(&b, 13, &[1, 0, 0, 0, 1, 0, 0, 0]); // padding + + // test 3: 2xbyte vector + b = Builder::with_capacity(0); + b.start_vector(1, 2, 1); + check(&b, 14, &[0,0]); // align to 4bytes + b.add_u8(1); + check(&b, 15, &[1,0,0]); + b.add_u8(2); + check(&b, 16, &[2,1,0,0]); + b.end_vector(); + check(&b, 17, &[2, 0, 0, 0, 2, 1, 0, 0]); // padding + + // test 3b: 11xbyte vector matches builder size + b = Builder::with_capacity(12); + b.start_vector(1, 8, 1); + check(&b, 18, &[]); + for i in 0..11 { + b.add_u8(i); + } + b.end_vector(); + // says size is 8 not 11 + check(&b, 19, &[8, 0, 0, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]); + + // test 4: 1xuint16 vector + b = Builder::with_capacity(0); + b.start_vector(2, 1, 1); + check(&b, 20, &[0,0]); // align to 4bytes + b.add_u16(1); + check(&b, 21, &[1,0,0,0]); + b.end_vector(); + check(&b, 22, &[1,0,0,0,1,0,0,0]); // padding + + // test 5: 2xuint16 vector + b = Builder::with_capacity(0); + b.start_vector(2, 2, 1); + check(&b, 23, &[]); // align to 4bytes + b.add_u16(0xABCD); + check(&b, 24, &[0xCD, 0xAB]); + b.add_u16(0xDCBA); + check(&b, 25, &[0xBA, 0xDC,0xCD, 0xAB]); + b.end_vector(); + check(&b, 25, &[2, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB]); + + // create string + b = Builder::with_capacity(0); + b.create_string("foo"); + check(&b, 26, &[3, 0, 0, 0, 102, 111, 111, 0]); // 0-terminated, no pad + b.create_string("moop"); + check(&b, 27, &[4, 0, 0, 0, 109, 111, 111, 112, 0, 0, 0, 0, // 0-terminated, 3-byte pad + 3, 0, 0, 0, 102, 111, 111, 0]); + + // test 7: empty vtable + b = Builder::with_capacity(0); + b.start_object(0); + check(&b, 28, &[]); + b.end_object(); + check(&b, 29, &[4, 0, 4, 0, 4, 0, 0, 0]); + + // test 8: vtable with one true bool + b = Builder::with_capacity(0); + b.start_object(1); + check(&b, 30, &[]); + b.add_slot_bool(0, true, false); + b.end_object(); + check(&b, 31, &[ + 6, 0, // vtable bytes + 8, 0, // length of object including vtable offset + 7, 0, // start of bool value + 6, 0, 0, 0, // offset for start of vtable (int32) + 0, 0, 0, // padded to 4 bytes + 1, // bool value + ]); + + // test 9: vtable with one default bool + b = Builder::with_capacity(0); + b.start_object(1); + check(&b, 32, &[]); + b.add_slot_bool(0, false, false); + b.end_object(); + check(&b, 33, &[ + 6, 0, // vtable bytes + 4, 0, // end of object from here + 0, 0, // entry 1 is zero + 6, 0, 0, 0, // offset for start of vtable (int32) + ]); + + // test 10: vtable with one int16 + b = Builder::with_capacity(0); + b.start_object(1); + b.add_slot_i16(0, 0x789A, 0); + b.end_object(); + check(&b, 34, &[ + 6, 0, // vtable bytes + 8, 0, // end of object from here + 6, 0, // offset to value + 6, 0, 0, 0, // offset for start of vtable (int32) + 0, 0, // padding to 4 bytes + 0x9A, 0x78, + ]); + + // test 11: vtable with two int16 + b = Builder::with_capacity(0); + b.start_object(2); + b.add_slot_i16(0, 0x3456, 0); + b.add_slot_i16(1, 0x789A, 0); + b.end_object(); + check(&b, 35, &[ + 8, 0, // vtable bytes + 8, 0, // end of object from here + 6, 0, // offset to value 0 + 4, 0, // offset to value 1 + 8, 0, 0, 0, // offset for start of vtable (int32) + 0x9A, 0x78, // value 1 + 0x56, 0x34, // value 0 + ]); + + // test 12a: vtable with int16 and bool + b = Builder::with_capacity(0); + b.start_object(2); + b.add_slot_i16(0, 0x3456, 0); + b.add_slot_bool(1, true, false); + b.end_object(); + check(&b, 36, &[ + 8, 0, // vtable bytes + 8, 0, // end of object from here + 6, 0, // offset to value 0 + 5, 0, // offset to value 1 + 8, 0, 0, 0, // offset for start of vtable (int32) + 0, // padding + 1, // value 1 + 0x56, 0x34, // value 0 + ]); + + // test 12b: vtable with empty vector + b = Builder::with_capacity(0); + b.start_vector(1, 0, 1); + let vecend = b.end_vector(); + b.start_object(1); + b.add_slot_uoffset(0, vecend, 0); + b.end_object(); + check(&b, 37, &[ + 6, 0, // vtable bytes + 8, 0, + 4, 0, // offset to vector offset + 6, 0, 0, 0, // offset for start of vtable (int32) + 4, 0, 0, 0, + 0, 0, 0, 0, // length of vector (not in struct) + ]); + + // test 12c: vtable with empty vector of byte and some scalars + b = Builder::with_capacity(0); + b.start_vector(1, 0, 1); + let vecend = b.end_vector(); + b.start_object(2); + b.add_slot_i16(0, 55, 0); + b.add_slot_uoffset(1, vecend, 0); + b.end_object(); + check(&b, 38, &[ + 8, 0, // vtable bytes + 12, 0, + 10, 0, // offset to value 0 + 4, 0, // offset to vector offset + 8, 0, 0, 0, // vtable loc + 8, 0, 0, 0, // value 1 + 0, 0, 55, 0, // value 0 + 0, 0, 0, 0, // length of vector (not in struct) + ]); + + // test 13: vtable with 1 int16 and 2-vector of int16 + b = Builder::with_capacity(0); + b.start_vector(2, 2, 1); + b.add_i16(0x1234); + b.add_i16(0x5678); + let vecend = b.end_vector(); + b.start_object(2); + b.add_slot_uoffset(1, vecend, 0); + b.add_slot_i16(0, 55, 0); + b.end_object(); + check(&b, 39, &[ + 8, 0, // vtable bytes + 12, 0, // length of object + 6, 0, // start of value 0 from end of vtable + 8, 0, // start of value 1 from end of buffer + 8, 0, 0, 0, // offset for start of vtable (int32) + 0, 0, // padding + 55, 0, // value 0 + 4, 0, 0, 0, // vector position from here + 2, 0, 0, 0, // length of vector (uint32) + 0x78, 0x56, // vector value 1 + 0x34, 0x12, // vector value 0 + ]); + + // test 14: vtable with 1 struct of 1 int8, 1 int16, 1 int32 + b = Builder::with_capacity(0); + b.start_object(1); + b.prep(4+4+4, 0); + b.add_i8(55); + b.pad(3); + b.add_i16(0x1234); + b.pad(2); + b.add_i32(0x12345678); + let struct_start = b.offset(); + b.add_slot_struct(0, struct_start as u32, 0); + b.end_object(); + check(&b, 40, &[ + 6, 0, // vtable bytes + 16, 0, // end of object from here + 4, 0, // start of struct from here + 6, 0, 0, 0, // offset for start of vtable (int32) + 0x78, 0x56, 0x34, 0x12, // value 2 + 0, 0, // padding + 0x34, 0x12, // value 1 + 0, 0, 0, // padding + 55, // value 0 + ]); + + // test 15: vtable with 1 vector of 2 struct of 2 int8 + b = Builder::with_capacity(0); + b.start_vector(1*2, 2, 1); + b.add_i8(33); + b.add_i8(44); + b.add_i8(55); + b.add_i8(66); + let vecend = b.end_vector(); + b.start_object(1); + b.add_slot_uoffset(0, vecend, 0); + b.end_object(); + check(&b, 41, &[ + 6, 0, // vtable bytes + 8, 0, + 4, 0, // offset of vector offset + 6, 0, 0, 0, // offset for start of vtable (int32) + 4, 0, 0, 0, // vector start offset + + 2, 0, 0, 0, // vector length + 66, // vector value 1,1 + 55, // vector value 1,0 + 44, // vector value 0,1 + 33, // vector value 0,0 + ]); + + // test 16: table with some elements + b = Builder::with_capacity(0); + b.start_object(2); + b.add_slot_i8(0, 33, 0); + b.add_slot_i16(1, 66, 0); + let off = b.end_object(); + b.finish(off); + + check(&b, 42, &[ + 12, 0, 0, 0, // root of table: points to vtable offset + + 8, 0, // vtable bytes + 8, 0, // end of object from here + 7, 0, // start of value 0 + 4, 0, // start of value 1 + + 8, 0, 0, 0, // offset for start of vtable (int32) + + 66, 0, // value 1 + 0, // padding + 33, // value 0 + ]); + + // test 17: one unfinished table and one finished table + b = Builder::with_capacity(0); + b.start_object(2); + b.add_slot_i8(0, 33, 0); + b.add_slot_i8(1, 44, 0); + let off = b.end_object(); + b.finish(off); + + b.start_object(3); + b.add_slot_i8(0, 55, 0); + b.add_slot_i8(1, 66, 0); + b.add_slot_i8(2, 77, 0); + let off = b.end_object(); + b.finish(off); + + check(&b, 43, &[ + 16, 0, 0, 0, // root of table: points to object + 0, 0, // padding + + 10, 0, // vtable bytes + 8, 0, // size of object + 7, 0, // start of value 0 + 6, 0, // start of value 1 + 5, 0, // start of value 2 + 10, 0, 0, 0, // offset for start of vtable (int32) + 0, // padding + 77, // value 2 + 66, // value 1 + 55, // value 0 + + 12, 0, 0, 0, // root of table: points to object + + 8, 0, // vtable bytes + 8, 0, // size of object + 7, 0, // start of value 0 + 6, 0, // start of value 1 + 8, 0, 0, 0, // offset for start of vtable (int32) + 0, 0, // padding + 44, // value 1 + 33, // value 0 + ]); + + // test 18: a bunch of bools + b = Builder::with_capacity(0); + b.start_object(8); + b.add_slot_bool(0, true, false); + b.add_slot_bool(1, true, false); + b.add_slot_bool(2, true, false); + b.add_slot_bool(3, true, false); + b.add_slot_bool(4, true, false); + b.add_slot_bool(5, true, false); + b.add_slot_bool(6, true, false); + b.add_slot_bool(7, true, false); + let off = b.end_object(); + b.finish(off); + + check(&b, 44, &[ + 24, 0, 0, 0, // root of table: points to vtable offset + + 20, 0, // vtable bytes + 12, 0, // size of object + 11, 0, // start of value 0 + 10, 0, // start of value 1 + 9, 0, // start of value 2 + 8, 0, // start of value 3 + 7, 0, // start of value 4 + 6, 0, // start of value 5 + 5, 0, // start of value 6 + 4, 0, // start of value 7 + 20, 0, 0, 0, // vtable offset + + 1, // value 7 + 1, // value 6 + 1, // value 5 + 1, // value 4 + 1, // value 3 + 1, // value 2 + 1, // value 1 + 1, // value 0 + ]); + + + // test 19: three bools + b = Builder::with_capacity(0); + b.start_object(3); + b.add_slot_bool(0, true, false); + b.add_slot_bool(1, true, false); + b.add_slot_bool(2, true, false); + let off = b.end_object(); + b.finish(off); + + check(&b, 45, &[ + 16, 0, 0, 0, // root of table: points to vtable offset + + 0, 0, // padding + + 10, 0, // vtable bytes + 8, 0, // size of object + 7, 0, // start of value 0 + 6, 0, // start of value 1 + 5, 0, // start of value 2 + 10, 0, 0, 0, // vtable offset from here + + 0, // padding + 1, // value 2 + 1, // value 1 + 1, // value 0 + ]); + + // test 20: some floats + b = Builder::with_capacity(0); + b.start_object(1); + b.add_slot_f32(0, 1.0, 0.0); + b.end_object(); + + check(&b, 46, &[ + 6, 0, // vtable bytes + 8, 0, // size of object + 4, 0, // start of value 0 + 6, 0, 0, 0, // vtable offset + + 0, 0, 128, 63, // value 0 + ]); + } +} diff --git a/rust/src/iter.rs b/rust/src/iter.rs new file mode 100644 index 0000000000..df5a1479c2 --- /dev/null +++ b/rust/src/iter.rs @@ -0,0 +1,129 @@ +use std::iter; +use std::marker::PhantomData; + +use table; +use types::*; + +/// An iterator over flatbuffer vectors. +#[derive(Debug)] +pub struct Iterator<'a, T> { + is_table: bool, + table: &'a table::Table<'a>, + index: usize, + len: usize, + i: usize, + _marker: PhantomData<[T]> +} + +/// Create a new iterator over a flatbuffer vector of string. +pub fn new_string_iterator<'a>(table: &'a table::Table, offset: usize) -> Iterator<'a, &'a str> { + let len = table.get_u32(offset as u32); + Iterator { + is_table: false, + table: table, + index: offset + UOFFSETT_SIZE, + len: len as usize, + i: 0, + _marker: PhantomData, + } +} + +/// Create a new iterator over a flatbuffer vector of structs. +pub fn new_struct_iterator<'a, T: From>>(table: &'a table::Table, offset: usize) -> Iterator<'a, T> { + let len = table.get_u32(offset as u32); + Iterator { + is_table: false, + table: table, + index: offset + UOFFSETT_SIZE, + len: len as usize, + i: 0, + _marker: PhantomData, + } +} +/// Create a new iterator over a flatbuffer vector of tables. +pub fn new_table_iterator<'a, T: From>>(table: &'a table::Table, offset: usize) -> Iterator<'a, T> { + let len = table.get_u32(offset as u32); + Iterator { + is_table: true, + table: table, + index: offset, + len: len as usize, + i: 0, + _marker: PhantomData, + } +} + +#[doc(hide)] +/// Helper function. Constructs a zero iterator. +pub fn empty_iterator<'a, T>(table: &'a table::Table) -> Iterator<'a, T> { + Iterator { + is_table: false, + table: table, + index: 0, + len: 0, + i: 100, + _marker: PhantomData + } +} + + +impl<'a> iter::Iterator for Iterator<'a, &'a str> { + type Item = &'a str; + + fn next(&mut self) -> Option<&'a str> { + if self.i < self.len { + let offset = self.index as u32; + let res = self.table.get_str(offset); + self.index += UOFFSETT_SIZE; + self.i += 1; + return Some(res) + } + None + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.table.get_u32(0); + (0, Some(len as usize)) + } +} + +impl<'a> ExactSizeIterator for Iterator<'a, &'a str> { + fn len(&self) -> usize { + self.len + } +} + +impl<'a, T: From>> iter::Iterator for Iterator<'a, T> { + type Item = T; + + fn next(&mut self) -> Option { + if self.i < self.len { + self.i += 1; + if self.is_table { + //let offset = self.table.get_u32(self.index as u32); + let offset = self.index as u32; + let res = self.table.get_indirect_root(offset); + self.index += UOFFSETT_SIZE; + return Some(res.into()) + } else { + let index = self.index; + let res = self.table.get_struct(index as u32); + self.index += UOFFSETT_SIZE; + return Some(res) + + } + } + None + } + + fn size_hint(&self) -> (usize, Option) { + let len = self.table.get_u32(0); + (0, Some(len as usize)) + } +} + +impl<'a, T: From>> ExactSizeIterator for Iterator<'a, T> { + fn len(&self) -> usize { + self.len + } +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs new file mode 100644 index 0000000000..0b6c47263c --- /dev/null +++ b/rust/src/lib.rs @@ -0,0 +1,25 @@ +//! Rust support for Flatbuffers. +//! +//! FlatBuffers is an efficient cross platform serialization library for games +//! and other memory constrained apps. It allows you to directly access +//! serialized data without unpacking/parsing it first, while still having great +//! forwards/backwards compatibility. +//! +#![doc(html_logo_url="http://google.github.io/flatbuffers/fpl_logo_small.png")] + +#![deny(unused_qualifications, missing_debug_implementations, trivial_casts, + missing_copy_implementations, unused_import_braces, missing_docs)] + +extern crate byteorder; + +mod builder; +mod types; +mod table; +mod iter; + +pub use self::builder::{Builder,ObjectBuilder}; +pub use self::types::{UOffsetT, VOffsetT, SOffsetT}; +pub use self::table::Table; +pub use self::iter::*; + + diff --git a/rust/src/table.rs b/rust/src/table.rs new file mode 100644 index 0000000000..3e1c67a921 --- /dev/null +++ b/rust/src/table.rs @@ -0,0 +1,225 @@ +use byteorder::{ByteOrder, LittleEndian}; + +use types::*; +use iter; + +/// A wrapper object around Flatbuffer table data. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Table<'a> { + buffer: &'a [u8], + pos: UOffsetT +} + +impl<'a> Table<'a> { + /// Create a table using from a slice using data starting at offset. + pub fn from_offset(buffer: &[u8], offset: UOffsetT) -> Table { + let n = read_uoffset(&buffer, offset as UOffsetT); + Table { + buffer: buffer, + pos: n + offset + } + } + + /// Create a table for a simple inline struct. + pub fn with_pos(buffer: &[u8], pos: UOffsetT) -> Table { + Table { + buffer: buffer, + pos: pos + } + } + + /// Return an object table at offset. + pub fn get_root(&self, offset: UOffsetT) -> Table { + Table::from_offset(self.buffer, self.pos + offset) + } + + /// Return an object table at offset specified by offset. + pub fn get_indirect_root(&self, offset: UOffsetT) -> Table { + let actual_offset = self.pos as u32 + offset + self.get_u32(offset); + Table::with_pos(&self.buffer, actual_offset) + } + + + // Returns a slice of table including the vtable. + // + // First element of root table is Offset to vtable used + // and is by default a negative direction. + #[inline(always)] + fn vtable(&self) -> &[u8] { + let pos = self.pos; + let vt_offset = read_soffset(&self.buffer, self.pos as UOffsetT); + let vtable = (self.pos as i32 - vt_offset) as usize; + &self.buffer[vtable..pos as usize] + } + + /// Returns the field offset or 0 if the field was not present. + pub fn field_offset(&self, field: VOffsetT) -> UOffsetT { + let vtable = self.vtable(); + let vt_size = LittleEndian::read_u16(vtable); + if field < vt_size { + return LittleEndian::read_u16(&vtable[field as usize..]) as u32 + } + 0 + } + + /// ByteVector gets an unsigned byte slice from data stored inside + /// the flatbuffer. + pub fn byte_vector(&self, offset: UOffsetT) -> &[u8] { + let mut offset = offset + self.pos as UOffsetT; + offset += read_uoffset(self.buffer, offset); + let start = offset as usize + 4 as usize; + let length = read_uoffset(self.buffer, offset) as usize; + &self.buffer[start..start+length] + } + + /// ByteVector gets a signed byte slice from data stored inside + /// the flatbuffer. + pub fn ibyte_vector(&self, offset: UOffsetT) -> &[i8] { + let slice = self.byte_vector(offset); + let len = slice.len(); + unsafe { + use std::slice; + let z = slice.as_ptr() as *const i8; + slice::from_raw_parts(z, len) + } + } + + /// ByteVector gets a slice of bool from data stored inside the flatbuffer. + pub fn bool_vector(&self, offset: UOffsetT) -> &[bool] { + let slice = self.byte_vector(offset); + let len = slice.len(); + unsafe { + use std::slice; + let z = slice.as_ptr() as *const bool; + slice::from_raw_parts(z, len) + } + } + + /// TODO + pub fn struct_vector>>(&'a self, offset: UOffsetT) -> iter::Iterator { + let mut offset = offset; + offset += self.get_u32(offset); + iter::new_struct_iterator::(&self, offset as usize) + } + + /// TODO + pub fn table_vector>>(&'a self, offset: UOffsetT) -> iter::Iterator { + let mut offset = offset; + offset += self.get_u32(offset); + iter::new_table_iterator::(&self, offset as usize) + } + + /// TODO + pub fn str_vector(&'a self, offset: UOffsetT) -> iter::Iterator<&str> { + let mut offset = offset; + offset += self.get_u32(offset); + iter::new_string_iterator(&self, offset as usize) + } + + /// TODO + pub fn get_bool(&self, offset: UOffsetT) -> bool { + let pos = self.pos as usize; + self.buffer[pos + offset as usize] == 1 + } + + /// TODO + pub fn get_u8(&self, offset: UOffsetT) -> u8 { + let pos = self.pos as usize; + self.buffer[pos + offset as usize] + } + + /// TODO + pub fn get_i8(&self, offset: UOffsetT) -> i8 { + let pos = self.pos as usize; + self.buffer[pos + offset as usize] as i8 + } + + /// TODO + pub fn get_u16(&self, offset: UOffsetT) -> u16 { + let pos = self.pos as usize; + LittleEndian::read_u16(&self.buffer[pos + offset as usize..]) + } + + /// TODO + pub fn get_i16(&self, offset: UOffsetT) -> i16 { + let pos = self.pos as usize; + LittleEndian::read_i16(&self.buffer[pos + offset as usize..]) + } + + /// TODO + pub fn get_u32(&self, offset: UOffsetT) -> u32 { + let pos = self.pos as usize; + LittleEndian::read_u32(&self.buffer[pos + offset as usize..]) + } + + /// TODO + pub fn get_i32(&self, offset: UOffsetT) -> i32 { + let pos = self.pos as usize; + LittleEndian::read_i32(&self.buffer[pos + offset as usize..]) + } + + /// TODO + pub fn get_u64(&self, offset: UOffsetT) -> u64 { + let pos = self.pos as usize; + LittleEndian::read_u64(&self.buffer[pos + offset as usize..]) + } + + /// TODO + pub fn get_i64(&self, offset: UOffsetT) -> i64 { + let pos = self.pos as usize; + LittleEndian::read_i64(&self.buffer[pos + offset as usize..]) + } + + /// TODO + pub fn get_f32(&self, offset: UOffsetT) -> f32 { + let pos = self.pos as usize; + LittleEndian::read_f32(&self.buffer[pos + offset as usize..]) + } + + /// TODO + pub fn get_f64(&self, offset: UOffsetT) -> f64 { + let pos = self.pos as usize; + LittleEndian::read_f64(&self.buffer[pos + offset as usize..]) + } + + /// TODO + pub fn get_str(&self, offset: UOffsetT) -> &str { + use std::str; + let s = self.byte_vector(offset); + unsafe { str::from_utf8_unchecked(s) } + } + + /// Retrieve a struct table from offset. + pub fn get_struct>>(&self, offset: UOffsetT) -> T { + let pos = self.pos as UOffsetT + offset; + let table = Table::with_pos(self.buffer, pos); + table.into() + } + + /// Accesor function for the tables position in the buffer. + #[inline] + pub fn get_pos(&self) -> UOffsetT { + self.pos as UOffsetT + } + + /// Reads an offset at exact position. + pub fn read_uoffset(&self, offset: UOffsetT) -> UOffsetT { + read_uoffset(self.buffer, offset) + } +} + +/// Read a Unsigned offset value at given offset +pub fn read_uoffset(buf: &[u8], offset: UOffsetT) -> UOffsetT { + LittleEndian::read_u32(&buf[offset as usize..]) +} + +/// Read a Signed offset value at given offset +pub fn read_soffset(buf: &[u8], offset: UOffsetT) -> SOffsetT { + LittleEndian::read_i32(&buf[offset as usize..]) +} + +impl<'a> From<&'a [u8]> for Table<'a> { + fn from(buf: &[u8]) -> Table { + Table::from_offset(buf, 0) + } +} diff --git a/rust/src/types.rs b/rust/src/types.rs new file mode 100644 index 0000000000..80f7ee26c4 --- /dev/null +++ b/rust/src/types.rs @@ -0,0 +1,19 @@ + +/// A SOffsetT stores a signed offset into arbitrary data. +pub type SOffsetT = i32; + +/// A UOffsetT stores an unsigned offset into vector data. +pub type UOffsetT = u32; + +/// A VOffsetT stores an unsigned offset in a vtable. +pub type VOffsetT = u16; + +/// Byte size of a `VOffsetT`. +pub const VOFFSETT_SIZE: usize = 2; +/// Byte size of a `UOffsetT`. +pub const UOFFSETT_SIZE: usize = 4; + +/// Number of metadata fields in a `VTable`. +pub const VTABLE_METADATA_FIEDS: usize = 2; +/// Byte size of `Vtable` metadata. +pub const VTABLE_METADATA_SIZE: usize = VTABLE_METADATA_FIEDS * VOFFSETT_SIZE; diff --git a/samples/monster_generated.h b/samples/monster_generated.h index cf45bbb91f..1a16126a56 100644 --- a/samples/monster_generated.h +++ b/samples/monster_generated.h @@ -5,12 +5,13 @@ #include "flatbuffers/flatbuffers.h" - namespace MyGame { namespace Sample { struct Vec3; + struct Monster; + struct Weapon; enum Color { @@ -55,8 +56,11 @@ MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS { : x_(flatbuffers::EndianScalar(_x)), y_(flatbuffers::EndianScalar(_y)), z_(flatbuffers::EndianScalar(_z)) { } float x() const { return flatbuffers::EndianScalar(x_); } + void mutate_x(float _x) { flatbuffers::WriteScalar(&x_, _x); } float y() const { return flatbuffers::EndianScalar(y_); } + void mutate_y(float _y) { flatbuffers::WriteScalar(&y_, _y); } float z() const { return flatbuffers::EndianScalar(z_); } + void mutate_z(float _z) { flatbuffers::WriteScalar(&z_, _z); } }; STRUCT_END(Vec3, 12); @@ -73,14 +77,23 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_EQUIPPED = 22 }; const Vec3 *pos() const { return GetStruct(VT_POS); } + Vec3 *mutable_pos() { return GetStruct(VT_POS); } int16_t mana() const { return GetField(VT_MANA, 150); } + bool mutate_mana(int16_t _mana) { return SetField(VT_MANA, _mana); } int16_t hp() const { return GetField(VT_HP, 100); } + bool mutate_hp(int16_t _hp) { return SetField(VT_HP, _hp); } const flatbuffers::String *name() const { return GetPointer(VT_NAME); } + flatbuffers::String *mutable_name() { return GetPointer(VT_NAME); } const flatbuffers::Vector *inventory() const { return GetPointer *>(VT_INVENTORY); } + flatbuffers::Vector *mutable_inventory() { return GetPointer *>(VT_INVENTORY); } Color color() const { return static_cast(GetField(VT_COLOR, 2)); } + bool mutate_color(Color _color) { return SetField(VT_COLOR, static_cast(_color)); } const flatbuffers::Vector> *weapons() const { return GetPointer> *>(VT_WEAPONS); } + flatbuffers::Vector> *mutable_weapons() { return GetPointer> *>(VT_WEAPONS); } Equipment equipped_type() const { return static_cast(GetField(VT_EQUIPPED_TYPE, 0)); } + bool mutate_equipped_type(Equipment _equipped_type) { return SetField(VT_EQUIPPED_TYPE, static_cast(_equipped_type)); } const void *equipped() const { return GetPointer(VT_EQUIPPED); } + void *mutable_equipped() { return GetPointer(VT_EQUIPPED); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField(verifier, VT_POS) && @@ -150,7 +163,9 @@ struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_DAMAGE = 6 }; const flatbuffers::String *name() const { return GetPointer(VT_NAME); } + flatbuffers::String *mutable_name() { return GetPointer(VT_NAME); } int16_t damage() const { return GetField(VT_DAMAGE, 0); } + bool mutate_damage(int16_t _damage) { return SetField(VT_DAMAGE, _damage); } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField(verifier, VT_NAME) && @@ -192,6 +207,8 @@ inline bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *union_o inline const MyGame::Sample::Monster *GetMonster(const void *buf) { return flatbuffers::GetRoot(buf); } +inline Monster *GetMutableMonster(void *buf) { return flatbuffers::GetMutableRoot(buf); } + inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer(); } inline void FinishMonsterBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset root) { fbb.Finish(root); } diff --git a/src/flatc.cpp b/src/flatc.cpp index d4be151c8f..869320317f 100644 --- a/src/flatc.cpp +++ b/src/flatc.cpp @@ -78,6 +78,11 @@ const Generator generators[] = { flatbuffers::IDLOptions::kMAX, "Generate PHP files for tables/structs", flatbuffers::GeneralMakeRule }, + { flatbuffers::GenerateRust, "-r", "--rust", "Rust", + flatbuffers::IDLOptions::kMAX, + "Generate Rust files for tables/structs", + flatbuffers::GeneralMakeRule }, + }; const char *program_name = nullptr; @@ -122,6 +127,7 @@ static void Error(const std::string &err, bool usage, bool show_exe_name) { " This may crash flatc given a mismatched schema.\n" " --proto Input is a .proto, translate to .fbs.\n" " --schema Serialize schemas instead of JSON (use with -b)\n" + " --strict-rust Follow naming conventions for Rust.\n" "FILEs may be schemas, or JSON files (conforming to preceding schema)\n" "FILEs after the -- must be binary flatbuffer format files.\n" "Output files are named using the base file name of the input,\n" @@ -197,6 +203,8 @@ int main(int argc, const char *argv[]) { } else if(arg == "--version") { printf("flatc version %s\n", FLATC_VERSION); exit(0); + } else if(arg == "--strict-rust") { + opts.strict_rust = true; } else { for (size_t i = 0; i < num_generators; ++i) { if (arg == generators[i].generator_opt_long || diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index f0daca26a4..025b463407 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -64,7 +64,7 @@ static std::string TranslateNameSpace(const std::string &qualified_name) { // Return a C++ type from the table in idl.h static std::string GenTypeBasic(const Type &type, bool user_facing_type) { static const char *ctypename[] = { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ #CTYPE, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp index 4a4e54dc4a..d958f55313 100644 --- a/src/idl_gen_general.cpp +++ b/src/idl_gen_general.cpp @@ -224,7 +224,7 @@ static std::string GenTypeBasic(const LanguageParameters &lang, const Parser &pa const Type &type, bool enableLangOverrides) { static const char *gtypename[] = { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ #JTYPE, #NTYPE, #GTYPE, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD diff --git a/src/idl_gen_go.cpp b/src/idl_gen_go.cpp index bce8f95bc3..aed0115744 100644 --- a/src/idl_gen_go.cpp +++ b/src/idl_gen_go.cpp @@ -617,7 +617,7 @@ static bool SaveType(const Parser &parser, const Definition &def, static std::string GenTypeBasic(const Type &type) { static const char *ctypename[] = { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ #GTYPE, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD diff --git a/src/idl_gen_php.cpp b/src/idl_gen_php.cpp index b43ea67029..9a44590f4b 100644 --- a/src/idl_gen_php.cpp +++ b/src/idl_gen_php.cpp @@ -898,7 +898,7 @@ namespace php { static std::string GenTypeBasic(const Type &type) { static const char *ctypename[] = { -#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ +#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ #NTYPE, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD diff --git a/src/idl_gen_python.cpp b/src/idl_gen_python.cpp index ee6d168744..306fa24c5c 100644 --- a/src/idl_gen_python.cpp +++ b/src/idl_gen_python.cpp @@ -591,7 +591,7 @@ static bool SaveType(const Parser &parser, const Definition &def, static std::string GenTypeBasic(const Type &type) { static const char *ctypename[] = { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ #PTYPE, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD diff --git a/src/idl_gen_rust.cpp b/src/idl_gen_rust.cpp new file mode 100644 index 0000000000..88e18d22a1 --- /dev/null +++ b/src/idl_gen_rust.cpp @@ -0,0 +1,1264 @@ +/* + * Copyright 2014 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. + */ + +// independent from idl_parser, since this code is not needed for most clients + +#include + +#include "flatbuffers/flatbuffers.h" +#include "flatbuffers/idl.h" +#include "flatbuffers/util.h" +#include "flatbuffers/code_generators.h" + +namespace flatbuffers { +namespace rust { + +static std::string GenGetter(const Type &type); +static std::string GenMethod(const FieldDef &field); +static void GenStructBuilder(const StructDef &struct_def, + std::string *code_ptr); +static std::string GenTypeBasic(const Type &type); +static std::string GenTypeGet(const Type &type); +static std::string TypeName(const FieldDef &field); + +// Hardcode spaces per indentation. +const std::string Indent = " "; + +// Format a module name from struct/enum definitions. +static std::string ModName(std::string &def_name) { + std::string name = def_name; + std::transform(name.begin(), name.end(), + name.begin(), ::tolower); + return name; +} + +// Begin by declaring namespace and imports. +static void BeginFile(const bool needs_imports, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += "//! Automatically generated, do not modify.\n\n"; + if (needs_imports) { + // the flatbuffers runtime lib + code += "use flatbuffers;\n"; + // definitions in the same namepsace + code += "use super::*;\n\n"; + } +} + +// Begin a table struct declaration. +static void TableStructDefinition(const StructDef &struct_def, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += "#[derive(Debug)]\n"; + code += "pub struct " + struct_def.name + "<'a> {\n"; + code += Indent + "table: flatbuffers::Table<'a>,\n"; + code += "}\n\n"; +} + +std::string GenFieldOffsetName(const FieldDef &field, + bool qualified) { + std::string uname = field.name; + std::transform(uname.begin(), uname.end(), uname.begin(), ::toupper); + if (qualified) { + return "VT::" + uname; + } else { + return uname; + } +} + +// Vtable Enum defintion +static void VtableDefinition(const StructDef &struct_def, + std::string *code_ptr) { + std::string &code = *code_ptr; + if (struct_def.fields.vec.size() > 0) { + code += "enum VT {\n"; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); + ++it) { + auto &field = **it; + if (!field.deprecated) { // Deprecated fields won't be accessible. + code += Indent + GenFieldOffsetName(field, false) + " = "; + code += NumToString(field.value.offset); + code += ","; + if (field.padding) { + code += "// Padding" + NumToString(field.padding) + "\n"; + } else { + code += "\n"; + } + } + } + code += "}\n\n"; + } +} + +// Start Table Struct implimentation functions +static void BeginTableImpl(const StructDef &struct_def, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += "impl<'a> " + struct_def.name + "<'a> {\n"; +} + +// End Struct implimentation functions +static void EndImpl(std::string *code_ptr) { + std::string &code = *code_ptr; + code += "}\n\n"; +} + +// A single enum member definition +static void EnumUnionMember(const EnumVal ev, std::string *code_ptr) { + std::string &code = *code_ptr; + code += Indent; + if (ev.name.compare("NONE") == 0) { + code += "None,\n"; + } else { + // TODO dont assume table + code += ev.name + "(" +ev.name + "<'a>),\n"; + } +} + +// A wrapper aroudn a union Enum to use as a return type in accessor +// functions +static void EnumUnionImpl(const EnumDef &enum_def, std::string *code_ptr) { + std::string &code = *code_ptr; + std::string uname = enum_def.name + "Union"; + code += "#[derive(Debug)]\n"; + code += "pub enum " + uname + "<'a> {\n"; + for (auto it = enum_def.vals.vec.begin(); + it != enum_def.vals.vec.end(); + ++it) { + auto &ev = **it; + EnumUnionMember(ev, code_ptr); + } + code += "}\n\n"; + code += "impl<'a> " + enum_def.name + "Union<'a> {\n"; + code += Indent + "pub fn from_type("; + code += "table: &'a flatbuffers::Table, t: "; + code += enum_def.name + ", offset: usize) -> "; + code += enum_def.name + "Union<'a> {\n"; + code += Indent + Indent + "match t {\n"; + for (auto it = enum_def.vals.vec.begin(); + it != enum_def.vals.vec.end(); + ++it) { + auto &ev = **it; + code += Indent + Indent + Indent; + if (ev.name.compare("NONE") == 0) { + code += enum_def.name + "::NONE => {\n"; + code += Indent + Indent + Indent + Indent; + code += uname + "::None\n"; + code += Indent + Indent + Indent; + code +="}\n"; + } else { + code += enum_def.name +"::" + ev.name; + code += " => {\n"; + code += Indent + Indent + Indent +Indent; + code += uname + "::" + ev.name +"("; + code += "table.get_root(offset as u32).into()"; + code += ")\n"; + code += Indent + Indent + Indent; + code += "}\n"; + } + } + code += Indent + Indent + "}\n"; + code += Indent + "}\n"; + code += "}\n\n"; +} + + +// Begin enum code with a class declaration. +static void BeginEnum(const EnumDef &enum_def, std::string *code_ptr) { + std::string &code = *code_ptr; + code += "#[derive(PartialEq, Eq, Clone, Debug, Hash)]\n"; + code += "#[repr(" + GenTypeGet(enum_def.underlying_type) + ")]\n"; + code += "pub enum " + enum_def.name + " {\n"; +} + +// A single enum member definition +static void EnumMember(const EnumVal ev, std::string *code_ptr) { + std::string &code = *code_ptr; + code += Indent; + code += ev.name; + code += " = " + NumToString(ev.value) + ",\n"; +} + +// A single enum member match on value return type +static void EnumValueMatch(const std::string class_name, + const EnumVal ev, std::string *code_ptr) { + std::string &code = *code_ptr; + code += Indent + Indent + Indent; + code += NumToString(ev.value) + " => " ; + code += class_name + "::" + ev.name+ ",\n"; +} + + // A single enum member match on type return name +static void EnumNameMatch(const std::string class_name, + const EnumVal ev, std::string *code_ptr) { + std::string &code = *code_ptr; + code += Indent + Indent + Indent; + code += class_name + "::" + ev.name; + code += " => \"" + ev.name + "\",\n"; +} + +// Const to list all Enum variants +static void EnumConst(const EnumDef &enum_def, std::string *code_ptr) { + std::string &code = *code_ptr; + std::string uname = enum_def.name; + std::transform(uname.begin(), uname.end(), uname.begin(), ::toupper); + code += "/// A List of all `"+ enum_def.name + "` enum variants.\n"; + code += "pub const " + uname + "_LIST: ["; + code += enum_def.name + ";" + NumToString(enum_def.vals.vec.size()); + code += "] = ["; + for (auto it = enum_def.vals.vec.begin(); + it != enum_def.vals.vec.end(); + ++it) { + auto &ev = **it; + code += enum_def.name + "::" + ev.name + ","; + } + code += "];\n\n"; +} + +// Impl for Enum +static void EnumImpl(const EnumDef &enum_def, std::string *code_ptr) { + EnumConst(enum_def, code_ptr); + std::string &code = *code_ptr; + code += "impl " + enum_def.name + " {\n"; + code += Indent; + code += "/// Returns a `str` representation of a `"+ enum_def.name; + code += "` enum.\n"; + code += Indent + "pub fn name(&self) -> &'static str {\n"; + code += Indent + Indent; + code += "match *self {\n"; + for (auto it = enum_def.vals.vec.begin(); + it != enum_def.vals.vec.end(); + ++it) { + auto &ev = **it; + EnumNameMatch(enum_def.name, ev, code_ptr); + } + code += Indent + Indent + "}\n"; + code += Indent + "}\n"; + code += "}\n\n"; +} + +// Enum Impl for From trait +static void EnumFromImpl(const EnumDef &enum_def, std::string *code_ptr) { + std::string &code = *code_ptr; + code += "impl From<"; + code += GenTypeGet(enum_def.underlying_type); + code += "> for " + enum_def.name + " {\n"; + code += Indent + "fn from(value: "; + code += GenTypeGet(enum_def.underlying_type); + code += ") -> " + enum_def.name; + code += " {\n"; + code += Indent + Indent; + code += "match value {\n"; + for (auto it = enum_def.vals.vec.begin(); + it != enum_def.vals.vec.end(); + ++it) { + auto &ev = **it; + EnumValueMatch(enum_def.name, ev, code_ptr); + } + code += Indent + Indent + Indent; + code += "_ => unreachable!(\"Unable to create a `" + enum_def.name; + code += "` from value {} \", value),\n"; + code += Indent + Indent + "}\n"; + code += Indent + "}\n"; + code += "}\n\n"; +} + +// Enum Impl for From trait +// static void EnumFromRefImpl(const EnumDef &enum_def, std::string *code_ptr) { +// std::string &code = *code_ptr; +// code += "impl<'a> From<&'a "; +// code += GenTypeGet(enum_def.underlying_type); +// code += "> for &'a " + enum_def.name + " {\n"; +// code += Indent + "fn from(value: &"; +// code += GenTypeGet(enum_def.underlying_type); +// code += ") -> &" + enum_def.name; +// code += " {\n"; +// code += Indent + Indent; +// code += "unsafe {\n"; +// code += Indent + Indent + Indent; +// code += "use std::mem;\n"; +// code += Indent + Indent + Indent; +// code += "mem::transmute(value)\n"; +// code += Indent + Indent + "}\n"; +// code += Indent + "}\n"; +// code += "}\n\n"; +// } + + +// End enum code. +static void EndEnum(std::string *code_ptr) { + std::string &code = *code_ptr; + code += "}\n\n"; +} + +// Initialize a new struct or table from existing data. +static void NewRootTypeFromBuffer(const StructDef &struct_def, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += Indent + "pub fn new"; + code += "(buf: &[u8], offset: flatbuffers::UOffsetT) -> "; + code += struct_def.name + " {\n"; + code += Indent + Indent; + code += struct_def.name + " {\n"; + code += Indent + Indent + Indent; + if (struct_def.fixed) { + code += "table: flatbuffers::Table::with_pos(buf, offset),\n"; + } else { + code += "table: flatbuffers::Table::from_offset(buf, offset),\n"; + } + code += Indent + Indent + "}\n"; + code += Indent + "}\n\n"; +} + +// Most field accessors need to retrieve and test the field offset first, +// this is the prefix code for that. +std::string OffsetPrefix(const FieldDef &field) { + return Indent + Indent + + "let offset = self.table.field_offset(" + + GenFieldOffsetName(field, true) + + " as u16);\n" + Indent + Indent + "if offset != 0 {\n"; +} + +//Get the value of a struct's scalar. +static void GetScalarFieldOfStruct(const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + std::string getter = GenGetter(field.value.type); + std::string unsigned_type = TypeName(field); + bool is_enum = false; + if (field.value.type.enum_def) { + is_enum = true; + } + code += Indent + "pub fn "; + code += field.name + "(&self) -> "; + if (is_enum) { + code += field.value.type.enum_def->name; + } else { + code += TypeName(field); + } + code += " {\n"; + code += Indent + Indent; + code += "let offset = "; + code += GenFieldOffsetName(field, true) + " as u32;\n"; + code += Indent + Indent; + code += "return " + getter + "offset)"; + if (is_enum) { + code += ".into()"; + } + code += "\n"; + code += Indent + "}\n\n"; +} + +static std::string MapConstant(const FieldDef &field) { + if ( (IsScalar(field.value.type.base_type)) + && (TypeName(field).compare("bool") == 0) ) { + if (field.value.constant == "0") { + return "false"; + } + return "true"; + } + return field.value.constant; +} + +// Get the value of a table's scalar. +static void GetScalarFieldOfTable(const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + std::string getter = GenGetter(field.value.type); + bool is_enum = false; + if (field.value.type.enum_def) { + is_enum = true; + } + code += Indent + "pub fn "; + code += field.name + "(&self) -> "; + if (is_enum) { + code += field.value.type.enum_def->name; + } else { + code += TypeName(field); + } + code += " {\n"; + code += OffsetPrefix(field); + code += Indent + Indent + Indent + "return " + getter; + code += "offset)"; + if (is_enum) { + code += ".into()"; + } + code += "\n"; + code += Indent + Indent + "}\n"; + code += Indent + Indent + MapConstant(field); + if (is_enum) { + code += ".into()"; + } + code += "\n" +Indent + "}\n\n"; +} + +// Get a struct by initializing an existing struct. +// Specific to Struct. +static void GetStructFieldOfStruct(const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += Indent + "pub fn " + field.name; + code += "(&self) -> "+ TypeName(field) +" {\n"; + code += Indent + Indent; + code += "let offset = " + GenFieldOffsetName(field, true); + code += " as u32;\n"; + code += Indent + Indent + " return self.table.get_struct"; + code += "::<" + TypeName(field) + ">"; + code += "(offset)\n"; + code += Indent + "}\n\n"; +} + +// Get a struct by initializing an existing struct. +// Specific to Table. +static void GetStructFieldOfTable(const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += Indent + "pub fn " + field.name; + code += "(&self) -> Option<"+ TypeName(field) + "> {\n"; + code += OffsetPrefix(field); + if (field.value.type.struct_def->fixed) { + /// struct stored inli + code += Indent + Indent + Indent + " return Some(self.table.get_struct"; + code += "::<" + TypeName(field) + ">"; + code += "(offset))\n"; + } else { + code += Indent + Indent + Indent; + code += "return Some(self.table.get_indirect_root(offset).into())\n"; + } + code += Indent + Indent + "};\n"; + code += Indent + Indent + "None\n"; + code += Indent + "}\n\n"; +} + +// Get the value of a string. +static void GetStringField(const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += Indent + "pub fn " + field.name; + code += "(&self) -> &str {\n"; + code += OffsetPrefix(field); + code += Indent + Indent + Indent + "return " + GenGetter(field.value.type); + code += "offset)\n"; + code += Indent + Indent + "}\n"; + code += Indent + Indent + "\"\"\n"; + code += Indent + "}\n\n"; +} + +// Get the value of a union from an object. +static void GetUnionField(const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += Indent + "pub fn " + field.name; + code += "(&self) -> "; + code += TypeName(field) + " {\n"; + code += OffsetPrefix(field); + code += Indent + Indent + Indent + "let t = self."; + code += field.name +"_type();\n"; + code += Indent + Indent + Indent; + code += Indent + Indent + Indent + "return "; + code += TypeName(field) + "::from_type(&self.table"; + code += ", t, offset as usize);\n"; + code += Indent + Indent + "}\n"; + code += Indent +Indent + TypeName(field) + "::None\n"; + code += Indent + "}\n\n"; +} + +// Get the value of a vector's struct member. +static void GetMemberOfVectorOfStruct(const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + auto vectortype = field.value.type.VectorType(); + code += Indent + "pub fn " + field.name; + code += "(&self) -> flatbuffers::Iterator<"; + code += TypeName(field) + "> {\n"; + code += OffsetPrefix(field); + code += Indent + Indent + Indent; + if (!(vectortype.struct_def->fixed)) { + code += "return self.table"; + code += ".table_vector(offset)\n"; + } else { + code += "return self.table"; + code += ".struct_vector(offset)\n"; + } + code += Indent + Indent + "}\n"; + code += Indent +Indent + "flatbuffers::empty_iterator(&self.table)\n"; + code += Indent + "}\n\n"; +} + +// Get the value of a vector's non-struct member. +static void GetMemberOfVectorOfNonStruct(const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += Indent + "pub fn " + field.name; + if (field.value.type.VectorType().base_type == BASE_TYPE_STRING) { + code += "(&self) -> flatbuffers::Iterator<"; + code += TypeName(field) + "> {\n"; + } else { + code += "(&self) -> &["; + code += TypeName(field) + "] {\n"; + } + + code += OffsetPrefix(field); + code += Indent + Indent + Indent; + code += "return " + GenGetter(field.value.type); + code += "offset);\n"; + code += Indent + Indent + "}\n"; + if (field.value.type.VectorType().base_type == BASE_TYPE_STRING) { + code += Indent + Indent + "flatbuffers::empty_iterator(&self.table)"; + } else { + code += Indent +Indent + "&[]\n"; + } + code += Indent + "}\n\n"; +} + +// Begin the creator function signature. +static void BeginBuilderArgs(const StructDef &struct_def, + std::string *code_ptr) { + std::string &code = *code_ptr; + std::string lname = struct_def.name; + std::transform(lname.begin(), lname.end(), lname.begin(), ::tolower); + code += "pub fn build_" + lname; + code += "(builder: &mut flatbuffers::Builder"; +} + +// Recursively generate arguments for a constructor, to deal with nested +// structs. +static void StructBuilderArgs(const StructDef &struct_def, + const char *nameprefix, + std::string *code_ptr, + bool name_only = false) { + std::string &code = *code_ptr; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); + ++it) { + auto &field = **it; + if (IsStruct(field.value.type)) { + // Generate arguments for a struct inside a struct. To ensure names + // don't clash, and to make it obvious these arguments are constructing + // a nested struct, prefix the name with the field name. + StructBuilderArgs(*field.value.type.struct_def, + (nameprefix + (field.name + "_")).c_str(), + code_ptr, name_only); + } else { + code += (std::string)", " + nameprefix; + code += field.name; + if (!name_only) { + code += ": " + GenTypeBasic(field.value.type); + } + } + } +} + +// End the creator function signature. +static void EndBuilderArgs(std::string *code_ptr) { + std::string &code = *code_ptr; + code += ") -> flatbuffers::UOffsetT {\n"; +} + +// Recursively generate struct construction statements and instert manual +// padding. +static void StructBuilderBody(const StructDef &struct_def, + const char *nameprefix, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += " builder.prep(" + NumToString(struct_def.minalign) + ", "; + code += NumToString(struct_def.bytesize) + ");\n"; + for (auto it = struct_def.fields.vec.rbegin(); + it != struct_def.fields.vec.rend(); + ++it) { + auto &field = **it; + if (field.padding) + code += " builder.pad(" + NumToString(field.padding) + ");\n"; + if (IsStruct(field.value.type)) { + StructBuilderBody(*field.value.type.struct_def, + (nameprefix + (field.name + "_")).c_str(), + code_ptr); + } else { + code += " builder.add_" + GenMethod(field) + "("; + code += nameprefix + field.name + ");\n"; + } + } +} + +// End the builder function +static void EndBuilderBody(std::string *code_ptr) { + std::string &code = *code_ptr; + code += " builder.offset() as flatbuffers::UOffsetT \n"; + code += "}\n"; +} + +// Init functions for the table Builder object +static void GenTableBuilderInitFn(std::string *code_ptr) { + std::string &code = *code_ptr; + code += Indent + "/// Create a new builder.\n"; + code += Indent + "pub fn with_capacity(size: usize) -> Self {\n"; + code += Indent + Indent + "Builder {\n"; + code += Indent + Indent + Indent + "inner: flatbuffers"; + code += "::Builder::with_capacity(size),\n"; + code += Indent + Indent + "}\n"; + code += Indent + "}\n\n"; +} + + // Add Default, From, Into and ObjectBuilder traits. +static void GenTableBuilderBoilerPlate(std::string *code_ptr) { + std::string &code = *code_ptr; + // Default + code += "impl Default for Builder {\n"; + code += Indent + "fn default() -> Builder {\n"; + code += Indent + Indent +"Builder::with_capacity(1024)\n"; + code += Indent +"}\n"; + code += "}\n\n"; + // From + code += "impl From for Builder {\n"; + code += Indent + "fn from(b: flatbuffers::Builder) -> Builder {\n"; + code += Indent + Indent +"Builder {\n"; + code += Indent + Indent + Indent + "inner: b,\n"; + code += Indent + Indent + "}\n"; + code += Indent +"}\n"; + code += "}\n\n"; + // Into + code += "impl Into for Builder {\n"; + code += Indent + "fn into(self) -> flatbuffers::Builder {\n"; + code += Indent + Indent +"self.inner\n"; + code += Indent +"}\n"; + code += "}\n\n"; + // ObjectBuilder + code += "impl flatbuffers::ObjectBuilder for Builder {}\n\n"; +} + +// Get the value of a table's starting offset. +static void GetStartOfTable(const StructDef &struct_def, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += Indent; + code += "/// Initialize a new `Builder` for a `"; + code += struct_def.name + "` table.\n"; + code += Indent; + code += "pub fn start(&mut self) {\n"; + code += Indent + Indent; + code += "self.inner.start_object("; + code += NumToString(struct_def.fields.vec.size()); + code += ");\n"; + code += Indent + "}\n\n"; +} + +// Set the value of a table's field. +static void BuildFieldOfTable(const StructDef &struct_def, + const FieldDef &field, + const size_t offset, + std::string *code_ptr) { + std::string &code = *code_ptr; + std::string lname = struct_def.name; + std::transform(lname.begin(), lname.end(), lname.begin(), ::tolower); + code += Indent; + code += "/// Set the value for field `" + field.name + "`.\n"; + code += Indent; + code += "pub fn add_" + field.name; + code += "(&mut self, "; + code += field.name + ": "; + if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) { + code += "flatbuffers::UOffsetT"; + } else { + code += GenTypeBasic(field.value.type); + } + code += ") {\n"; + code += Indent + Indent; + code += "self.inner.add_slot_"; + code += GenMethod(field) + "("; + code += NumToString(offset) + ", "; + code += field.name; + code += ", " + MapConstant(field); + code += ")\n"; + code += Indent + "}\n\n"; +} + +// Set the value of one of the members of a table's vector. +static void BuildVectorOfTable(const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += Indent; + code += "/// Initializes bookkeeping for writing a new `"; + code += field.name + "` vector.\n"; + code += Indent; + code += "pub fn start_"; + code += field.name; + code += "_vector(&mut self, numElems: usize) {\n"; + code += Indent + Indent; + code += "self.inner.start_vector("; + auto vector_type = field.value.type.VectorType(); + auto alignment = InlineAlignment(vector_type); + auto elem_size = InlineSize(vector_type); + code += NumToString(elem_size); + code += ", numElems, " + NumToString(alignment); + code += ")\n"; + code += Indent + "}\n\n"; +} + +// Get the offset of the end of a table. +static void GenEndOfTable(std::string *code_ptr) { + std::string &code = *code_ptr; + code += Indent; + code += "/// Finalize the current object and return the offset.\n"; + code += Indent; + code += "pub fn end"; + code += "(&mut self) -> flatbuffers::UOffsetT {\n"; + code += Indent + Indent + "return self.inner.end_object()\n"; + code += Indent + "}\n\n"; +} + +// Get the offset of the end of a table. +static void GenFinishOnTable(std::string *code_ptr) { + std::string &code = *code_ptr; + code += Indent; + code += "/// Finish the buffer.\n"; + code += Indent; + code += "pub fn finish"; + code += "(&mut self, r: flatbuffers::UOffsetT) {\n"; + code += Indent + Indent + "return self.inner.finish(r)\n"; + code += Indent + "}\n\n"; +} + +// Generic builder functions. +// This table builder wraps an inner flatbuffers:Builder +// so these are conveniance functions that delegate to the +// inner builder +static void GenBuilderFns(std::string *code_ptr) { + std::string &code = *code_ptr; + std::string inner = "self.inner."; + code += Indent; + code += "pub fn create_string(&mut self, v: &str) -> flatbuffers::UOffsetT { "; + code += inner +"create_string(v) }\n"; + code += Indent; + code += "pub fn get_bytes(&self) -> &[u8] { "; + code += inner +"get_bytes() }\n"; + code += Indent; + code += "pub fn len(&self) -> usize { "; + code += inner +"len() }\n"; + code += Indent; + code += "pub fn offset(&self) -> usize { "; + code += inner +"offset() }\n"; + code += Indent; + code += "pub fn reset(&mut self) { "; + code += inner +"reset() }\n"; + code += Indent; + code += "pub fn prep(&mut self, s:usize, a: usize) { "; + code += inner +"prep(s,a) }\n"; + code += Indent; + code += "pub fn pad(&mut self, n:usize) { "; + code += inner +"pad(n) }\n"; + code += Indent; + code += "pub fn end_vector(&mut self) -> flatbuffers::UOffsetT { "; + code += inner +"end_vector() }\n"; + + code += Indent; + code += "pub fn add_bool(&mut self, v:bool) { "; + code += inner +"add_bool(v) }\n"; + code += Indent; + code += "pub fn add_u8(&mut self, v:u8) { "; + code += inner +"add_u8(v) }\n"; + code += Indent; + code += "pub fn add_i8(&mut self, v:i8) { "; + code += inner +"add_i8(v) }\n"; + code += Indent; + code += "pub fn add_u16(&mut self, v:u16) { "; + code += inner +"add_u16(v) }\n"; + code += Indent; + code += "pub fn add_i16(&mut self, v:i16) { "; + code += inner +"add_i16(v) }\n"; + code += Indent; + code += "pub fn add_u32(&mut self, v:u32) { "; + code += inner +"add_u32(v) }\n"; + code += Indent; + code += "pub fn add_i32(&mut self, v:i32) { "; + code += inner +"add_i32(v) }\n"; + code += Indent; + code += "pub fn add_u64(&mut self, v:u64) { "; + code += inner +"add_u64(v) }\n"; + code += Indent; + code += "pub fn add_i64(&mut self, v:i64) { "; + code += inner +"add_i64(v) }\n"; + code += Indent; + code += "pub fn add_f32(&mut self, v:f32) { "; + code += inner +"add_f32(v) }\n"; + code += Indent; + code += "pub fn add_f64(&mut self, v:f64) { "; + code += inner +"add_f64(v) }\n"; + code += Indent; + code += "pub fn add_uoffset(&mut self, v: flatbuffers::UOffsetT) { "; + code += inner +"add_uoffset(v) }\n"; + + code += Indent; + code += "pub fn add_slot_bool(&mut self, o: usize, v: bool, d: bool) { "; + code += inner +"add_slot_bool(o,v,d) }\n"; + code += Indent; + code += "pub fn add_slot_u8(&mut self, o: usize, v: u8, d: u8) { "; + code += inner +"add_slot_u8(o,v,d) }\n"; + code += Indent; + code += "pub fn add_slot_i8(&mut self, o: usize, v: i8, d: i8) { "; + code += inner +"add_slot_i8(o,v,d) }\n"; + code += Indent; + code += "pub fn add_slot_u16(&mut self, o: usize, v: u16, d: u16) { "; + code += inner +"add_slot_u16(o,v,d) }\n"; + code += Indent; + code += "pub fn add_slot_i16(&mut self, o: usize, v: i16, d: i16) { "; + code += inner +"add_slot_i16(o,v,d) }\n"; + code += Indent; + code += "pub fn add_slot_i32(&mut self, o: usize, v: i32, d: i32) { "; + code += inner +"add_slot_i32(o,v,d) }\n"; + code += Indent; + code += "pub fn add_slot_u32(&mut self, o: usize, v: u32, d: u32) { "; + code += inner +"add_slot_u32(o,v,d) }\n"; + code += Indent; + code += "pub fn add_slot_u64(&mut self, o: usize, v: u64, d: u64) { "; + code += inner +"add_slot_u64(o,v,d) }\n"; + code += Indent; + code += "pub fn add_slot_i64(&mut self, o: usize, v: i64, d: i64) { "; + code += inner +"add_slot_i64(o,v,d) }\n"; + code += Indent; + code += "pub fn add_slot_f32(&mut self, o: usize, v: f32, d: f32) { "; + code += inner +"add_slot_f32(o,v,d) }\n"; + code += Indent; + code += "pub fn add_slot_f64(&mut self, o: usize, v: f64, d: f64) { "; + code += inner +"add_slot_f64(o,v,d) }\n"; + code += Indent; + code += "pub fn add_slot_uoffset(&mut self, o: usize, v: "; + code += "flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { "; + code += inner +"add_slot_uoffset(o,v,d) }\n"; + code += Indent; + code += "pub fn add_slot_struct(&mut self, o: usize, v: "; + code += "flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { "; + code += inner +"add_slot_struct(o,v,d) }\n"; +} + +// Generate a struct field, conditioned on its child type(s). +static void GenStructAccessor(const StructDef &struct_def, + const FieldDef &field, + std::string *code_ptr) { + GenComment(field.doc_comment, code_ptr, nullptr, Indent.c_str()); + if (IsScalar(field.value.type.base_type)) { + if (struct_def.fixed) { + GetScalarFieldOfStruct(field, code_ptr); + } else { + GetScalarFieldOfTable(field, code_ptr); + } + } else { + switch (field.value.type.base_type) { + case BASE_TYPE_STRUCT: + if (struct_def.fixed) { + GetStructFieldOfStruct(field, code_ptr); + } else { + GetStructFieldOfTable(field, code_ptr); + } + break; + case BASE_TYPE_STRING: + GetStringField(field, code_ptr); + break; + case BASE_TYPE_VECTOR: { + auto vectortype = field.value.type.VectorType(); + if (vectortype.base_type == BASE_TYPE_STRUCT) { + GetMemberOfVectorOfStruct(field, code_ptr); + } else { + GetMemberOfVectorOfNonStruct(field, code_ptr); + } + break; + } + case BASE_TYPE_UNION: + GetUnionField(field, code_ptr); + break; + default: + assert(0); + } + } +} + +// Generate table constructors, conditioned on its members' types. +static void GenTableBuilderStructImpl(const StructDef &struct_def, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += "/// Builder Object for `"+ struct_def.name + "` tables.\n"; + code += "pub struct Builder {\n"; + code += Indent + "inner: flatbuffers::Builder,\n"; + code += "}\n\n"; + code += "impl Builder {\n"; +} + +// Generate table constructors, conditioned on its members' types. +static void GenEndTableBuilderStructImpl(std::string *code_ptr) { + std::string &code = *code_ptr; + code += "}\n\n"; +} + +// Build helper functions for simple fixed structs +static void GenTableBuilderFxedFnImpl(const StructDef &struct_def, + std::string *code_ptr) { + std::string &code = *code_ptr; + std::string oname = struct_def.name; + std::string lname = struct_def.name; + std::transform(lname.begin(), lname.end(), + lname.begin(), ::tolower); + code += Indent + "pub fn build_" + lname + "(&mut self "; + StructBuilderArgs(struct_def, "", code_ptr); + code += ") -> flatbuffers::UOffsetT {\n"; + code += Indent + Indent + ModName(oname) + "::build_"; + code += lname + "(&mut self.inner"; + StructBuilderArgs(struct_def, "", code_ptr, true); + code += ")\n"; + code += Indent + "}\n\n"; +} + + + +// Build helper functions for simple fixed structs +static void GenTableBuilderFxedFns(const StructDef &struct_def, + std::string *code_ptr) { + std::set generated; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); + ++it) { + auto &field = **it; + if (field.deprecated) continue; + if (field.value.type.base_type == BASE_TYPE_VECTOR) { + if (field.value.type.element == BASE_TYPE_STRUCT) { + if (field.value.type.struct_def->fixed) { + std::string id = field.value.type.struct_def->name; + auto result_1 = generated.insert(id); + if (result_1.second) { + GenTableBuilderFxedFnImpl(*field.value.type.struct_def, code_ptr); + } + } + } + } + if (field.value.type.base_type == BASE_TYPE_STRUCT) { + if (field.value.type.struct_def->fixed) { + std::string id = field.value.type.struct_def->name; + auto result_1 = generated.insert(id); + if (result_1.second) { + GenTableBuilderFxedFnImpl(*field.value.type.struct_def, code_ptr); + } + } + } + } +} + +// Generate table constructors, conditioned on its members' types. +static void GenTableBuilders(const StructDef &struct_def, + std::string *code_ptr) { + GenTableBuilderStructImpl(struct_def, code_ptr); + GenTableBuilderInitFn(code_ptr); + GetStartOfTable(struct_def, code_ptr); + GenEndOfTable(code_ptr); + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); + ++it) { + auto &field = **it; + if (field.deprecated) continue; + + auto offset = it - struct_def.fields.vec.begin(); + BuildFieldOfTable(struct_def, field, offset, code_ptr); + if (field.value.type.base_type == BASE_TYPE_VECTOR) { + BuildVectorOfTable(field, code_ptr); + } + } + GenTableBuilderFxedFns(struct_def, code_ptr); + GenFinishOnTable(code_ptr); + GenBuilderFns(code_ptr); + GenEndTableBuilderStructImpl(code_ptr); + GenTableBuilderBoilerPlate(code_ptr); +} + +// Generate a From<&framebuffer:Table> impl +static void GenTableFromImpl(const StructDef &struct_def, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += "impl<'a> From> for "; + code += struct_def.name + "<'a> {\n"; + code += Indent + "fn from(table: flatbuffers::Table) -> "; + code += struct_def.name + " {\n"; + code += Indent + Indent + struct_def.name + "{\n"; + code += Indent + Indent + Indent + "table: table,\n"; + code += Indent + Indent + "}\n"; + code += Indent + "}\n"; + code += "}\n\n"; + } + +// Generate struct or table methods. +static void GenStruct(const StructDef &struct_def, + std::string *code_ptr) { + if (struct_def.generated) return; + GenComment(struct_def.doc_comment, code_ptr, nullptr); + + TableStructDefinition(struct_def, code_ptr); + VtableDefinition(struct_def, code_ptr); + BeginTableImpl(struct_def, code_ptr); + NewRootTypeFromBuffer(struct_def, code_ptr); + // Generate the Init method that sets the field in a pre-existing + // accessor object. This is to allow object reuse. + //InitializeExisting(struct_def, code_ptr); + + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); + ++it) { + auto &field = **it; + if (field.deprecated) continue; + GenStructAccessor(struct_def, field, code_ptr); + } + EndImpl(code_ptr); + GenTableFromImpl(struct_def, code_ptr); + + if (struct_def.fixed) { + // create a struct constructor function + GenStructBuilder(struct_def, code_ptr); + } else { + // Create a set of functions that allow table construction. + GenTableBuilders(struct_def, code_ptr); + } +} + +// Generate enum declarations. +static void GenEnum(const EnumDef &enum_def, std::string *code_ptr) { + if (enum_def.generated) return; + + GenComment(enum_def.doc_comment, code_ptr, nullptr); + BeginEnum(enum_def, code_ptr); + for (auto it = enum_def.vals.vec.begin(); + it != enum_def.vals.vec.end(); + ++it) { + auto &ev = **it; + GenComment(ev.doc_comment, code_ptr, nullptr, Indent.c_str()); + EnumMember(ev, code_ptr); + } + EndEnum(code_ptr); + EnumImpl(enum_def, code_ptr); + EnumFromImpl(enum_def, code_ptr); + if (enum_def.is_union) { + EnumUnionImpl(enum_def, code_ptr); + } +} + +// Returns the function name that is able to read a value of the given type. +static std::string GenGetter(const Type &type) { + switch (type.base_type) { + case BASE_TYPE_STRING: return "self.table.get_str("; + case BASE_TYPE_UNION: return "let obj = self.table \ + .get_union::<"+ type.enum_def->name + ">("; + case BASE_TYPE_VECTOR: + if (type.VectorType().base_type == BASE_TYPE_STRING) { + return "self.table.str_vector("; + } else if (type.VectorType().base_type==BASE_TYPE_UCHAR) { + return "self.table.byte_vector("; + } else if (type.VectorType().base_type==BASE_TYPE_BOOL) { + return "self.table.bool_vector("; + } else if (type.VectorType().base_type==BASE_TYPE_CHAR) { + return "self.table.ibyte_vector("; + } + default: + return "self.table.get_" + \ + GenTypeGet(type) + "("; + } +} + +// Returns the method name for use with add/put calls. +static std::string GenMethod(const FieldDef &field) { + return IsScalar(field.value.type.base_type) + ? GenTypeBasic(field.value.type) + : (IsStruct(field.value.type) ? "struct" : "uoffset"); +} + + +// Generate the mod.rs export. +static std::string GenNameSpaceExports(const Parser &parser_, + std::string &namespace_name) { + std::string code = ""; + std::string re_exports = ""; + code += "//! Automatically generated, do not modify\n"; + code += "//!\n"; + code += "//! Flatbuffer definitions for the " + namespace_name; + code += " namespace.\n"; + for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); + ++it) { + auto &enum_def = **it; + std::string mod_name = ModName(enum_def.name); + std::string qname = enum_def.defined_namespace->components.back(); + if (namespace_name.compare(qname) == 0) { + code += "mod " + mod_name + ";\n"; + re_exports += "pub use self::" + mod_name + "::*;\n"; + } + } + + for (auto it = parser_.structs_.vec.begin(); + it != parser_.structs_.vec.end(); ++it) { + auto &struct_def = **it; + std::string mod_name = ModName(struct_def.name); + std::string qname = struct_def.defined_namespace->components.back(); + if (namespace_name.compare(qname) == 0) { + code += "pub mod " + mod_name + ";\n"; + if (struct_def.fixed) { + std::string lname = struct_def.name; + std::transform(lname.begin(), lname.end(), lname.begin(), ::tolower); + re_exports += "pub use self::" + mod_name + "::{"; + re_exports += struct_def.name + ", build_" + lname +"};\n"; + } else { + re_exports += "pub use self::" + mod_name + "::"; + re_exports += struct_def.name + ";\n"; + } + } + } + std::vector components = parser_.namespaces_.back()->components; + int pos = find(components.begin(), + components.end(), + namespace_name) + - components.begin(); + unsigned long next_pos = pos + 1; + if(next_pos < components.size()) { + std::string mod_name = ModName(components[next_pos]); + re_exports += "pub mod " + mod_name; + re_exports += ";\n"; + } + code += "\n" + re_exports; + return code; +} + +// Save out the generated code for a Rust Table type. +static bool SaveType(const Parser &parser, const Definition &def, + const std::string &classcode, const std::string &path, + bool needs_imports) { + if (!classcode.length()) return true; + + std::string namespace_name; + std::string namespace_dir = path; + auto &namespaces = parser.namespaces_.back()->components; + for (auto it = namespaces.begin(); it != namespaces.end(); ++it) { + if (namespace_name.length()) { + namespace_name += "."; + namespace_dir += kPathSeparator; + } + namespace_name = *it; + namespace_dir += *it; + if (parser.opts.strict_rust) { + std::transform(namespace_dir.begin(), namespace_dir.end(), + namespace_dir.begin(), ::tolower); + } + EnsureDirExists(namespace_dir.c_str()); + + std::string mod_filename = namespace_dir + "/mod.rs"; + std::string mod_exports = GenNameSpaceExports(parser, namespace_name); + SaveFile(mod_filename.c_str(), mod_exports, false); + } + + + std::string code = ""; + BeginFile(needs_imports, &code); + code += classcode; + std::string filename = namespace_dir + kPathSeparator + def.name + ".rs"; + if (parser.opts.strict_rust) { + std::transform(filename.begin(), filename.end(), + filename.begin(), ::tolower); + } + return SaveFile(filename.c_str(), code, false); +} + +static std::string GenTypeBasic(const Type &type) { + static const char *ctypename[] = { + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ + #RTYPE, + FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) + #undef FLATBUFFERS_TD + }; + return ctypename[type.base_type]; +} + +static std::string GenTypePointer(const Type &type) { + switch (type.base_type) { + case BASE_TYPE_STRING: + return "&str"; + case BASE_TYPE_VECTOR: + return GenTypeGet(type.VectorType()); + case BASE_TYPE_STRUCT: + return type.struct_def->name; + case BASE_TYPE_UNION: + // fall through + default: + return type.enum_def->name + "Union"; + } +} + +static std::string GenTypeGet(const Type &type) { + return IsScalar(type.base_type) + ? GenTypeBasic(type) + : GenTypePointer(type); +} + +static std::string TypeName(const FieldDef &field) { + return GenTypeGet(field.value.type); +} + +// Create a struct with a builder and the struct's arguments. +static void GenStructBuilder(const StructDef &struct_def, + std::string *code_ptr) { + BeginBuilderArgs(struct_def, code_ptr); + StructBuilderArgs(struct_def, "", code_ptr); + EndBuilderArgs(code_ptr); + + StructBuilderBody(struct_def, "", code_ptr); + EndBuilderBody(code_ptr); +} + +class RustGenerator : public BaseGenerator { + public: + RustGenerator(const Parser &parser, const std::string &path, + const std::string &file_name) + : BaseGenerator(parser, path, file_name){}; + bool generate() { + if (!generateEnums()) return false; + if (!generateStructs()) return false; + return true; + } + + private: + bool generateEnums() { + for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); + ++it) { + auto &enum_def = **it; + std::string enumcode; + GenEnum(enum_def, &enumcode); + bool import = enum_def.is_union; + if (!SaveType(parser_, enum_def, enumcode, path_, import)) return false; + } + return true; + } + + bool generateStructs() { + for (auto it = parser_.structs_.vec.begin(); + it != parser_.structs_.vec.end(); ++it) { + auto &struct_def = **it; + std::string declcode; + GenStruct(struct_def, &declcode); + if (!SaveType(parser_, struct_def, declcode, path_, true)) return false; + } + return true; + } +}; + +} // namespace rust + +bool GenerateRust(const Parser &parser, const std::string &path, + const std::string &file_name) { + rust::RustGenerator generator(parser, path, file_name); + return generator.generate(); +} + +} // namespace flatbuffers diff --git a/src/idl_gen_text.cpp b/src/idl_gen_text.cpp index dd96912cdc..2c5d0a039e 100644 --- a/src/idl_gen_text.cpp +++ b/src/idl_gen_text.cpp @@ -165,7 +165,7 @@ template<> void Print(const void *val, // Call PrintVector above specifically for each element type: switch (type.base_type) { #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ - PTYPE) \ + PTYPE, RTYPE) \ case BASE_TYPE_ ## ENUM: \ PrintVector( \ *reinterpret_cast *>(val), \ @@ -236,7 +236,7 @@ static void GenStruct(const StructDef &struct_def, const Table *table, if (is_present) { switch (fd.value.type.base_type) { #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ - PTYPE) \ + PTYPE, RTYPE) \ case BASE_TYPE_ ## ENUM: \ GenField(fd, table, struct_def.fixed, \ opts, indent + Indent(opts), _text); \ @@ -245,7 +245,7 @@ static void GenStruct(const StructDef &struct_def, const Table *table, #undef FLATBUFFERS_TD // Generate drop-thru case statements for all pointer types: #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ - PTYPE) \ + PTYPE, RTYPE) \ case BASE_TYPE_ ## ENUM: FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD) #undef FLATBUFFERS_TD diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 2bf99eac0c..eb6451a253 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -23,7 +23,7 @@ namespace flatbuffers { const char *const kTypeNames[] = { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ IDLTYPE, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD @@ -31,7 +31,7 @@ const char *const kTypeNames[] = { }; const char kTypeSizes[] = { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ sizeof(CTYPE), FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD @@ -117,7 +117,8 @@ template<> inline CheckedError atot>(const char *s, Parser &parser, } std::string Namespace::GetFullyQualifiedName(const std::string &name, - size_t max_components) const { + size_t max_components, + const std::string &sep) const { // Early exit if we don't have a defined namespace. if (components.size() == 0 || !max_components) { return name; @@ -126,12 +127,12 @@ std::string Namespace::GetFullyQualifiedName(const std::string &name, for (size_t i = 0; i < std::min(components.size(), max_components); i++) { if (i) { - stream << "."; + stream << sep; } stream << components[i]; } - stream << "." << name; + stream << sep << name; return stream.str(); } @@ -164,7 +165,7 @@ enum { #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) kToken ## NAME = VALUE, FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) #undef FLATBUFFERS_TOKEN - #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ kToken ## ENUM, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD @@ -175,7 +176,7 @@ static std::string TokenToString(int t) { #define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) STRING, FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN) #undef FLATBUFFERS_TOKEN - #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ IDLTYPE, FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) #undef FLATBUFFERS_TD @@ -347,7 +348,7 @@ CheckedError Parser::Next() { attribute_.append(start, cursor_); // First, see if it is a type keyword from the table of types: #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ - PTYPE) \ + PTYPE, RTYPE) \ if (attribute_ == IDLTYPE) { \ token_ = kToken ## ENUM; \ return NoError(); \ @@ -800,7 +801,7 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, size == SizeOf(field_value.type.base_type)) { switch (field_value.type.base_type) { #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ - PTYPE) \ + PTYPE, RTYPE) \ case BASE_TYPE_ ## ENUM: \ builder_.Pad(field->padding); \ if (struct_def.fixed) { \ @@ -817,7 +818,7 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value, FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD); #undef FLATBUFFERS_TD #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \ - PTYPE) \ + PTYPE, RTYPE) \ case BASE_TYPE_ ## ENUM: \ builder_.Pad(field->padding); \ if (IsStruct(field->value.type)) { \ @@ -875,7 +876,7 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue) { // start at the back, since we're building the data backwards. auto &val = field_stack_.back().first; switch (val.type.base_type) { - #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ + #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE) \ case BASE_TYPE_ ## ENUM: \ if (IsStruct(val.type)) SerializeStruct(*val.type.struct_def, val); \ else { \ diff --git a/tests/GoTest.sh b/tests/GoTest.sh index 353930a612..a18d992b5a 100755 --- a/tests/GoTest.sh +++ b/tests/GoTest.sh @@ -29,9 +29,15 @@ mkdir -p ${go_src}/MyGame/Example mkdir -p ${go_src}/github.com/google/flatbuffers/go mkdir -p ${go_src}/flatbuffers_test -cp -u MyGame/Example/*.go ./go_gen/src/MyGame/Example/ -cp -u ../go/* ./go_gen/src/github.com/google/flatbuffers/go -cp -u ./go_test.go ./go_gen/src/flatbuffers_test/ +sync_cmd='cp -u' +unamestr=`uname` +if [[ "$unamestr" == 'Darwin' ]]; then + sync_cmd='rsync -u' +fi + +${sync_cmd} MyGame/Example/*.go ./go_gen/src/MyGame/Example/ +${sync_cmd} ../go/* ./go_gen/src/github.com/google/flatbuffers/go +${sync_cmd} ./go_test.go ./go_gen/src/flatbuffers_test/ # Run tests with necessary flags. # Developers may wish to see more detail by appending the verbosity flag diff --git a/tests/MyGame/Example/Any.rs b/tests/MyGame/Example/Any.rs new file mode 100644 index 0000000000..24cc67be6f --- /dev/null +++ b/tests/MyGame/Example/Any.rs @@ -0,0 +1,61 @@ +//! Automatically generated, do not modify. + +use flatbuffers; +use super::*; + +#[derive(PartialEq, Eq, Clone, Debug, Hash)] +#[repr(u8)] +pub enum Any { + NONE = 0, + Monster = 1, + TestSimpleTableWithEnum = 2, +} + +/// A List of all `Any` enum variants. +pub const ANY_LIST: [Any;3] = [Any::NONE,Any::Monster,Any::TestSimpleTableWithEnum,]; + +impl Any { + /// Returns a `str` representation of a `Any` enum. + pub fn name(&self) -> &'static str { + match *self { + Any::NONE => "NONE", + Any::Monster => "Monster", + Any::TestSimpleTableWithEnum => "TestSimpleTableWithEnum", + } + } +} + +impl From for Any { + fn from(value: u8) -> Any { + match value { + 0 => Any::NONE, + 1 => Any::Monster, + 2 => Any::TestSimpleTableWithEnum, + _ => unreachable!("Unable to create a `Any` from value {} ", value), + } + } +} + +#[derive(Debug)] +pub enum AnyUnion<'a> { + None, + Monster(Monster<'a>), + TestSimpleTableWithEnum(TestSimpleTableWithEnum<'a>), +} + +impl<'a> AnyUnion<'a> { + pub fn from_type(table: &'a flatbuffers::Table, t: Any, offset: usize) -> AnyUnion<'a> { + match t { + Any::NONE => { + AnyUnion::None + } + Any::Monster => { + AnyUnion::Monster(table.get_root(offset as u32).into()) + } + Any::TestSimpleTableWithEnum => { + AnyUnion::TestSimpleTableWithEnum(table.get_root(offset as u32).into()) + } + } + } +} + diff --git a/tests/MyGame/Example/Color.rs b/tests/MyGame/Example/Color.rs new file mode 100644 index 0000000000..d60b7ac5cb --- /dev/null +++ b/tests/MyGame/Example/Color.rs @@ -0,0 +1,35 @@ +//! Automatically generated, do not modify. + +#[derive(PartialEq, Eq, Clone, Debug, Hash)] +#[repr(i8)] +pub enum Color { + Red = 1, + Green = 2, + Blue = 8, +} + +/// A List of all `Color` enum variants. +pub const COLOR_LIST: [Color;3] = [Color::Red,Color::Green,Color::Blue,]; + +impl Color { + /// Returns a `str` representation of a `Color` enum. + pub fn name(&self) -> &'static str { + match *self { + Color::Red => "Red", + Color::Green => "Green", + Color::Blue => "Blue", + } + } +} + +impl From for Color { + fn from(value: i8) -> Color { + match value { + 1 => Color::Red, + 2 => Color::Green, + 8 => Color::Blue, + _ => unreachable!("Unable to create a `Color` from value {} ", value), + } + } +} + diff --git a/tests/MyGame/Example/Monster.rs b/tests/MyGame/Example/Monster.rs new file mode 100644 index 0000000000..f89ff78d26 --- /dev/null +++ b/tests/MyGame/Example/Monster.rs @@ -0,0 +1,534 @@ +//! Automatically generated, do not modify. + +use flatbuffers; +use super::*; + +/// an example documentation comment: monster object +#[derive(Debug)] +pub struct Monster<'a> { + table: flatbuffers::Table<'a>, +} + +enum VT { + POS = 4, + MANA = 6, + HP = 8, + NAME = 10, + INVENTORY = 14, + COLOR = 16, + TEST_TYPE = 18, + TEST = 20, + TEST4 = 22, + TESTARRAYOFSTRING = 24, + TESTARRAYOFTABLES = 26, + ENEMY = 28, + TESTNESTEDFLATBUFFER = 30, + TESTEMPTY = 32, + TESTBOOL = 34, + TESTHASHS32_FNV1 = 36, + TESTHASHU32_FNV1 = 38, + TESTHASHS64_FNV1 = 40, + TESTHASHU64_FNV1 = 42, + TESTHASHS32_FNV1A = 44, + TESTHASHU32_FNV1A = 46, + TESTHASHS64_FNV1A = 48, + TESTHASHU64_FNV1A = 50, + TESTARRAYOFBOOLS = 52, + TESTF = 54, + TESTF2 = 56, + TESTF3 = 58, +} + +impl<'a> Monster<'a> { + pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> Monster { + Monster { + table: flatbuffers::Table::from_offset(buf, offset), + } + } + + pub fn pos(&self) -> Option { + let offset = self.table.field_offset(VT::POS as u16); + if offset != 0 { + return Some(self.table.get_struct::(offset)) + }; + None + } + + pub fn mana(&self) -> i16 { + let offset = self.table.field_offset(VT::MANA as u16); + if offset != 0 { + return self.table.get_i16(offset) + } + 150 + } + + pub fn hp(&self) -> i16 { + let offset = self.table.field_offset(VT::HP as u16); + if offset != 0 { + return self.table.get_i16(offset) + } + 100 + } + + pub fn name(&self) -> &str { + let offset = self.table.field_offset(VT::NAME as u16); + if offset != 0 { + return self.table.get_str(offset) + } + "" + } + + pub fn inventory(&self) -> &[u8] { + let offset = self.table.field_offset(VT::INVENTORY as u16); + if offset != 0 { + return self.table.byte_vector(offset); + } + &[] + } + + pub fn color(&self) -> Color { + let offset = self.table.field_offset(VT::COLOR as u16); + if offset != 0 { + return self.table.get_i8(offset).into() + } + 8.into() + } + + pub fn test_type(&self) -> Any { + let offset = self.table.field_offset(VT::TEST_TYPE as u16); + if offset != 0 { + return self.table.get_u8(offset).into() + } + 0.into() + } + + pub fn test(&self) -> AnyUnion { + let offset = self.table.field_offset(VT::TEST as u16); + if offset != 0 { + let t = self.test_type(); + return AnyUnion::from_type(&self.table, t, offset as usize); + } + AnyUnion::None + } + + pub fn test4(&self) -> flatbuffers::Iterator { + let offset = self.table.field_offset(VT::TEST4 as u16); + if offset != 0 { + return self.table.struct_vector(offset) + } + flatbuffers::empty_iterator(&self.table) + } + + pub fn testarrayofstring(&self) -> flatbuffers::Iterator<&str> { + let offset = self.table.field_offset(VT::TESTARRAYOFSTRING as u16); + if offset != 0 { + return self.table.str_vector(offset); + } + flatbuffers::empty_iterator(&self.table) } + + /// an example documentation comment: this will end up in the generated code + /// multiline too + pub fn testarrayoftables(&self) -> flatbuffers::Iterator { + let offset = self.table.field_offset(VT::TESTARRAYOFTABLES as u16); + if offset != 0 { + return self.table.table_vector(offset) + } + flatbuffers::empty_iterator(&self.table) + } + + pub fn enemy(&self) -> Option { + let offset = self.table.field_offset(VT::ENEMY as u16); + if offset != 0 { + return Some(self.table.get_indirect_root(offset).into()) + }; + None + } + + pub fn testnestedflatbuffer(&self) -> &[u8] { + let offset = self.table.field_offset(VT::TESTNESTEDFLATBUFFER as u16); + if offset != 0 { + return self.table.byte_vector(offset); + } + &[] + } + + pub fn testempty(&self) -> Option { + let offset = self.table.field_offset(VT::TESTEMPTY as u16); + if offset != 0 { + return Some(self.table.get_indirect_root(offset).into()) + }; + None + } + + pub fn testbool(&self) -> bool { + let offset = self.table.field_offset(VT::TESTBOOL as u16); + if offset != 0 { + return self.table.get_bool(offset) + } + false + } + + pub fn testhashs32_fnv1(&self) -> i32 { + let offset = self.table.field_offset(VT::TESTHASHS32_FNV1 as u16); + if offset != 0 { + return self.table.get_i32(offset) + } + 0 + } + + pub fn testhashu32_fnv1(&self) -> u32 { + let offset = self.table.field_offset(VT::TESTHASHU32_FNV1 as u16); + if offset != 0 { + return self.table.get_u32(offset) + } + 0 + } + + pub fn testhashs64_fnv1(&self) -> i64 { + let offset = self.table.field_offset(VT::TESTHASHS64_FNV1 as u16); + if offset != 0 { + return self.table.get_i64(offset) + } + 0 + } + + pub fn testhashu64_fnv1(&self) -> u64 { + let offset = self.table.field_offset(VT::TESTHASHU64_FNV1 as u16); + if offset != 0 { + return self.table.get_u64(offset) + } + 0 + } + + pub fn testhashs32_fnv1a(&self) -> i32 { + let offset = self.table.field_offset(VT::TESTHASHS32_FNV1A as u16); + if offset != 0 { + return self.table.get_i32(offset) + } + 0 + } + + pub fn testhashu32_fnv1a(&self) -> u32 { + let offset = self.table.field_offset(VT::TESTHASHU32_FNV1A as u16); + if offset != 0 { + return self.table.get_u32(offset) + } + 0 + } + + pub fn testhashs64_fnv1a(&self) -> i64 { + let offset = self.table.field_offset(VT::TESTHASHS64_FNV1A as u16); + if offset != 0 { + return self.table.get_i64(offset) + } + 0 + } + + pub fn testhashu64_fnv1a(&self) -> u64 { + let offset = self.table.field_offset(VT::TESTHASHU64_FNV1A as u16); + if offset != 0 { + return self.table.get_u64(offset) + } + 0 + } + + pub fn testarrayofbools(&self) -> &[bool] { + let offset = self.table.field_offset(VT::TESTARRAYOFBOOLS as u16); + if offset != 0 { + return self.table.bool_vector(offset); + } + &[] + } + + pub fn testf(&self) -> f32 { + let offset = self.table.field_offset(VT::TESTF as u16); + if offset != 0 { + return self.table.get_f32(offset) + } + 3.14159 + } + + pub fn testf2(&self) -> f32 { + let offset = self.table.field_offset(VT::TESTF2 as u16); + if offset != 0 { + return self.table.get_f32(offset) + } + 3.0 + } + + pub fn testf3(&self) -> f32 { + let offset = self.table.field_offset(VT::TESTF3 as u16); + if offset != 0 { + return self.table.get_f32(offset) + } + 0.0 + } + +} + +impl<'a> From> for Monster<'a> { + fn from(table: flatbuffers::Table) -> Monster { + Monster{ + table: table, + } + } +} + +/// Builder Object for `Monster` tables. +pub struct Builder { + inner: flatbuffers::Builder, +} + +impl Builder { + /// Create a new builder. + pub fn with_capacity(size: usize) -> Self { + Builder { + inner: flatbuffers::Builder::with_capacity(size), + } + } + + /// Initialize a new `Builder` for a `Monster` table. + pub fn start(&mut self) { + self.inner.start_object(28); + } + + /// Finalize the current object and return the offset. + pub fn end(&mut self) -> flatbuffers::UOffsetT { + return self.inner.end_object() + } + + /// Set the value for field `pos`. + pub fn add_pos(&mut self, pos: flatbuffers::UOffsetT) { + self.inner.add_slot_struct(0, pos, 0) + } + + /// Set the value for field `mana`. + pub fn add_mana(&mut self, mana: i16) { + self.inner.add_slot_i16(1, mana, 150) + } + + /// Set the value for field `hp`. + pub fn add_hp(&mut self, hp: i16) { + self.inner.add_slot_i16(2, hp, 100) + } + + /// Set the value for field `name`. + pub fn add_name(&mut self, name: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(3, name, 0) + } + + /// Set the value for field `inventory`. + pub fn add_inventory(&mut self, inventory: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(5, inventory, 0) + } + + /// Initializes bookkeeping for writing a new `inventory` vector. + pub fn start_inventory_vector(&mut self, numElems: usize) { + self.inner.start_vector(1, numElems, 1) + } + + /// Set the value for field `color`. + pub fn add_color(&mut self, color: i8) { + self.inner.add_slot_i8(6, color, 8) + } + + /// Set the value for field `test_type`. + pub fn add_test_type(&mut self, test_type: u8) { + self.inner.add_slot_u8(7, test_type, 0) + } + + /// Set the value for field `test`. + pub fn add_test(&mut self, test: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(8, test, 0) + } + + /// Set the value for field `test4`. + pub fn add_test4(&mut self, test4: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(9, test4, 0) + } + + /// Initializes bookkeeping for writing a new `test4` vector. + pub fn start_test4_vector(&mut self, numElems: usize) { + self.inner.start_vector(4, numElems, 2) + } + + /// Set the value for field `testarrayofstring`. + pub fn add_testarrayofstring(&mut self, testarrayofstring: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(10, testarrayofstring, 0) + } + + /// Initializes bookkeeping for writing a new `testarrayofstring` vector. + pub fn start_testarrayofstring_vector(&mut self, numElems: usize) { + self.inner.start_vector(4, numElems, 4) + } + + /// Set the value for field `testarrayoftables`. + pub fn add_testarrayoftables(&mut self, testarrayoftables: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(11, testarrayoftables, 0) + } + + /// Initializes bookkeeping for writing a new `testarrayoftables` vector. + pub fn start_testarrayoftables_vector(&mut self, numElems: usize) { + self.inner.start_vector(4, numElems, 4) + } + + /// Set the value for field `enemy`. + pub fn add_enemy(&mut self, enemy: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(12, enemy, 0) + } + + /// Set the value for field `testnestedflatbuffer`. + pub fn add_testnestedflatbuffer(&mut self, testnestedflatbuffer: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(13, testnestedflatbuffer, 0) + } + + /// Initializes bookkeeping for writing a new `testnestedflatbuffer` vector. + pub fn start_testnestedflatbuffer_vector(&mut self, numElems: usize) { + self.inner.start_vector(1, numElems, 1) + } + + /// Set the value for field `testempty`. + pub fn add_testempty(&mut self, testempty: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(14, testempty, 0) + } + + /// Set the value for field `testbool`. + pub fn add_testbool(&mut self, testbool: bool) { + self.inner.add_slot_bool(15, testbool, false) + } + + /// Set the value for field `testhashs32_fnv1`. + pub fn add_testhashs32_fnv1(&mut self, testhashs32_fnv1: i32) { + self.inner.add_slot_i32(16, testhashs32_fnv1, 0) + } + + /// Set the value for field `testhashu32_fnv1`. + pub fn add_testhashu32_fnv1(&mut self, testhashu32_fnv1: u32) { + self.inner.add_slot_u32(17, testhashu32_fnv1, 0) + } + + /// Set the value for field `testhashs64_fnv1`. + pub fn add_testhashs64_fnv1(&mut self, testhashs64_fnv1: i64) { + self.inner.add_slot_i64(18, testhashs64_fnv1, 0) + } + + /// Set the value for field `testhashu64_fnv1`. + pub fn add_testhashu64_fnv1(&mut self, testhashu64_fnv1: u64) { + self.inner.add_slot_u64(19, testhashu64_fnv1, 0) + } + + /// Set the value for field `testhashs32_fnv1a`. + pub fn add_testhashs32_fnv1a(&mut self, testhashs32_fnv1a: i32) { + self.inner.add_slot_i32(20, testhashs32_fnv1a, 0) + } + + /// Set the value for field `testhashu32_fnv1a`. + pub fn add_testhashu32_fnv1a(&mut self, testhashu32_fnv1a: u32) { + self.inner.add_slot_u32(21, testhashu32_fnv1a, 0) + } + + /// Set the value for field `testhashs64_fnv1a`. + pub fn add_testhashs64_fnv1a(&mut self, testhashs64_fnv1a: i64) { + self.inner.add_slot_i64(22, testhashs64_fnv1a, 0) + } + + /// Set the value for field `testhashu64_fnv1a`. + pub fn add_testhashu64_fnv1a(&mut self, testhashu64_fnv1a: u64) { + self.inner.add_slot_u64(23, testhashu64_fnv1a, 0) + } + + /// Set the value for field `testarrayofbools`. + pub fn add_testarrayofbools(&mut self, testarrayofbools: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(24, testarrayofbools, 0) + } + + /// Initializes bookkeeping for writing a new `testarrayofbools` vector. + pub fn start_testarrayofbools_vector(&mut self, numElems: usize) { + self.inner.start_vector(1, numElems, 1) + } + + /// Set the value for field `testf`. + pub fn add_testf(&mut self, testf: f32) { + self.inner.add_slot_f32(25, testf, 3.14159) + } + + /// Set the value for field `testf2`. + pub fn add_testf2(&mut self, testf2: f32) { + self.inner.add_slot_f32(26, testf2, 3.0) + } + + /// Set the value for field `testf3`. + pub fn add_testf3(&mut self, testf3: f32) { + self.inner.add_slot_f32(27, testf3, 0.0) + } + + pub fn build_vec3(&mut self , x: f32, y: f32, z: f32, test1: f64, test2: i8, test3_a: i16, test3_b: i8) -> flatbuffers::UOffsetT { + vec3::build_vec3(&mut self.inner, x, y, z, test1, test2, test3_a, test3_b) + } + + pub fn build_test(&mut self , a: i16, b: i8) -> flatbuffers::UOffsetT { + test::build_test(&mut self.inner, a, b) + } + + /// Finish the buffer. + pub fn finish(&mut self, r: flatbuffers::UOffsetT) { + return self.inner.finish(r) + } + + pub fn create_string(&mut self, v: &str) -> flatbuffers::UOffsetT { self.inner.create_string(v) } + pub fn get_bytes(&self) -> &[u8] { self.inner.get_bytes() } + pub fn len(&self) -> usize { self.inner.len() } + pub fn offset(&self) -> usize { self.inner.offset() } + pub fn reset(&mut self) { self.inner.reset() } + pub fn prep(&mut self, s:usize, a: usize) { self.inner.prep(s,a) } + pub fn pad(&mut self, n:usize) { self.inner.pad(n) } + pub fn end_vector(&mut self) -> flatbuffers::UOffsetT { self.inner.end_vector() } + pub fn add_bool(&mut self, v:bool) { self.inner.add_bool(v) } + pub fn add_u8(&mut self, v:u8) { self.inner.add_u8(v) } + pub fn add_i8(&mut self, v:i8) { self.inner.add_i8(v) } + pub fn add_u16(&mut self, v:u16) { self.inner.add_u16(v) } + pub fn add_i16(&mut self, v:i16) { self.inner.add_i16(v) } + pub fn add_u32(&mut self, v:u32) { self.inner.add_u32(v) } + pub fn add_i32(&mut self, v:i32) { self.inner.add_i32(v) } + pub fn add_u64(&mut self, v:u64) { self.inner.add_u64(v) } + pub fn add_i64(&mut self, v:i64) { self.inner.add_i64(v) } + pub fn add_f32(&mut self, v:f32) { self.inner.add_f32(v) } + pub fn add_f64(&mut self, v:f64) { self.inner.add_f64(v) } + pub fn add_uoffset(&mut self, v: flatbuffers::UOffsetT) { self.inner.add_uoffset(v) } + pub fn add_slot_bool(&mut self, o: usize, v: bool, d: bool) { self.inner.add_slot_bool(o,v,d) } + pub fn add_slot_u8(&mut self, o: usize, v: u8, d: u8) { self.inner.add_slot_u8(o,v,d) } + pub fn add_slot_i8(&mut self, o: usize, v: i8, d: i8) { self.inner.add_slot_i8(o,v,d) } + pub fn add_slot_u16(&mut self, o: usize, v: u16, d: u16) { self.inner.add_slot_u16(o,v,d) } + pub fn add_slot_i16(&mut self, o: usize, v: i16, d: i16) { self.inner.add_slot_i16(o,v,d) } + pub fn add_slot_i32(&mut self, o: usize, v: i32, d: i32) { self.inner.add_slot_i32(o,v,d) } + pub fn add_slot_u32(&mut self, o: usize, v: u32, d: u32) { self.inner.add_slot_u32(o,v,d) } + pub fn add_slot_u64(&mut self, o: usize, v: u64, d: u64) { self.inner.add_slot_u64(o,v,d) } + pub fn add_slot_i64(&mut self, o: usize, v: i64, d: i64) { self.inner.add_slot_i64(o,v,d) } + pub fn add_slot_f32(&mut self, o: usize, v: f32, d: f32) { self.inner.add_slot_f32(o,v,d) } + pub fn add_slot_f64(&mut self, o: usize, v: f64, d: f64) { self.inner.add_slot_f64(o,v,d) } + pub fn add_slot_uoffset(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_uoffset(o,v,d) } + pub fn add_slot_struct(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_struct(o,v,d) } +} + +impl Default for Builder { + fn default() -> Builder { + Builder::with_capacity(1024) + } +} + +impl From for Builder { + fn from(b: flatbuffers::Builder) -> Builder { + Builder { + inner: b, + } + } +} + +impl Into for Builder { + fn into(self) -> flatbuffers::Builder { + self.inner + } +} + +impl flatbuffers::ObjectBuilder for Builder {} + diff --git a/tests/MyGame/Example/Stat.rs b/tests/MyGame/Example/Stat.rs new file mode 100644 index 0000000000..4bccf31436 --- /dev/null +++ b/tests/MyGame/Example/Stat.rs @@ -0,0 +1,157 @@ +//! Automatically generated, do not modify. + +use flatbuffers; +use super::*; + +#[derive(Debug)] +pub struct Stat<'a> { + table: flatbuffers::Table<'a>, +} + +enum VT { + ID = 4, + VAL = 6, + COUNT = 8, +} + +impl<'a> Stat<'a> { + pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> Stat { + Stat { + table: flatbuffers::Table::from_offset(buf, offset), + } + } + + pub fn id(&self) -> &str { + let offset = self.table.field_offset(VT::ID as u16); + if offset != 0 { + return self.table.get_str(offset) + } + "" + } + + pub fn val(&self) -> i64 { + let offset = self.table.field_offset(VT::VAL as u16); + if offset != 0 { + return self.table.get_i64(offset) + } + 0 + } + + pub fn count(&self) -> u16 { + let offset = self.table.field_offset(VT::COUNT as u16); + if offset != 0 { + return self.table.get_u16(offset) + } + 0 + } + +} + +impl<'a> From> for Stat<'a> { + fn from(table: flatbuffers::Table) -> Stat { + Stat{ + table: table, + } + } +} + +/// Builder Object for `Stat` tables. +pub struct Builder { + inner: flatbuffers::Builder, +} + +impl Builder { + /// Create a new builder. + pub fn with_capacity(size: usize) -> Self { + Builder { + inner: flatbuffers::Builder::with_capacity(size), + } + } + + /// Initialize a new `Builder` for a `Stat` table. + pub fn start(&mut self) { + self.inner.start_object(3); + } + + /// Finalize the current object and return the offset. + pub fn end(&mut self) -> flatbuffers::UOffsetT { + return self.inner.end_object() + } + + /// Set the value for field `id`. + pub fn add_id(&mut self, id: flatbuffers::UOffsetT) { + self.inner.add_slot_uoffset(0, id, 0) + } + + /// Set the value for field `val`. + pub fn add_val(&mut self, val: i64) { + self.inner.add_slot_i64(1, val, 0) + } + + /// Set the value for field `count`. + pub fn add_count(&mut self, count: u16) { + self.inner.add_slot_u16(2, count, 0) + } + + /// Finish the buffer. + pub fn finish(&mut self, r: flatbuffers::UOffsetT) { + return self.inner.finish(r) + } + + pub fn create_string(&mut self, v: &str) -> flatbuffers::UOffsetT { self.inner.create_string(v) } + pub fn get_bytes(&self) -> &[u8] { self.inner.get_bytes() } + pub fn len(&self) -> usize { self.inner.len() } + pub fn offset(&self) -> usize { self.inner.offset() } + pub fn reset(&mut self) { self.inner.reset() } + pub fn prep(&mut self, s:usize, a: usize) { self.inner.prep(s,a) } + pub fn pad(&mut self, n:usize) { self.inner.pad(n) } + pub fn end_vector(&mut self) -> flatbuffers::UOffsetT { self.inner.end_vector() } + pub fn add_bool(&mut self, v:bool) { self.inner.add_bool(v) } + pub fn add_u8(&mut self, v:u8) { self.inner.add_u8(v) } + pub fn add_i8(&mut self, v:i8) { self.inner.add_i8(v) } + pub fn add_u16(&mut self, v:u16) { self.inner.add_u16(v) } + pub fn add_i16(&mut self, v:i16) { self.inner.add_i16(v) } + pub fn add_u32(&mut self, v:u32) { self.inner.add_u32(v) } + pub fn add_i32(&mut self, v:i32) { self.inner.add_i32(v) } + pub fn add_u64(&mut self, v:u64) { self.inner.add_u64(v) } + pub fn add_i64(&mut self, v:i64) { self.inner.add_i64(v) } + pub fn add_f32(&mut self, v:f32) { self.inner.add_f32(v) } + pub fn add_f64(&mut self, v:f64) { self.inner.add_f64(v) } + pub fn add_uoffset(&mut self, v: flatbuffers::UOffsetT) { self.inner.add_uoffset(v) } + pub fn add_slot_bool(&mut self, o: usize, v: bool, d: bool) { self.inner.add_slot_bool(o,v,d) } + pub fn add_slot_u8(&mut self, o: usize, v: u8, d: u8) { self.inner.add_slot_u8(o,v,d) } + pub fn add_slot_i8(&mut self, o: usize, v: i8, d: i8) { self.inner.add_slot_i8(o,v,d) } + pub fn add_slot_u16(&mut self, o: usize, v: u16, d: u16) { self.inner.add_slot_u16(o,v,d) } + pub fn add_slot_i16(&mut self, o: usize, v: i16, d: i16) { self.inner.add_slot_i16(o,v,d) } + pub fn add_slot_i32(&mut self, o: usize, v: i32, d: i32) { self.inner.add_slot_i32(o,v,d) } + pub fn add_slot_u32(&mut self, o: usize, v: u32, d: u32) { self.inner.add_slot_u32(o,v,d) } + pub fn add_slot_u64(&mut self, o: usize, v: u64, d: u64) { self.inner.add_slot_u64(o,v,d) } + pub fn add_slot_i64(&mut self, o: usize, v: i64, d: i64) { self.inner.add_slot_i64(o,v,d) } + pub fn add_slot_f32(&mut self, o: usize, v: f32, d: f32) { self.inner.add_slot_f32(o,v,d) } + pub fn add_slot_f64(&mut self, o: usize, v: f64, d: f64) { self.inner.add_slot_f64(o,v,d) } + pub fn add_slot_uoffset(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_uoffset(o,v,d) } + pub fn add_slot_struct(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_struct(o,v,d) } +} + +impl Default for Builder { + fn default() -> Builder { + Builder::with_capacity(1024) + } +} + +impl From for Builder { + fn from(b: flatbuffers::Builder) -> Builder { + Builder { + inner: b, + } + } +} + +impl Into for Builder { + fn into(self) -> flatbuffers::Builder { + self.inner + } +} + +impl flatbuffers::ObjectBuilder for Builder {} + diff --git a/tests/MyGame/Example/Test.rs b/tests/MyGame/Example/Test.rs new file mode 100644 index 0000000000..55f3baf290 --- /dev/null +++ b/tests/MyGame/Example/Test.rs @@ -0,0 +1,49 @@ +//! Automatically generated, do not modify. + +use flatbuffers; +use super::*; + +#[derive(Debug)] +pub struct Test<'a> { + table: flatbuffers::Table<'a>, +} + +enum VT { + A = 0, + B = 2,// Padding1 +} + +impl<'a> Test<'a> { + pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> Test { + Test { + table: flatbuffers::Table::with_pos(buf, offset), + } + } + + pub fn a(&self) -> i16 { + let offset = VT::A as u32; + return self.table.get_i16(offset) + } + + pub fn b(&self) -> i8 { + let offset = VT::B as u32; + return self.table.get_i8(offset) + } + +} + +impl<'a> From> for Test<'a> { + fn from(table: flatbuffers::Table) -> Test { + Test{ + table: table, + } + } +} + +pub fn build_test(builder: &mut flatbuffers::Builder, a: i16, b: i8) -> flatbuffers::UOffsetT { + builder.prep(2, 4); + builder.pad(1); + builder.add_i8(b); + builder.add_i16(a); + builder.offset() as flatbuffers::UOffsetT +} diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.rs b/tests/MyGame/Example/TestSimpleTableWithEnum.rs new file mode 100644 index 0000000000..b6ccba8914 --- /dev/null +++ b/tests/MyGame/Example/TestSimpleTableWithEnum.rs @@ -0,0 +1,129 @@ +//! Automatically generated, do not modify. + +use flatbuffers; +use super::*; + +#[derive(Debug)] +pub struct TestSimpleTableWithEnum<'a> { + table: flatbuffers::Table<'a>, +} + +enum VT { + COLOR = 4, +} + +impl<'a> TestSimpleTableWithEnum<'a> { + pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> TestSimpleTableWithEnum { + TestSimpleTableWithEnum { + table: flatbuffers::Table::from_offset(buf, offset), + } + } + + pub fn color(&self) -> Color { + let offset = self.table.field_offset(VT::COLOR as u16); + if offset != 0 { + return self.table.get_i8(offset).into() + } + 2.into() + } + +} + +impl<'a> From> for TestSimpleTableWithEnum<'a> { + fn from(table: flatbuffers::Table) -> TestSimpleTableWithEnum { + TestSimpleTableWithEnum{ + table: table, + } + } +} + +/// Builder Object for `TestSimpleTableWithEnum` tables. +pub struct Builder { + inner: flatbuffers::Builder, +} + +impl Builder { + /// Create a new builder. + pub fn with_capacity(size: usize) -> Self { + Builder { + inner: flatbuffers::Builder::with_capacity(size), + } + } + + /// Initialize a new `Builder` for a `TestSimpleTableWithEnum` table. + pub fn start(&mut self) { + self.inner.start_object(1); + } + + /// Finalize the current object and return the offset. + pub fn end(&mut self) -> flatbuffers::UOffsetT { + return self.inner.end_object() + } + + /// Set the value for field `color`. + pub fn add_color(&mut self, color: i8) { + self.inner.add_slot_i8(0, color, 2) + } + + /// Finish the buffer. + pub fn finish(&mut self, r: flatbuffers::UOffsetT) { + return self.inner.finish(r) + } + + pub fn create_string(&mut self, v: &str) -> flatbuffers::UOffsetT { self.inner.create_string(v) } + pub fn get_bytes(&self) -> &[u8] { self.inner.get_bytes() } + pub fn len(&self) -> usize { self.inner.len() } + pub fn offset(&self) -> usize { self.inner.offset() } + pub fn reset(&mut self) { self.inner.reset() } + pub fn prep(&mut self, s:usize, a: usize) { self.inner.prep(s,a) } + pub fn pad(&mut self, n:usize) { self.inner.pad(n) } + pub fn end_vector(&mut self) -> flatbuffers::UOffsetT { self.inner.end_vector() } + pub fn add_bool(&mut self, v:bool) { self.inner.add_bool(v) } + pub fn add_u8(&mut self, v:u8) { self.inner.add_u8(v) } + pub fn add_i8(&mut self, v:i8) { self.inner.add_i8(v) } + pub fn add_u16(&mut self, v:u16) { self.inner.add_u16(v) } + pub fn add_i16(&mut self, v:i16) { self.inner.add_i16(v) } + pub fn add_u32(&mut self, v:u32) { self.inner.add_u32(v) } + pub fn add_i32(&mut self, v:i32) { self.inner.add_i32(v) } + pub fn add_u64(&mut self, v:u64) { self.inner.add_u64(v) } + pub fn add_i64(&mut self, v:i64) { self.inner.add_i64(v) } + pub fn add_f32(&mut self, v:f32) { self.inner.add_f32(v) } + pub fn add_f64(&mut self, v:f64) { self.inner.add_f64(v) } + pub fn add_uoffset(&mut self, v: flatbuffers::UOffsetT) { self.inner.add_uoffset(v) } + pub fn add_slot_bool(&mut self, o: usize, v: bool, d: bool) { self.inner.add_slot_bool(o,v,d) } + pub fn add_slot_u8(&mut self, o: usize, v: u8, d: u8) { self.inner.add_slot_u8(o,v,d) } + pub fn add_slot_i8(&mut self, o: usize, v: i8, d: i8) { self.inner.add_slot_i8(o,v,d) } + pub fn add_slot_u16(&mut self, o: usize, v: u16, d: u16) { self.inner.add_slot_u16(o,v,d) } + pub fn add_slot_i16(&mut self, o: usize, v: i16, d: i16) { self.inner.add_slot_i16(o,v,d) } + pub fn add_slot_i32(&mut self, o: usize, v: i32, d: i32) { self.inner.add_slot_i32(o,v,d) } + pub fn add_slot_u32(&mut self, o: usize, v: u32, d: u32) { self.inner.add_slot_u32(o,v,d) } + pub fn add_slot_u64(&mut self, o: usize, v: u64, d: u64) { self.inner.add_slot_u64(o,v,d) } + pub fn add_slot_i64(&mut self, o: usize, v: i64, d: i64) { self.inner.add_slot_i64(o,v,d) } + pub fn add_slot_f32(&mut self, o: usize, v: f32, d: f32) { self.inner.add_slot_f32(o,v,d) } + pub fn add_slot_f64(&mut self, o: usize, v: f64, d: f64) { self.inner.add_slot_f64(o,v,d) } + pub fn add_slot_uoffset(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_uoffset(o,v,d) } + pub fn add_slot_struct(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_struct(o,v,d) } +} + +impl Default for Builder { + fn default() -> Builder { + Builder::with_capacity(1024) + } +} + +impl From for Builder { + fn from(b: flatbuffers::Builder) -> Builder { + Builder { + inner: b, + } + } +} + +impl Into for Builder { + fn into(self) -> flatbuffers::Builder { + self.inner + } +} + +impl flatbuffers::ObjectBuilder for Builder {} + diff --git a/tests/MyGame/Example/Vec3.rs b/tests/MyGame/Example/Vec3.rs new file mode 100644 index 0000000000..f1714a9fdc --- /dev/null +++ b/tests/MyGame/Example/Vec3.rs @@ -0,0 +1,82 @@ +//! Automatically generated, do not modify. + +use flatbuffers; +use super::*; + +#[derive(Debug)] +pub struct Vec3<'a> { + table: flatbuffers::Table<'a>, +} + +enum VT { + X = 0, + Y = 4, + Z = 8,// Padding4 + TEST1 = 16, + TEST2 = 24,// Padding1 + TEST3 = 26,// Padding2 +} + +impl<'a> Vec3<'a> { + pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> Vec3 { + Vec3 { + table: flatbuffers::Table::with_pos(buf, offset), + } + } + + pub fn x(&self) -> f32 { + let offset = VT::X as u32; + return self.table.get_f32(offset) + } + + pub fn y(&self) -> f32 { + let offset = VT::Y as u32; + return self.table.get_f32(offset) + } + + pub fn z(&self) -> f32 { + let offset = VT::Z as u32; + return self.table.get_f32(offset) + } + + pub fn test1(&self) -> f64 { + let offset = VT::TEST1 as u32; + return self.table.get_f64(offset) + } + + pub fn test2(&self) -> Color { + let offset = VT::TEST2 as u32; + return self.table.get_i8(offset).into() + } + + pub fn test3(&self) -> Test { + let offset = VT::TEST3 as u32; + return self.table.get_struct::(offset) + } + +} + +impl<'a> From> for Vec3<'a> { + fn from(table: flatbuffers::Table) -> Vec3 { + Vec3{ + table: table, + } + } +} + +pub fn build_vec3(builder: &mut flatbuffers::Builder, x: f32, y: f32, z: f32, test1: f64, test2: i8, test3_a: i16, test3_b: i8) -> flatbuffers::UOffsetT { + builder.prep(16, 32); + builder.pad(2); + builder.prep(2, 4); + builder.pad(1); + builder.add_i8(test3_b); + builder.add_i16(test3_a); + builder.pad(1); + builder.add_i8(test2); + builder.add_f64(test1); + builder.pad(4); + builder.add_f32(z); + builder.add_f32(y); + builder.add_f32(x); + builder.offset() as flatbuffers::UOffsetT +} diff --git a/tests/MyGame/Example/mod.rs b/tests/MyGame/Example/mod.rs new file mode 100644 index 0000000000..657a1baab1 --- /dev/null +++ b/tests/MyGame/Example/mod.rs @@ -0,0 +1,18 @@ +//! Automatically generated, do not modify +//! +//! Flatbuffer definitions for the Example namespace. +mod color; +mod any; +pub mod test; +pub mod testsimpletablewithenum; +pub mod vec3; +pub mod stat; +pub mod monster; + +pub use self::color::*; +pub use self::any::*; +pub use self::test::{Test, build_test}; +pub use self::testsimpletablewithenum::TestSimpleTableWithEnum; +pub use self::vec3::{Vec3, build_vec3}; +pub use self::stat::Stat; +pub use self::monster::Monster; diff --git a/tests/MyGame/mod.rs b/tests/MyGame/mod.rs new file mode 100644 index 0000000000..b305cc9d96 --- /dev/null +++ b/tests/MyGame/mod.rs @@ -0,0 +1,5 @@ +//! Automatically generated, do not modify +//! +//! Flatbuffer definitions for the MyGame namespace. + +pub mod example; diff --git a/tests/RustTest.sh b/tests/RustTest.sh new file mode 100755 index 0000000000..d2f57ebf2f --- /dev/null +++ b/tests/RustTest.sh @@ -0,0 +1,41 @@ +# 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. + +pushd "$(dirname $0)" >/dev/null +test_dir="$(pwd)" +rust_path=${test_dir}/rust_gen +rust_src=${rust_path}/src + +# Emit Rust code for the example schema in the test dir: +../flatc -r monster_test.fbs + +mkdir -p ${rust_src}/bin/test/MyGame/Example + +sync_cmd='cp -u' +unamestr=`uname` +if [[ "$unamestr" == 'Darwin' ]]; then + sync_cmd='rsync -u' +fi + +${sync_cmd} MyGame/Example/*.rs ${rust_src}/bin/test/MyGame/Example/ +${sync_cmd} MyGame/*.rs ${rust_src}/bin/test/MyGame/ +${sync_cmd} ../rust/* ${rust_path} +${sync_cmd} ../rust/src/* ${rust_src} +${sync_cmd} ../rust/src/bin/* ${rust_src}/bin/ +cp *.mon ${rust_path}/ + +#run tests +( cd $rust_path ; cargo test --features test_idl_gen -- --nocapture) +#run bench +# cant bench on stable rust as of 1.9.0 + +echo "Ok: Rust tests passed." From e312e78fa21830de2b5de6f58deac6469af81f01 Mon Sep 17 00:00:00 2001 From: Joseph Dunne Date: Thu, 2 Jun 2016 02:54:21 +0100 Subject: [PATCH 2/7] V0.1.1 - make builder bytes public --- rust/Cargo.lock | 2 +- rust/Cargo.toml | 2 +- rust/src/builder.rs | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index bc75cc791c..faa7d8438a 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "flatbuffers" -version = "0.1.0" +version = "0.1.1" dependencies = [ "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index e479e44da2..a724004acd 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "flatbuffers" -version = "0.1.0" +version = "0.1.1" authors = ["Joseph Dunne "] description = "Memory Efficient Serialization Library. Flatbuffers runtime for Rust." keywords = ["flatbuffers", "serialization", "deserialization"] diff --git a/rust/src/builder.rs b/rust/src/builder.rs index 0f497a8d39..740753bcee 100644 --- a/rust/src/builder.rs +++ b/rust/src/builder.rs @@ -14,7 +14,7 @@ use types::*; #[derive(Debug)] pub struct Builder { // Where the FlatBuffer is constructed. - bytes: Vec, + pub bytes: Vec, // Minimum alignment encountered so far. min_align: usize, // Starting offset of the current struct/table. @@ -123,7 +123,6 @@ impl Builder { /// Consume the builder and return the finished flatbuffer. pub fn get_bytes(&self) -> &[u8] { - assert!(self.finished, "Flatbuffer is not been finished"); &self.bytes } From 4a2ea629596d2af113a0170ea20cbaa5ee46f517 Mon Sep 17 00:00:00 2001 From: Joseph Dunne Date: Fri, 3 Jun 2016 07:59:14 +0100 Subject: [PATCH 3/7] Moved to a macro based code generation system --- rust/Cargo.lock | 2 +- rust/Cargo.toml | 2 +- rust/src/bin/test.rs | 45 +- rust/src/builder.rs | 417 +++++-- rust/src/iter.rs | 199 ++-- rust/src/lib.rs | 5 +- rust/src/macros.rs | 206 ++++ rust/src/table.rs | 311 +++-- rust/src/types.rs | 1 + src/idl_gen_rust.cpp | 1058 ++++------------- tests/MyGame/Example/Any.rs | 58 +- tests/MyGame/Example/Color.rs | 37 +- tests/MyGame/Example/Monster.rs | 617 +++------- tests/MyGame/Example/Stat.rs | 161 +-- tests/MyGame/Example/Test.rs | 50 +- .../MyGame/Example/TestSimpleTableWithEnum.rs | 125 +- tests/MyGame/Example/Vec3.rs | 98 +- tests/MyGame/Example/mod.rs | 10 +- 18 files changed, 1400 insertions(+), 2002 deletions(-) create mode 100644 rust/src/macros.rs diff --git a/rust/Cargo.lock b/rust/Cargo.lock index faa7d8438a..b151104a40 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "flatbuffers" -version = "0.1.1" +version = "0.2.0" dependencies = [ "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index a724004acd..01f8698076 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "flatbuffers" -version = "0.1.1" +version = "0.2.0" authors = ["Joseph Dunne "] description = "Memory Efficient Serialization Library. Flatbuffers runtime for Rust." keywords = ["flatbuffers", "serialization", "deserialization"] diff --git a/rust/src/bin/test.rs b/rust/src/bin/test.rs index 2668e99500..b6936fc132 100644 --- a/rust/src/bin/test.rs +++ b/rust/src/bin/test.rs @@ -1,3 +1,5 @@ + +#[macro_use] extern crate flatbuffers; fn main() { @@ -7,11 +9,10 @@ fn main() { #[cfg(test)] #[cfg(feature = "test_idl_gen")] mod test { + #[allow(non_snake_case,dead_code,unused_imports, non_camel_case_types)] mod MyGame; - extern crate flatbuffers; - use flatbuffers::*; use self::MyGame::*; @@ -78,11 +79,13 @@ mod test { b.add_slot_uoffset(9, test4 as u32, 0); let mon = b.end_object(); - b.finish(mon); + b.finish_table(mon); } fn build_monster() { - let mut b = example::monster::Builder::with_capacity(0); + use self::MyGame::example::monster::MonsterBuilder; + + let mut b = Builder::with_capacity(0); let name = b.create_string("MyMonster"); let test1 = b.create_string("test1"); let test2 = b.create_string("test2"); @@ -95,10 +98,12 @@ mod test { b.add_u8(0); let inv = b.end_vector(); - b.start(); + b.start_monster(); b.add_name(fred); - let mon2 = b.end(); + let mon2 = b.end_object(); + + use self::MyGame::example::test::TestBuilder; b.start_test4_vector(2); b.build_test(10, 20); b.build_test(30, 40); @@ -108,18 +113,19 @@ mod test { b.add_uoffset(test2); b.add_uoffset(test1); let test_array = b.end_vector(); - - let mut stat = example::stat::Builder::from_other(b); + use self::MyGame::example::stat::StatBuilder; + let mut stat = b; let stat_id = stat.create_string("way out..statistical"); - stat.start(); + stat.start_stat(); stat.add_id(stat_id); stat.add_val(20); stat.add_count(0); - let stat_offset = stat.end(); + let stat_offset = stat.end_object(); + b = stat; - b = example::monster::Builder::from_other(stat); - b.start(); + use self::MyGame::example::vec3::Vec3Builder; + b.start_monster(); let pos = b.build_vec3(1.0, 2.0, 3.0, 3.0, 2, 5, 6); b.add_pos(pos); @@ -131,9 +137,9 @@ mod test { b.add_test4(test4); b.add_testempty(stat_offset); b.add_testarrayofstring(test_array); - let mon = b.end(); + let mon = b.end_object(); - b.finish(mon); + b.finish_table(mon); } #[test] @@ -156,7 +162,8 @@ mod test { let mut reader = BufReader::new(f1); let mut buf: Vec = Vec::new(); reader.read_to_end(&mut buf).unwrap(); - let monster = example::monster::Monster::new(&buf, 0); + let table = Table::from_offset(&buf, 0); + let monster = example::monster::Monster::new(table); let got = monster.hp(); assert!(got == 80, "bad {}: want {:?} got {:?}", "HP", 80, got); let got = monster.mana(); @@ -176,7 +183,7 @@ mod test { let got = vec3.test1(); assert!(got == 3.0, "bad {}: want {:?} got {:?}", "Vec3.test1", "3.0", got); let got = vec3.test2(); - assert!(got == example::Color::Green, "bad {}: want {:?} got {:?}", + assert!(got == Some(example::Color::Green), "bad {}: want {:?} got {:?}", "Vec3.test2", "Color::Green", got); // Verify properties of test3 let test3 = vec3.test3(); @@ -186,10 +193,10 @@ mod test { assert!(got == 6, "bad {}: want {:?} got {:?}", "Test.b", "6", got); // Verify test type let got = monster.test_type(); - assert!(got == example::Any::Monster, "bad {}: want {:?} got {:?}", "TestType", "Monster", got); + assert!(got == Some(example::AnyType::Monster), "bad {}: want {:?} got {:?}", "TestType", "Monster", got); // initialize a Table from a union field let got = monster.test(); - if let example::AnyUnion::Monster(monster2) = got { + if let Some(example::Any::Monster(monster2)) = got { let got = monster2.name(); assert!(got == "Fred", "bad {}: want {:?} got {:?}", "Name", "Fred", got); } else { @@ -199,7 +206,7 @@ mod test { assert!(got.len() == 5, "bad {}: want {:?} got {:?}", "Inventory", "Byte Vector of length 5", got); use std::ops::Add; - let got: u8 = got.iter().fold(0, Add::add); + let got: u8 = got.fold(0, Add::add); assert!(got == 10, "bad {}: want {:?} got {:?}", "Inventory Sum", "10", got); // Test4 let mut got = monster.test4(); diff --git a/rust/src/builder.rs b/rust/src/builder.rs index 740753bcee..7fe4df81e1 100644 --- a/rust/src/builder.rs +++ b/rust/src/builder.rs @@ -2,23 +2,23 @@ //! //! Builder is a state machine for creating FlatBuffer objects. //! Use a Builder to construct object(s) starting from leaf nodes. -use std::mem; use byteorder::{ByteOrder, LittleEndian}; use types::*; +use table::Table; -/// Flatbuffer builder. +/// Builder provides functions to build Flatbuffer data. /// /// A Builder constructs byte buffers in a last-first manner for simplicity and /// performance. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Builder { // Where the FlatBuffer is constructed. - pub bytes: Vec, + bytes: Vec, // Minimum alignment encountered so far. min_align: usize, // Starting offset of the current struct/table. - object_start: usize, + object_start: UOffsetT, // Whether we are currently serializing a table. nested: bool, // Whether the buffer is finished. @@ -76,6 +76,20 @@ impl Builder { self.write_vtable() } + /// Read a completed object at offset. + /// + /// The offset is the `UOffsetT` returned by `end_object`. + pub fn read_object(&self, offset: UOffsetT) -> Table { + Table::with_pos(&self.bytes, self.bytes.len() - offset as usize) + } + + /// Read a completed object at offset. + /// + /// The offset is the `UOffsetT` returned by `end_table`. + pub fn read_table(&self, offset: UOffsetT) -> Table { + Table::from_offset(&self.bytes, self.bytes.len() - offset as usize) + } + /// Initializes bookkeeping for writing a new vector. pub fn start_vector(&mut self, elem_size: usize, num_elems: usize, alignment: usize) { self.assert_not_nested(); @@ -88,11 +102,16 @@ impl Builder { /// finish off writing the current vector. pub fn end_vector(&mut self) -> UOffsetT { - self.assert_nested(); - let len = self.vector_len; - self.put_u32(len as u32); + self.end_vector_with(len as u32) + } + /// Finish off writing the current vector of length `len`. + /// + /// Useful if you dont know the exact size of the vector when you start it. + pub fn end_vector_with(&mut self, len: u32) -> UOffsetT { + self.assert_nested(); + self.put_u32(len); self.nested = false; self.offset() as UOffsetT } @@ -110,33 +129,57 @@ impl Builder { self.end_vector() } - /// Finalize a buffer, pointing to the given `root_table`. - pub fn finish(&mut self, root_table: UOffsetT) { - if !self.finished { - self.assert_not_nested(); - let align = self.min_align; - self.prep(align, UOFFSETT_SIZE); - self.add_uoffset(root_table); - self.finished = true; + /// Create a vector in the buffer from an already encoded + /// byte vector. + pub fn create_vector(&mut self, value: &[u8]) -> UOffsetT { + let len = value.len(); + self.start_vector(1, len, 0); + self.space -= len; + for (i, c) in value.iter().enumerate() { + let pos = self.space + i; + self.place_u8(pos, *c); } + self.end_vector() } - /// Consume the builder and return the finished flatbuffer. - pub fn get_bytes(&self) -> &[u8] { - &self.bytes + /// Create a vector of `UOffsetT` in the buffer. + /// This function will encode the values to `LittleEndian`. + pub fn create_uoffset_vector(&mut self, value: &[UOffsetT]) -> UOffsetT { + let len = value.len(); + self.start_vector(UOFFSETT_SIZE, len, 0); + self.space -= len; + for (i, c) in value.iter().enumerate() { + let pos = self.space + i; + self.place_u32(pos, *c); + } + self.end_vector() } - /// Returns the length of the buffer. - pub fn len(&self) -> usize { - self.bytes.len() + /// Finalize a table, pointing to the given `root_table`. + pub fn finish_table(&mut self, root_table: UOffsetT) -> UOffsetT { + self.assert_not_nested(); + let align = self.min_align; + self.prep(align, UOFFSETT_SIZE); + self.add_uoffset(root_table); + self.finished = true; + self.offset() } - /// Returns the current finished buffer and replaces it with + /// Get a reference to the underlying buffer. + /// Buffer starts from the first byte of useful data + /// i.e. `&[pos..]`. + pub fn get_bytes(&self) -> &[u8] { + let pos = self.pos(); + &self.bytes[pos..] + } + + /// Returns the current buffer and replaces it with /// a `new_buffer`. /// /// Thie function facilitates some reuse of the `Builder` object. /// Use `into()` if the `Builder` is no longer required. pub fn swap_out(&mut self, mut new_buffer: Vec) -> Vec { + use std::mem; mem::swap(&mut self.bytes, &mut new_buffer); self.reset(); new_buffer @@ -160,10 +203,21 @@ impl Builder { self.vector_len = 0; } - /// Offset relative to the end of the buffer + /// Returns the length of the buffer. + pub fn len(&self) -> usize { + self.bytes.len() + } + + /// Offset relative to the end of the buffer. #[inline(always)] - pub fn offset(&self) -> usize { - self.bytes.len() - self.space + pub fn offset(&self) -> UOffsetT { + (self.bytes.len() - self.space) as UOffsetT + } + + /// Returns the offset relative to the beggining + /// of the buffer. + pub fn pos(&self) -> usize { + self.space } /// prepare to write an element of `size` after `additional_bytes` @@ -172,7 +226,7 @@ impl Builder { if size > self.min_align { self.min_align = size } - let align_size = self.offset() + additional_bytes + 1; + let align_size = self.offset() as usize + additional_bytes + 1; let align_size = ((align_size ^ 1)) & (size - 1); while self.space <= align_size + size + additional_bytes { self.grow(); @@ -493,13 +547,90 @@ impl Builder { } } - // helper method to read a VOffsetT - fn get_u16(&self, pos: usize) -> VOffsetT { + /// Place a `u8` at `pos` relative to the beginning + /// of the underlaying buffer. + pub fn place_u8(&mut self, pos: usize, value: u8) { + self.bytes[pos] = value; + } + + /// Place a `u32` with `LittleEndian` encoding at `pos` + /// relative to the beginning of the underlaying buffer. + pub fn place_u32(&mut self, pos: usize, value: u32) { + LittleEndian::write_u32(&mut self.bytes[pos..pos + 4], value); + } + + /// Place a `i32` with `LittleEndian` encoding at `pos` + /// relative to the beginning of the underlaying buffer. + pub fn place_i32(&mut self, pos: usize, value: i32) { + LittleEndian::write_i32(&mut self.bytes[pos..pos + 4], value); + } + + /// Place a `u64` with `LittleEndian` encoding at `pos` + /// relative to the beginning of the underlaying buffer. + pub fn place_u64(&mut self, pos: usize, value: u64) { + LittleEndian::write_u64(&mut self.bytes[pos..pos + 8], value); + } + + /// Check to assert `finish` has not been called. + pub fn assert_not_finished(&self) { + assert!(!self.finished, + "FlatBuffers: root table is not finished."); + } + + /// Check to assert `start_object` has not been called. + pub fn assert_not_nested(&self) { + assert!(!self.nested, + "FlatBuffers: object serialization must not be nested."); + } + + /// Check to assert `start_object` has been called. + pub fn assert_nested(&self) { + assert!(self.nested, + "FlatBuffers: struct must be serialized inline."); + } + + /// Helper method to read a VOffsetT at `pos` relative to the + /// beginning of the underlying buffer - this may not be the start + /// of any useful data. Use with `offset()` to get the `UOffsetT` + /// of useful data. + pub fn get_u16(&self, pos: usize) -> VOffsetT { LittleEndian::read_u16(&self.bytes[pos..pos + 2]) } -} -impl Builder { + /// Helper method to read a UOffsetT at `pos` relative to the + /// beginning of the underlying buffer - this may not be the start + /// of any useful data. Use with `offset()` to get the `UOffsetT` + /// of useful data. + pub fn get_32(&self, pos: usize) -> UOffsetT { + LittleEndian::read_u32(&self.bytes[pos..pos + 4]) + } + + /// Doubles the size of the buffer. + /// + /// Copies the old data towards the end of the new buffer (since we build + /// the buffer backwards). + /// Max buffer size is 2 Gigabytes - otherwise u16 index values might + /// be invalid. + pub fn grow(&mut self) { + let old_capacity = if self.bytes.capacity() == 0 { + 1 + } else { + self.bytes.capacity() + }; + let size_test = old_capacity & 0xC0000000; + assert!(size_test == 0, + "FlatBuffers: cannot grow buffer beyond 2 gigabytes."); + let new_capacity = old_capacity << 1; + let mut nbytes = Vec::with_capacity(new_capacity); + for _ in 0..old_capacity { + nbytes.push(0) + } + self.space = new_capacity - self.offset() as usize; + nbytes.extend_from_slice(&self.bytes); + unsafe { nbytes.set_len(new_capacity) }; + self.bytes = nbytes; + } + // WriteVtable serializes the vtable for the current object. // // Before writing out the vtable, this checks pre-existing vtables for @@ -510,7 +641,7 @@ impl Builder { // logically-equal vtables will be deduplicated. fn write_vtable(&mut self) -> UOffsetT { self.add_uoffset(0); - let vtableloc = self.offset(); + let vtableloc = self.offset() as usize; // Write out the current vtable. for i in (0..self.vtable_in_use).rev() { // Offset relative to the start of the table. @@ -522,7 +653,7 @@ impl Builder { self.add_u16(offset as u16); } // write the metadata - let total_obj_size = vtableloc - self.object_start; + let total_obj_size = vtableloc - self.object_start as usize; let vtable_size = (self.vtable_in_use + VTABLE_METADATA_FIEDS) * VOFFSETT_SIZE; self.add_u16(total_obj_size as u16); self.add_u16(vtable_size as u16); @@ -530,16 +661,15 @@ impl Builder { let mut existing_vt = 0; let mut this_vt = self.space; 'outer: for (i, vt_offset) in self.vtables.iter().rev().enumerate() { - let vt_start = self.bytes.capacity() - *vt_offset as usize; + let vt_start = self.bytes.len() - *vt_offset as usize; let vt_len = self.get_u16(vt_start); if vt_len != self.get_u16(this_vt) { continue; } let vt_end = vt_start + vt_len as usize; let vt_bytes = &self.bytes[vt_start + VTABLE_METADATA_SIZE..vt_end]; - for (j, chunk) in vt_bytes.chunks(2).enumerate() { - - let this_start = this_vt + (j * VOFFSETT_SIZE) as usize; + for (j, chunk) in vt_bytes.chunks(VOFFSETT_SIZE).enumerate() { + let this_start = this_vt + VTABLE_METADATA_SIZE + (j * VOFFSETT_SIZE) as usize; let this_end = this_start + VOFFSETT_SIZE; let this_chunk = &self.bytes[this_start..this_end]; if chunk != this_chunk { @@ -554,59 +684,17 @@ impl Builder { // found a match self.space = self.bytes.capacity() - vtableloc; let pos = self.space; - self.place_u32(pos, (existing_vt - vtableloc) as u32); + self.place_i32(pos, (existing_vt as i32 - vtableloc as i32)); } else { // no match - this_vt = self.offset(); + this_vt = self.offset() as usize; self.vtables.push(this_vt as u32); let capacity = self.bytes.capacity(); - self.place_u32(capacity - vtableloc, (this_vt - vtableloc) as u32); + self.place_i32(capacity - vtableloc, (this_vt - vtableloc) as i32); } + self.vtable.clear(); vtableloc as UOffsetT } - - /// Doubles the size of the buffer. - /// - /// copies the old data towards the end of the new buffer (since we build - /// the buffer backwards). - pub fn grow(&mut self) { - let old_capacity = if self.bytes.capacity() == 0 { - 1 - } else { - self.bytes.capacity() - }; - let size_test = old_capacity & 0xC0000000; - assert!(size_test == 0, - "FlatBuffers: cannot grow buffer beyond 2 gigabytes."); - let new_capacity = old_capacity << 1; - let mut nbytes = Vec::with_capacity(new_capacity); - for _ in 0..old_capacity { - nbytes.push(0) - } - self.space = new_capacity - self.offset(); - nbytes.extend_from_slice(&self.bytes); - unsafe { nbytes.set_len(new_capacity) }; - self.bytes = nbytes; - } - - - fn place_u8(&mut self, pos: usize, value: u8) { - self.bytes[pos] = value; - } - - fn place_u32(&mut self, pos: usize, value: u32) { - LittleEndian::write_u32(&mut self.bytes[pos..pos + 4], value); - } - - fn assert_not_nested(&self) { - assert!(!self.nested, - "FlatBuffers: object serialization must not be nested."); - } - - fn assert_nested(&self) { - assert!(self.nested, - "FlatBuffers: struct must be serialized inline."); - } } impl Default for Builder { @@ -621,19 +709,11 @@ impl Into> for Builder { } } -/// A trait used by generated object builders to facilitate -/// using the same flatbuffer `Builder`. -pub trait ObjectBuilder: Into + From { - /// Convert from one `ObjectBuilder` instance to another. - #[inline(always)] - fn from_other(x: T) -> Self { - x.into().into() - } -} - #[cfg(test)] mod test { use super::Builder; + use types::*; + use table::Table; #[test] fn grow_buffer() { @@ -780,7 +860,7 @@ mod test { b.start_object(1); check(&b, 30, &[]); b.add_slot_bool(0, true, false); - b.end_object(); + let obj = b.end_object(); check(&b, 31, &[ 6, 0, // vtable bytes 8, 0, // length of object including vtable offset @@ -789,6 +869,15 @@ mod test { 0, 0, 0, // padded to 4 bytes 1, // bool value ]); + { + let read_obj = b.read_object(obj); + let o = read_obj.field_offset(4); + let got = read_obj.get_bool(o); + assert!(got == true, "Failed to read back last object - got {:?} expected true", got); + let got = read_obj.get_u8(o); + assert!(got == 1, "Failed to read back last object. wrong value expected 1 got {}", got); + } + // test 9: vtable with one default bool b = Builder::with_capacity(0); @@ -884,6 +973,19 @@ mod test { 0, 0, 55, 0, // value 0 0, 0, 0, 0, // length of vector (not in struct) ]); + { + let buffer = b.get_bytes(); + assert_eq!(buffer, &[ + 8, 0, // vtable bytes + 12, 0, + 10, 0, // offset to value 0 + 4, 0, // offset to vector offset + 8, 0, 0, 0, // vtable loc + 8, 0, 0, 0, // value 1 + 0, 0, 55, 0, // value 0 + 0, 0, 0, 0, // length of vector (not in struct) + ]); + } // test 13: vtable with 1 int16 and 2-vector of int16 b = Builder::with_capacity(0); @@ -964,7 +1066,7 @@ mod test { b.add_slot_i8(0, 33, 0); b.add_slot_i16(1, 66, 0); let off = b.end_object(); - b.finish(off); + b.finish_table(off); check(&b, 42, &[ 12, 0, 0, 0, // root of table: points to vtable offset @@ -986,15 +1088,15 @@ mod test { b.start_object(2); b.add_slot_i8(0, 33, 0); b.add_slot_i8(1, 44, 0); - let off = b.end_object(); - b.finish(off); + let obj1 = b.end_object(); + let table1 = b.finish_table(obj1); b.start_object(3); b.add_slot_i8(0, 55, 0); b.add_slot_i8(1, 66, 0); b.add_slot_i8(2, 77, 0); - let off = b.end_object(); - b.finish(off); + let obj2 = b.end_object(); + let table2 = b.finish_table(obj2); check(&b, 43, &[ 16, 0, 0, 0, // root of table: points to object @@ -1022,6 +1124,30 @@ mod test { 44, // value 1 33, // value 0 ]); + assert!(b.offset() as usize + b.pos() == b.len()); + { + let read_obj = b.read_object(obj1); + let o = read_obj.field_offset(4); + let got = read_obj.get_u8(o); + assert!(got == 33, "Failed to read back last object - got {:?} expected 33", got); + let read_table = b.read_table(table1); + let o = read_table.field_offset(6); + let got = read_table.get_u8(o); + assert!(got == 44, "Failed to read back last object - got {:?} expected 44", got); + + let read_obj = b.read_object(obj2); + let o = read_obj.field_offset(4); + let got = read_obj.get_u8(o); + assert!(got == 55, "Failed to read back last object - got {:?} expected 55", got); + let read_table = b.read_table(table2); + let o = read_table.field_offset(6); + let got = read_table.get_u8(o); + assert!(got == 66, "Failed to read back last object - got {:?} expected 66", got); + let o = read_table.field_offset(8); + let got = read_table.get_u8(o); + assert!(got == 77, "Failed to read back last object - got {:?} expected 77", got); + } + // test 18: a bunch of bools b = Builder::with_capacity(0); @@ -1035,7 +1161,7 @@ mod test { b.add_slot_bool(6, true, false); b.add_slot_bool(7, true, false); let off = b.end_object(); - b.finish(off); + b.finish_table(off); check(&b, 44, &[ 24, 0, 0, 0, // root of table: points to vtable offset @@ -1070,7 +1196,7 @@ mod test { b.add_slot_bool(1, true, false); b.add_slot_bool(2, true, false); let off = b.end_object(); - b.finish(off); + b.finish_table(off); check(&b, 45, &[ 16, 0, 0, 0, // root of table: points to vtable offset @@ -1105,4 +1231,93 @@ mod test { 0, 0, 128, 63, // value 0 ]); } + + #[test] + fn duplicate_vtable() { + let mut b = Builder::with_capacity(0); + + b.start_object(4); + b.add_slot_u8(0, 0, 0); + b.add_slot_u8(1, 11, 0); + b.add_slot_u8(2, 22, 0); + b.add_slot_i16(3, 33, 0); + let obj0 = b.end_object(); + + b.start_object(4); + b.add_slot_u8(0, 0, 0); + b.add_slot_u8(1, 44, 0); + b.add_slot_u8(2, 55, 0); + b.add_slot_i16(3, 66, 0); + let obj1 = b.end_object(); + + b.start_object(4); + b.add_slot_u8(0, 0, 0); + b.add_slot_u8(1, 77, 0); + b.add_slot_u8(2, 88, 0); + b.add_slot_i16(3, 99, 0); + let obj2 = b.end_object(); + + let got = b.get_bytes(); + + let want: &[u8] = &[ + 240, 255, 255, 255, // == -12. offset to dedupped vtable. + 99, 0, + 88, + 77, + 248, 255, 255, 255, // == -8. offset to dedupped vtable. + 66, 0, + 55, + 44, + 12, 0, + 8, 0, + 0, 0, + 7, 0, + 6, 0, + 4, 0, + 12, 0, 0, 0, + 33, 0, + 22, + 11, + ]; + assert!(got == want, "testVtableDeduplication want:\n{} {:?}\nbut got:\n{} {:?}\n", + want.len(), want, got.len(), got); + + let len = got.len(); + let table0 = Table::with_pos(got, len - obj0 as usize); + let table1 = Table::with_pos(got, len - obj1 as usize); + let table2 = Table::with_pos(got, len - obj2 as usize); + fn test_table(tab: &Table, a: VOffsetT, b: u8, c: u8, d: u8) { + let got = tab.read_voffset_slot(0, 0); + if 12 != got { + panic!("failed 0, 0: {}", got) + } + // object size + let got = tab.read_voffset_slot(2, 0); + if 8 != got { + panic!("failed 2, 0: {}", got) + } + // default value + let got = tab.read_voffset_slot(4, 0); + if a != got { + panic!("failed 4, 0: {}", got) + } + let got = tab.get_slot_u8(6, 0); + if b != got as u8 { + panic!("failed 6, 0: {}", got) + } + let val = tab.get_slot_u8(8, 0); + if c != val as u8 { + panic!("failed 8, 0: {}", got) + } + let got = tab.get_slot_u8(10, 0); + if d != got as u8 { + panic!("failed 10, 0: {}", got) + } + + } + test_table(&table0, 0, 11, 22, 33); + test_table(&table1, 0, 44, 55, 66); + test_table(&table2, 0, 77, 88, 99); + + } } diff --git a/rust/src/iter.rs b/rust/src/iter.rs index df5a1479c2..19ba511e58 100644 --- a/rust/src/iter.rs +++ b/rust/src/iter.rs @@ -1,129 +1,162 @@ +use std::fmt::Debug; use std::iter; use std::marker::PhantomData; +use byteorder::{ByteOrder, LittleEndian}; use table; -use types::*; +use table::Table; + +/// A trait for Structs and Tables to implement. +pub trait VectorItem { + /// Table Objects require indirection. Structs do not. + fn indirect_lookup() -> bool; + /// The size of the object in the vector. + fn inline_size() -> usize; +} /// An iterator over flatbuffer vectors. #[derive(Debug)] pub struct Iterator<'a, T> { - is_table: bool, - table: &'a table::Table<'a>, + buffer: &'a [u8], index: usize, len: usize, i: usize, _marker: PhantomData<[T]> } -/// Create a new iterator over a flatbuffer vector of string. -pub fn new_string_iterator<'a>(table: &'a table::Table, offset: usize) -> Iterator<'a, &'a str> { - let len = table.get_u32(offset as u32); - Iterator { - is_table: false, - table: table, - index: offset + UOFFSETT_SIZE, - len: len as usize, - i: 0, - _marker: PhantomData, - } +/// A trait for handling little endian encoding of byte arrays. +pub trait LittleEndianReader<'a> { + /// Read the first byte from buffer and return type `Self`. + fn read(buffer: &'a [u8], index: usize) -> Self; + /// Provide the size in bytes of type `Self`. + fn size() -> usize; } -/// Create a new iterator over a flatbuffer vector of structs. -pub fn new_struct_iterator<'a, T: From>>(table: &'a table::Table, offset: usize) -> Iterator<'a, T> { - let len = table.get_u32(offset as u32); - Iterator { - is_table: false, - table: table, - index: offset + UOFFSETT_SIZE, - len: len as usize, - i: 0, - _marker: PhantomData, - } +impl<'a> LittleEndianReader<'a>for u8 { + fn read(buffer: &[u8], index: usize) -> u8 { buffer[index] } + fn size() -> usize { 1 } } -/// Create a new iterator over a flatbuffer vector of tables. -pub fn new_table_iterator<'a, T: From>>(table: &'a table::Table, offset: usize) -> Iterator<'a, T> { - let len = table.get_u32(offset as u32); - Iterator { - is_table: true, - table: table, - index: offset, - len: len as usize, - i: 0, - _marker: PhantomData, - } + +impl<'a> LittleEndianReader<'a>for i8 { + fn read(buffer: &[u8], index: usize) -> i8 { buffer[index] as i8 } + fn size() -> usize { 1 } } -#[doc(hide)] -/// Helper function. Constructs a zero iterator. -pub fn empty_iterator<'a, T>(table: &'a table::Table) -> Iterator<'a, T> { - Iterator { - is_table: false, - table: table, - index: 0, - len: 0, - i: 100, - _marker: PhantomData - } +impl<'a> LittleEndianReader<'a>for bool { + fn read(buffer: &[u8], index: usize) -> bool { buffer[index] == 0 } + fn size() -> usize { 1 } } +impl<'a> LittleEndianReader<'a>for u16 { + fn read(buffer: &[u8], index: usize) -> u16 { LittleEndian::read_u16(&buffer[index..]) } + fn size() -> usize { 2 } +} -impl<'a> iter::Iterator for Iterator<'a, &'a str> { - type Item = &'a str; +impl<'a> LittleEndianReader<'a>for i16 { + fn read(buffer: &[u8], index: usize) -> i16 { LittleEndian::read_i16(&buffer[index..]) } + fn size() -> usize { 2 } +} - fn next(&mut self) -> Option<&'a str> { - if self.i < self.len { - let offset = self.index as u32; - let res = self.table.get_str(offset); - self.index += UOFFSETT_SIZE; - self.i += 1; - return Some(res) - } - None - } +impl<'a> LittleEndianReader<'a>for u32 { + fn read(buffer: &[u8], index: usize) -> u32 { LittleEndian::read_u32(&buffer[index..]) } + fn size() -> usize { 4 } +} + +impl<'a> LittleEndianReader<'a>for i32 { + fn read(buffer: &[u8], index: usize) -> i32 { LittleEndian::read_i32(&buffer[index..]) } + fn size() -> usize { 4 } +} + +impl<'a> LittleEndianReader<'a>for u64 { + fn read(buffer: &[u8], index: usize) -> u64 { LittleEndian::read_u64(&buffer[index..]) } + fn size() -> usize { 8 } +} - fn size_hint(&self) -> (usize, Option) { - let len = self.table.get_u32(0); - (0, Some(len as usize)) +impl<'a> LittleEndianReader<'a>for i64 { + fn read(buffer: &[u8], index: usize) -> i64 { LittleEndian::read_i64(&buffer[index..]) } + fn size() -> usize { 8 } +} + +impl<'a> LittleEndianReader<'a>for f32 { + fn read(buffer: &[u8], index: usize) -> f32 { LittleEndian::read_f32(&buffer[index..]) } + fn size() -> usize { 4 } +} + +impl<'a> LittleEndianReader<'a>for f64 { + fn read(buffer: &[u8], index: usize) -> f64 { LittleEndian::read_f64(&buffer[index..]) } + fn size() -> usize { 8 } +} + +impl<'a> LittleEndianReader<'a>for &'a str { + fn read(buffer: &[u8], index:usize) -> &str { + use std::str; + let offset = LittleEndian::read_u32(&buffer[index..]) as usize + index; + let start = offset as usize + 4; + let length = table::read_uoffset(buffer, offset as usize) as usize; + let s = &buffer[start..start+length]; + unsafe { str::from_utf8_unchecked(s) } } + fn size() -> usize { 4 } } -impl<'a> ExactSizeIterator for Iterator<'a, &'a str> { - fn len(&self) -> usize { - self.len + +impl<'a, T: From> + VectorItem> LittleEndianReader<'a>for T { + fn read(buffer: &'a [u8], index: usize) -> T { + let table = if T::indirect_lookup() { + Table::from_offset(buffer, index as usize) + } else { + Table::with_pos(&buffer, index as usize) + }; + table.into() } + fn size() -> usize { T::inline_size() } } -impl<'a, T: From>> iter::Iterator for Iterator<'a, T> { +impl<'a, T: LittleEndianReader<'a>> iter::Iterator for Iterator<'a, T> { type Item = T; fn next(&mut self) -> Option { if self.i < self.len { self.i += 1; - if self.is_table { - //let offset = self.table.get_u32(self.index as u32); - let offset = self.index as u32; - let res = self.table.get_indirect_root(offset); - self.index += UOFFSETT_SIZE; - return Some(res.into()) - } else { - let index = self.index; - let res = self.table.get_struct(index as u32); - self.index += UOFFSETT_SIZE; + let slice = &self.buffer[self.index..]; + if slice.len() >= T::size() { + let res = T::read(self.buffer, self.index); + self.index += T::size(); return Some(res) - } } None } - - fn size_hint(&self) -> (usize, Option) { - let len = self.table.get_u32(0); - (0, Some(len as usize)) - } } -impl<'a, T: From>> ExactSizeIterator for Iterator<'a, T> { +impl<'a, T: LittleEndianReader<'a> + Debug> ExactSizeIterator for Iterator<'a, T> { fn len(&self) -> usize { self.len } } + +impl<'a, T> Default for Iterator<'a, T> { + fn default() -> Iterator<'a, T> { + Iterator { + buffer: &[], + index: 0, + len: 0, + i: 0, + _marker: PhantomData + } + } +} + +impl<'a, T> Iterator<'a, T> { + /// Create a new Iterator for type `T` starting at `index` with + /// a length of `len` items of size `T`. + pub fn new(buffer: &[u8], index: usize, len: usize) -> Iterator { + Iterator { + buffer: buffer, + index: index, + len: len, + i: 0, + _marker: PhantomData + } + } +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 0b6c47263c..d6c91b9a56 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -17,7 +17,10 @@ mod types; mod table; mod iter; -pub use self::builder::{Builder,ObjectBuilder}; +#[macro_use] +pub mod macros; + +pub use self::builder::Builder; pub use self::types::{UOffsetT, VOffsetT, SOffsetT}; pub use self::table::Table; pub use self::iter::*; diff --git a/rust/src/macros.rs b/rust/src/macros.rs new file mode 100644 index 0000000000..fd1357a4b1 --- /dev/null +++ b/rust/src/macros.rs @@ -0,0 +1,206 @@ +//! TODO + +#[macro_export] +macro_rules! table_fn { + (get_u8, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_slot_u8($slot, $default) }; + (get_i8, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_slot_i8($slot, $default) }; + (get_u16, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_slot_u16($slot, $default) }; + (get_i16, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_slot_i16($slot, $default) }; + (get_u32, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_slot_u32($slot, $default) }; + (get_i32, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_slot_i32($slot, $default) }; + (get_u64, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_slot_u64($slot, $default) }; + (get_i64, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_slot_i64($slot, $default) }; + (get_f32, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_slot_f32($slot, $default) }; + (get_f64, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_slot_f64($slot, $default) }; + (get_bool, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_slot_bool($slot, $default) }; + (get_str, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_slot_str($slot) }; + (get_struct, $s:ident, $slot:expr, $ty:ty) => { ($s.0).get_slot_struct::<$ty>($slot) }; + (vector, $s:ident, $slot:expr, $ty:ty) => { ($s.0).get_slot_vector::<$ty>($slot) }; +} + +#[macro_export] +macro_rules! struct_fn { + (get_u8, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_u8($slot) }; + (get_i8, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_i8($slot) }; + (get_u16, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_u16($slot) }; + (get_i16, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_i16($slot) }; + (get_u32, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_u32($slot) }; + (get_i32, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_i32($slot) }; + (get_u64, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_u64($slot) }; + (get_i64, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_i64($slot) }; + (get_f32, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_f32($slot) }; + (get_f64, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_f64($slot) }; + (get_bool, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_bool($slot) }; + (get_str, $s:ident, $slot:expr, $default:expr) => { ($s.0).get_str($slot) }; + (get_struct, $s:ident, $slot:expr, $ty:ty) => { ($s.0).get_struct::<$ty>($slot) }; +} + + +#[macro_export] +macro_rules! table_get_fn { + (($name:ident, get_struct, $ty:ty, $slot:expr)) => { + pub fn $name(&self) -> Option<$ty> { + table_fn!(get_struct, self, $slot, $ty) + } + }; + (($name:ident, vector, $ty:ty, $slot:expr)) => { + pub fn $name(&self) -> flatbuffers::Iterator<$ty> { + table_fn!(vector, self, $slot, $ty) + } + }; + (($name:ident, simple_enum, $n:ident, $ty:ty, $enum_mod:ident, $slot:expr, $default:expr)) => { + pub fn $name(&self) -> Option<$enum_mod> { + let v = table_fn!($n, self, $slot, $default); + $enum_mod::from(v) + } + }; + (($name:ident, union, $ty_fn:ident, $ty:ty, $enum_mod:ident, $slot:expr, $default:expr)) => { + pub fn $name(&self) -> Option<$ty> { + let offset = self.0.field_offset($slot); + if offset != 0 { + let ty = self.$ty_fn(); + let table = self.0.get_root(offset); + return $enum_mod::new(table, ty); + } + None + } + }; + (($name:ident, $n:ident, $ty:ty, $slot:expr, $default:expr)) => { + pub fn $name(&self) -> $ty { + table_fn!($n, self, $slot, $default) + } + } +} + +#[macro_export] +macro_rules! struct_get_fn { + (($name:ident, get_struct, $ty:ty, $slot:expr)) => { + pub fn $name(&self) -> $ty { + struct_fn!(get_struct, self, $slot, $ty) + } + }; + (($name:ident, simple_enum, $n:ident, $ty:ty, $enum_mod:ident, $slot:expr, $default:expr)) => { + pub fn $name(&self) -> Option<$enum_mod> { + let v = struct_fn!($n, self, $slot, $default); + $enum_mod::from(v) + } + }; + (($name:ident, $n:ident, $ty:ty, $slot:expr, $default:expr)) => { + pub fn $name(&self) -> $ty { + struct_fn!($n, self, $slot, $default) + } + } +} + +#[macro_export] +macro_rules! table_struct { + ($name:ident) => { + #[derive(Debug)] + pub struct $name<'a>($crate::Table<'a>); + + impl<'a> From<$crate::Table<'a>> for $name<'a> { + fn from(table: $crate::Table) -> $name { + $name(table) + } + } + } +} + +#[macro_export] +macro_rules! vector_item { + ($name:ident, $indirect:expr, $inline_size:expr) => { + impl<'a> $crate::VectorItem for $name<'a> { + fn indirect_lookup() -> bool { + $indirect + } + + fn inline_size() -> usize { + $inline_size + } + } + } +} + +#[macro_export] +macro_rules! table_object { + ($name:ident, $inline_size:expr, [ $( $f:tt ),* ]) => { + table_struct!{$name} + impl<'a> $name<'a> { + pub fn new(table: $crate::Table) -> $name { + $name ( table ) + } + $( table_get_fn!{$f} )* + } + vector_item!{ $name, true, $inline_size } + } +} + +#[macro_export] +macro_rules! struct_object { + ($name:ident, $inline_size:expr, [ $( $f:tt ),* ]) => { + table_struct!{$name} + impl<'a> $name<'a> { + pub fn new(table: $crate::Table) -> $name { + $name ( table ) + } + $( struct_get_fn!{$f} )* + } + vector_item!{ $name, false, $inline_size } + } +} + +#[macro_export] +macro_rules! simple_enum { + ($type_name:ident, $repr:ident, + [ $( ($e_name:ident, $value:expr) ),+ ]) => { + #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] + #[repr($repr)] + pub enum $type_name { + $( $e_name = $value ),+ + } + + impl $type_name { + pub fn from(value: $repr) -> Option<$type_name> { + match value { + $( $value => Some($type_name::$e_name) ),+, + _ => None + } + } + } + } +} + +#[macro_export] +macro_rules! union { + ($name:ident, $type_name:ident, $repr:ident, [ $( ($e_name:ident, $value:expr, $ty:ty) ),+ ]) => { + #[derive(Debug)] + pub enum $name<'a> { + None, + $( $e_name( $ty ) ),+ + } + + impl<'a> $name<'a> { + pub fn new(table: $crate::Table, utype: Option<$type_name>) -> Option<$name> { + match utype { + $( Some($type_name::$e_name) => Some( $name::$e_name( table.into() ) ), )* + _ => None + } + } + } + + simple_enum!($type_name, $repr, [ $( ($e_name, $value) ),+ ]); + }; +} + +// union!{Any, AnyType, u8, [(Monster, 1, Monster<'a>)]} + + +// table!{Monster, [ (get_u16, u16, hp, 8, 150), +// (get_i16, i16, mana, 10, 150), +// (byte_vector, u8, test, 11), +// (ibyte_vector, i8, test2, 11), +// (bool_vector, bool, test3, 11) +// ]} + +// simple_struct!{Vec3, BuildVec3, build_vec3, [ (get_u16, u16, hp, 8, 150), +// (get_i16, i16, mana, 10, 150)]} diff --git a/rust/src/table.rs b/rust/src/table.rs index 3e1c67a921..68fa5d5059 100644 --- a/rust/src/table.rs +++ b/rust/src/table.rs @@ -1,27 +1,63 @@ use byteorder::{ByteOrder, LittleEndian}; use types::*; -use iter; +use iter::Iterator; -/// A wrapper object around Flatbuffer table data. +/// Table provides functions to read Flatbuffer data. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Table<'a> { buffer: &'a [u8], - pos: UOffsetT + pos: usize } impl<'a> Table<'a> { - /// Create a table using from a slice using data starting at offset. - pub fn from_offset(buffer: &[u8], offset: UOffsetT) -> Table { - let n = read_uoffset(&buffer, offset as UOffsetT); + /// Create a table using from a slice using data starting at `pos`. + /// First `UOffsetT` should indicate the offset from the root + /// of the table to the begining of the object. + /// + /// In the following example pos should be 0: + /// ``` + /// 16, 0, 0, 0, // root of table: points to object <--------- + /// 0, 0, // padding + /// 10, 0, // vtable bytes + /// 8, 0, // size of object + /// 7, 0, // start of value 0 + /// 6, 0, // start of value 1 + /// 5, 0, // start of value 2 + /// 10, 0, 0, 0, // start of object..ie. vtable offset + /// 0, // padding + /// 77, // value 2 + /// 66, // value 1 + /// 55, // value 0 + /// ``` + pub fn from_offset(buffer: &[u8], pos: usize) -> Table { + let n = read_uoffset(&buffer, pos); Table { buffer: buffer, - pos: n + offset + pos: n as usize + pos } } - /// Create a table for a simple inline struct. - pub fn with_pos(buffer: &[u8], pos: UOffsetT) -> Table { + /// Create a table for an object. + /// `pos` should be the offset to the first byte of + /// useable data. + /// + /// In the following example pos should be 16: + /// ``` + /// 16, 0, 0, 0, // root of table: points to object + /// 0, 0, // padding + /// 10, 0, // vtable bytes + /// 8, 0, // size of object + /// 7, 0, // start of value 0 + /// 6, 0, // start of value 1 + /// 5, 0, // start of value 2 + /// 10, 0, 0, 0, // start of object..ie. vtable offset <--------- + /// 0, // padding + /// 77, // value 2 + /// 66, // value 1 + /// 55, // value 0 + /// ``` + pub fn with_pos(buffer: &[u8], pos: usize) -> Table { Table { buffer: buffer, pos: pos @@ -29,14 +65,15 @@ impl<'a> Table<'a> { } /// Return an object table at offset. + /// See `from_offset`. pub fn get_root(&self, offset: UOffsetT) -> Table { - Table::from_offset(self.buffer, self.pos + offset) + Table::from_offset(self.buffer, self.pos + offset as usize) } /// Return an object table at offset specified by offset. pub fn get_indirect_root(&self, offset: UOffsetT) -> Table { let actual_offset = self.pos as u32 + offset + self.get_u32(offset); - Table::with_pos(&self.buffer, actual_offset) + Table::with_pos(&self.buffer, actual_offset as usize) } @@ -46,10 +83,9 @@ impl<'a> Table<'a> { // and is by default a negative direction. #[inline(always)] fn vtable(&self) -> &[u8] { - let pos = self.pos; - let vt_offset = read_soffset(&self.buffer, self.pos as UOffsetT); + let vt_offset = read_soffset(&self.buffer, self.pos); let vtable = (self.pos as i32 - vt_offset) as usize; - &self.buffer[vtable..pos as usize] + &self.buffer[vtable..] } /// Returns the field offset or 0 if the field was not present. @@ -62,137 +98,240 @@ impl<'a> Table<'a> { 0 } - /// ByteVector gets an unsigned byte slice from data stored inside - /// the flatbuffer. - pub fn byte_vector(&self, offset: UOffsetT) -> &[u8] { - let mut offset = offset + self.pos as UOffsetT; - offset += read_uoffset(self.buffer, offset); - let start = offset as usize + 4 as usize; - let length = read_uoffset(self.buffer, offset) as usize; - &self.buffer[start..start+length] + /// Returns the `bool` value of the field at the offset written in the + /// vtable `slot`. + pub fn get_slot_bool(&self, slot: VOffsetT, default: bool) -> bool { + let offset = self.field_offset(slot); + if offset != 0 { + return self.get_bool(offset) + } + default } - /// ByteVector gets a signed byte slice from data stored inside - /// the flatbuffer. - pub fn ibyte_vector(&self, offset: UOffsetT) -> &[i8] { - let slice = self.byte_vector(offset); - let len = slice.len(); - unsafe { - use std::slice; - let z = slice.as_ptr() as *const i8; - slice::from_raw_parts(z, len) + /// Returns the `u8` value of the field at the offset written in the + /// vtable `slot`. + pub fn get_slot_u8(&self, slot: VOffsetT, default: u8) -> u8 { + let offset = self.field_offset(slot); + if offset != 0 { + return self.get_u8(offset) + } + default + } + + /// Returns the `i8` value of the field at the offset written in the + /// vtable `slot`. + pub fn get_slot_i8(&self, slot: VOffsetT, default: i8) -> i8 { + let offset = self.field_offset(slot); + if offset != 0 { + return self.get_i8(offset) + } + default + } + + /// Returns the `u16` value of the field at the offset written in the + /// vtable `slot`. + pub fn get_slot_u16(&self, slot: VOffsetT, default: u16) -> u16 { + let offset = self.field_offset(slot); + if offset != 0 { + return self.get_u16(offset) + } + default + } + + /// Returns the `i16` value of the field at the offset written in the + /// vtable `slot`. + pub fn get_slot_i16(&self, slot: VOffsetT, default: i16) -> i16 { + let offset = self.field_offset(slot); + if offset != 0 { + return self.get_i16(offset) + } + default + } + + /// Returns the `u32` value of the field at the offset written in the + /// vtable `slot`. + pub fn get_slot_u32(&self, slot: VOffsetT, default: u32) -> u32 { + let offset = self.field_offset(slot); + if offset != 0 { + return self.get_u32(offset) + } + default + } + + /// Returns the `i32` value of the field at the offset written in the + /// vtable `slot`. + pub fn get_slot_i32(&self, slot: VOffsetT, default: i32) -> i32 { + let offset = self.field_offset(slot); + if offset != 0 { + return self.get_i32(offset) + } + default + } + + /// Returns the `u64` value of the field at the offset written in the + /// vtable `slot`. + pub fn get_slot_u64(&self, slot: VOffsetT, default: u64) -> u64 { + let offset = self.field_offset(slot); + if offset != 0 { + return self.get_u64(offset) + } + default + } + + /// Returns the `i64` value of the field at the offset written in the + /// vtable `slot`. + pub fn get_slot_i64(&self, slot: VOffsetT, default: i64) -> i64 { + let offset = self.field_offset(slot); + if offset != 0 { + return self.get_i64(offset) } + default } - /// ByteVector gets a slice of bool from data stored inside the flatbuffer. - pub fn bool_vector(&self, offset: UOffsetT) -> &[bool] { - let slice = self.byte_vector(offset); - let len = slice.len(); - unsafe { - use std::slice; - let z = slice.as_ptr() as *const bool; - slice::from_raw_parts(z, len) + /// Returns the `f32` value of the field at the offset written in the + /// vtable `slot`. + pub fn get_slot_f32(&self, slot: VOffsetT, default: f32) -> f32 { + let offset = self.field_offset(slot); + if offset != 0 { + return self.get_f32(offset) } + default } - /// TODO - pub fn struct_vector>>(&'a self, offset: UOffsetT) -> iter::Iterator { - let mut offset = offset; - offset += self.get_u32(offset); - iter::new_struct_iterator::(&self, offset as usize) + /// Returns the `f64` value of the field at the offset written in the + /// vtable `slot`. + pub fn get_slot_f64(&self, slot: VOffsetT, default: f64) -> f64 { + let offset = self.field_offset(slot); + if offset != 0 { + return self.get_f64(offset) + } + default } - /// TODO - pub fn table_vector>>(&'a self, offset: UOffsetT) -> iter::Iterator { - let mut offset = offset; - offset += self.get_u32(offset); - iter::new_table_iterator::(&self, offset as usize) + /// Returns the `&str` value of the field at the offset written in the + /// vtable `slot`. + pub fn get_slot_str(&self, slot: VOffsetT) -> &str { + let offset = self.field_offset(slot); + if offset != 0 { + return self.get_str(offset) + } + "" } - /// TODO - pub fn str_vector(&'a self, offset: UOffsetT) -> iter::Iterator<&str> { - let mut offset = offset; - offset += self.get_u32(offset); - iter::new_string_iterator(&self, offset as usize) + + + /// Returns the struct `T` value of the field at the offset written in the + /// vtable `slot`. + pub fn get_slot_struct>>(&self, slot: VOffsetT) -> Option { + let offset = self.field_offset(slot); + if offset != 0 { + return Some(self.get_struct(offset)) + } + None + } + + /// Returns the unsigned byte vector value of the field at the offset written in the + /// vtable `slot`. + pub fn get_slot_vector(&self, slot: VOffsetT) -> Iterator<'a, T> { + let offset = self.field_offset(slot); + if offset != 0 { + return self.get_vector::(offset) + } + Default::default() + } + + /// ByteVector gets an unsigned byte slice from data stored inside + /// the flatbuffer. + pub fn get_vector(&self, offset: UOffsetT) -> Iterator<'a, T> { + let mut offset = offset as usize + self.pos; + offset += read_uoffset(self.buffer, offset) as usize; + let start = offset + UOFFSETT_SIZE; + let length = read_uoffset(self.buffer, offset) as usize; + Iterator::new(&self.buffer, start, length) } - /// TODO + /// Returns a value of `bool` at `offset`. pub fn get_bool(&self, offset: UOffsetT) -> bool { let pos = self.pos as usize; self.buffer[pos + offset as usize] == 1 } - /// TODO + /// Returns a value of `u8` at `offset`. pub fn get_u8(&self, offset: UOffsetT) -> u8 { let pos = self.pos as usize; self.buffer[pos + offset as usize] } - /// TODO + /// Returns a value of `i8` at `offset`. pub fn get_i8(&self, offset: UOffsetT) -> i8 { let pos = self.pos as usize; self.buffer[pos + offset as usize] as i8 } - /// TODO + /// Returns a value of `u16` at `offset`. pub fn get_u16(&self, offset: UOffsetT) -> u16 { let pos = self.pos as usize; LittleEndian::read_u16(&self.buffer[pos + offset as usize..]) } - /// TODO + /// Returns a value of `i16` at `offset`. pub fn get_i16(&self, offset: UOffsetT) -> i16 { let pos = self.pos as usize; LittleEndian::read_i16(&self.buffer[pos + offset as usize..]) } - /// TODO + /// Returns a value of `u32` at `offset`. pub fn get_u32(&self, offset: UOffsetT) -> u32 { let pos = self.pos as usize; LittleEndian::read_u32(&self.buffer[pos + offset as usize..]) } - /// TODO + /// Returns a value of `i32` at `offset`. pub fn get_i32(&self, offset: UOffsetT) -> i32 { let pos = self.pos as usize; LittleEndian::read_i32(&self.buffer[pos + offset as usize..]) } - /// TODO + /// Returns a value of `u64` at `offset`. pub fn get_u64(&self, offset: UOffsetT) -> u64 { let pos = self.pos as usize; LittleEndian::read_u64(&self.buffer[pos + offset as usize..]) } - /// TODO + /// Returns a value of `i64` at `offset`. pub fn get_i64(&self, offset: UOffsetT) -> i64 { let pos = self.pos as usize; LittleEndian::read_i64(&self.buffer[pos + offset as usize..]) } - /// TODO + /// Returns a value of `f32` at `offset`. pub fn get_f32(&self, offset: UOffsetT) -> f32 { let pos = self.pos as usize; LittleEndian::read_f32(&self.buffer[pos + offset as usize..]) } - /// TODO + /// Returns a value of `f64` at `offset`. pub fn get_f64(&self, offset: UOffsetT) -> f64 { let pos = self.pos as usize; LittleEndian::read_f64(&self.buffer[pos + offset as usize..]) } - /// TODO + /// Returns a value of `&str` at `offset`. pub fn get_str(&self, offset: UOffsetT) -> &str { use std::str; - let s = self.byte_vector(offset); + let mut offset = offset + self.pos as UOffsetT; + offset += read_uoffset(self.buffer, offset as usize); + let start = offset as usize + 4 as usize; + let length = read_uoffset(self.buffer, offset as usize) as usize; + let s = &self.buffer[start..start+length]; unsafe { str::from_utf8_unchecked(s) } } - /// Retrieve a struct table from offset. + /// Retrieve a struct table from offset. Offset should point to then + /// first usable byte of data i.e. the Vtable offset. pub fn get_struct>>(&self, offset: UOffsetT) -> T { let pos = self.pos as UOffsetT + offset; - let table = Table::with_pos(self.buffer, pos); + let table = Table::with_pos(self.buffer, pos as usize); table.into() } @@ -202,22 +341,48 @@ impl<'a> Table<'a> { self.pos as UOffsetT } - /// Reads an offset at exact position. + /// Reads an `UOffsetT` at exact position. pub fn read_uoffset(&self, offset: UOffsetT) -> UOffsetT { - read_uoffset(self.buffer, offset) + read_uoffset(self.buffer, offset as usize) + } + + /// Reads an `VOffsetT` at exact position. + pub fn read_voffset(&self, offset: UOffsetT) -> VOffsetT { + read_voffset(self.buffer, offset as usize) + } + + /// Retrieves the `VOffsetT` in the vtable `slot`. + /// If the vtable value is zero, the default value `d` will be returned. + pub fn read_voffset_slot(&self, slot: VOffsetT, d: VOffsetT) -> VOffsetT { + let offset = self.field_offset(slot); + if offset != 0 { + return offset as VOffsetT + } + d + } + + /// Get a reference to the raw buffer + #[inline] + pub fn get_bytes(&self) -> &[u8] { + self.buffer } } /// Read a Unsigned offset value at given offset -pub fn read_uoffset(buf: &[u8], offset: UOffsetT) -> UOffsetT { +pub fn read_uoffset(buf: &[u8], offset: usize) -> UOffsetT { LittleEndian::read_u32(&buf[offset as usize..]) } /// Read a Signed offset value at given offset -pub fn read_soffset(buf: &[u8], offset: UOffsetT) -> SOffsetT { +pub fn read_soffset(buf: &[u8], offset: usize) -> SOffsetT { LittleEndian::read_i32(&buf[offset as usize..]) } +/// Read a Signed offset value at given offset +pub fn read_voffset(buf: &[u8], offset: usize) -> VOffsetT { + LittleEndian::read_u16(&buf[offset as usize..]) +} + impl<'a> From<&'a [u8]> for Table<'a> { fn from(buf: &[u8]) -> Table { Table::from_offset(buf, 0) diff --git a/rust/src/types.rs b/rust/src/types.rs index 80f7ee26c4..5f903d2599 100644 --- a/rust/src/types.rs +++ b/rust/src/types.rs @@ -14,6 +14,7 @@ pub const VOFFSETT_SIZE: usize = 2; pub const UOFFSETT_SIZE: usize = 4; /// Number of metadata fields in a `VTable`. +/// Vtable Len and Object Size. pub const VTABLE_METADATA_FIEDS: usize = 2; /// Byte size of `Vtable` metadata. pub const VTABLE_METADATA_SIZE: usize = VTABLE_METADATA_FIEDS * VOFFSETT_SIZE; diff --git a/src/idl_gen_rust.cpp b/src/idl_gen_rust.cpp index 88e18d22a1..0cf532fb76 100644 --- a/src/idl_gen_rust.cpp +++ b/src/idl_gen_rust.cpp @@ -26,7 +26,7 @@ namespace flatbuffers { namespace rust { -static std::string GenGetter(const Type &type); + //static std::string GenGetter(const Type &type); static std::string GenMethod(const FieldDef &field); static void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr); @@ -46,26 +46,127 @@ static std::string ModName(std::string &def_name) { } // Begin by declaring namespace and imports. -static void BeginFile(const bool needs_imports, - std::string *code_ptr) { +static void BeginFile(std::string *code_ptr) { std::string &code = *code_ptr; code += "//! Automatically generated, do not modify.\n\n"; - if (needs_imports) { // the flatbuffers runtime lib code += "use flatbuffers;\n"; // definitions in the same namepsace code += "use super::*;\n\n"; - } } + static std::string MapConstant(const FieldDef &field) { + if ( (IsScalar(field.value.type.base_type)) + && (TypeName(field).compare("bool") == 0) ) { + if (field.value.constant == "0") { + return "false"; + } + return "true"; + } + return field.value.constant; + } + // Begin a table struct declaration. static void TableStructDefinition(const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; - code += "#[derive(Debug)]\n"; - code += "pub struct " + struct_def.name + "<'a> {\n"; - code += Indent + "table: flatbuffers::Table<'a>,\n"; - code += "}\n\n"; + if (!struct_def.fixed) { + code += "table_object!{" + struct_def.name; + code += ", 4"; //mmmm assuming type.base_type is UOFFSET + } else { + code += "struct_object!{" + struct_def.name; + code += ", " + NumToString(struct_def.bytesize); + } + code += ", ["; + bool first = true; + for (auto it = struct_def.fields.vec.begin(); + it != struct_def.fields.vec.end(); + ++it) { + auto &field = **it; + if (field.deprecated) continue; + if (first) { + code += "\n"; + first = false; + } else { + code += ", \n"; + } + //GenComment(field.doc_comment, code_ptr, nullptr, ""); + if ( (IsScalar(field.value.type.base_type)) + && !(field.value.type.enum_def)) { + code += Indent + "("; + code += field.name + ","; + code += "get_" + TypeName(field); + code += ", " + TypeName(field); + code += ", " + NumToString(field.value.offset); + code += ", " + MapConstant(field); + code += ")"; + continue; + } + if ( (IsScalar(field.value.type.base_type)) + && (field.value.type.enum_def) ) { + code += Indent + "("; + code += field.name + ","; + code += "simple_enum,"; + code += "get_" + TypeName(field); + code += ", " + TypeName(field); + if (field.value.type.enum_def->is_union) { + code += ", " + field.value.type.enum_def->name; + code += "Type"; + } else { + code += ", " + field.value.type.enum_def->name; + } + code += ", " + NumToString(field.value.offset); + code += ", " + MapConstant(field); + code += ")"; + continue; + } + switch (field.value.type.base_type) { + case BASE_TYPE_STRUCT: { + code += Indent + "("; + code += field.name + ","; + code += "get_struct"; + code += ", " + TypeName(field); + code += ", " + NumToString(field.value.offset); + code += ")"; + break; + } + case BASE_TYPE_STRING: { + code += Indent + "("; + code += field.name + ","; + code += "get_str"; + code += ", " + TypeName(field); + code += ", " + NumToString(field.value.offset); + code += ", " + MapConstant(field); + code += ")"; + break; + } + case BASE_TYPE_VECTOR: { + code += Indent + "("; + code += field.name + ","; + code += "vector"; + code += ", " + TypeName(field); + code += ", " + NumToString(field.value.offset); + code += ")"; + break; + break; + } + case BASE_TYPE_UNION: + code += Indent + "("; + code += field.name + ","; + code += "union,"; + code += field.name + "_type"; + code += ", " + TypeName(field); + code += ", " + field.value.type.enum_def->name; + code += ", " + NumToString(field.value.offset); + code += ", " + MapConstant(field); + code += ")"; + break; + default: + assert(0); + } + } + code += "]}\n\n"; + } std::string GenFieldOffsetName(const FieldDef &field, @@ -79,251 +180,6 @@ std::string GenFieldOffsetName(const FieldDef &field, } } -// Vtable Enum defintion -static void VtableDefinition(const StructDef &struct_def, - std::string *code_ptr) { - std::string &code = *code_ptr; - if (struct_def.fields.vec.size() > 0) { - code += "enum VT {\n"; - for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); - ++it) { - auto &field = **it; - if (!field.deprecated) { // Deprecated fields won't be accessible. - code += Indent + GenFieldOffsetName(field, false) + " = "; - code += NumToString(field.value.offset); - code += ","; - if (field.padding) { - code += "// Padding" + NumToString(field.padding) + "\n"; - } else { - code += "\n"; - } - } - } - code += "}\n\n"; - } -} - -// Start Table Struct implimentation functions -static void BeginTableImpl(const StructDef &struct_def, - std::string *code_ptr) { - std::string &code = *code_ptr; - code += "impl<'a> " + struct_def.name + "<'a> {\n"; -} - -// End Struct implimentation functions -static void EndImpl(std::string *code_ptr) { - std::string &code = *code_ptr; - code += "}\n\n"; -} - -// A single enum member definition -static void EnumUnionMember(const EnumVal ev, std::string *code_ptr) { - std::string &code = *code_ptr; - code += Indent; - if (ev.name.compare("NONE") == 0) { - code += "None,\n"; - } else { - // TODO dont assume table - code += ev.name + "(" +ev.name + "<'a>),\n"; - } -} - -// A wrapper aroudn a union Enum to use as a return type in accessor -// functions -static void EnumUnionImpl(const EnumDef &enum_def, std::string *code_ptr) { - std::string &code = *code_ptr; - std::string uname = enum_def.name + "Union"; - code += "#[derive(Debug)]\n"; - code += "pub enum " + uname + "<'a> {\n"; - for (auto it = enum_def.vals.vec.begin(); - it != enum_def.vals.vec.end(); - ++it) { - auto &ev = **it; - EnumUnionMember(ev, code_ptr); - } - code += "}\n\n"; - code += "impl<'a> " + enum_def.name + "Union<'a> {\n"; - code += Indent + "pub fn from_type("; - code += "table: &'a flatbuffers::Table, t: "; - code += enum_def.name + ", offset: usize) -> "; - code += enum_def.name + "Union<'a> {\n"; - code += Indent + Indent + "match t {\n"; - for (auto it = enum_def.vals.vec.begin(); - it != enum_def.vals.vec.end(); - ++it) { - auto &ev = **it; - code += Indent + Indent + Indent; - if (ev.name.compare("NONE") == 0) { - code += enum_def.name + "::NONE => {\n"; - code += Indent + Indent + Indent + Indent; - code += uname + "::None\n"; - code += Indent + Indent + Indent; - code +="}\n"; - } else { - code += enum_def.name +"::" + ev.name; - code += " => {\n"; - code += Indent + Indent + Indent +Indent; - code += uname + "::" + ev.name +"("; - code += "table.get_root(offset as u32).into()"; - code += ")\n"; - code += Indent + Indent + Indent; - code += "}\n"; - } - } - code += Indent + Indent + "}\n"; - code += Indent + "}\n"; - code += "}\n\n"; -} - - -// Begin enum code with a class declaration. -static void BeginEnum(const EnumDef &enum_def, std::string *code_ptr) { - std::string &code = *code_ptr; - code += "#[derive(PartialEq, Eq, Clone, Debug, Hash)]\n"; - code += "#[repr(" + GenTypeGet(enum_def.underlying_type) + ")]\n"; - code += "pub enum " + enum_def.name + " {\n"; -} - -// A single enum member definition -static void EnumMember(const EnumVal ev, std::string *code_ptr) { - std::string &code = *code_ptr; - code += Indent; - code += ev.name; - code += " = " + NumToString(ev.value) + ",\n"; -} - -// A single enum member match on value return type -static void EnumValueMatch(const std::string class_name, - const EnumVal ev, std::string *code_ptr) { - std::string &code = *code_ptr; - code += Indent + Indent + Indent; - code += NumToString(ev.value) + " => " ; - code += class_name + "::" + ev.name+ ",\n"; -} - - // A single enum member match on type return name -static void EnumNameMatch(const std::string class_name, - const EnumVal ev, std::string *code_ptr) { - std::string &code = *code_ptr; - code += Indent + Indent + Indent; - code += class_name + "::" + ev.name; - code += " => \"" + ev.name + "\",\n"; -} - -// Const to list all Enum variants -static void EnumConst(const EnumDef &enum_def, std::string *code_ptr) { - std::string &code = *code_ptr; - std::string uname = enum_def.name; - std::transform(uname.begin(), uname.end(), uname.begin(), ::toupper); - code += "/// A List of all `"+ enum_def.name + "` enum variants.\n"; - code += "pub const " + uname + "_LIST: ["; - code += enum_def.name + ";" + NumToString(enum_def.vals.vec.size()); - code += "] = ["; - for (auto it = enum_def.vals.vec.begin(); - it != enum_def.vals.vec.end(); - ++it) { - auto &ev = **it; - code += enum_def.name + "::" + ev.name + ","; - } - code += "];\n\n"; -} - -// Impl for Enum -static void EnumImpl(const EnumDef &enum_def, std::string *code_ptr) { - EnumConst(enum_def, code_ptr); - std::string &code = *code_ptr; - code += "impl " + enum_def.name + " {\n"; - code += Indent; - code += "/// Returns a `str` representation of a `"+ enum_def.name; - code += "` enum.\n"; - code += Indent + "pub fn name(&self) -> &'static str {\n"; - code += Indent + Indent; - code += "match *self {\n"; - for (auto it = enum_def.vals.vec.begin(); - it != enum_def.vals.vec.end(); - ++it) { - auto &ev = **it; - EnumNameMatch(enum_def.name, ev, code_ptr); - } - code += Indent + Indent + "}\n"; - code += Indent + "}\n"; - code += "}\n\n"; -} - -// Enum Impl for From trait -static void EnumFromImpl(const EnumDef &enum_def, std::string *code_ptr) { - std::string &code = *code_ptr; - code += "impl From<"; - code += GenTypeGet(enum_def.underlying_type); - code += "> for " + enum_def.name + " {\n"; - code += Indent + "fn from(value: "; - code += GenTypeGet(enum_def.underlying_type); - code += ") -> " + enum_def.name; - code += " {\n"; - code += Indent + Indent; - code += "match value {\n"; - for (auto it = enum_def.vals.vec.begin(); - it != enum_def.vals.vec.end(); - ++it) { - auto &ev = **it; - EnumValueMatch(enum_def.name, ev, code_ptr); - } - code += Indent + Indent + Indent; - code += "_ => unreachable!(\"Unable to create a `" + enum_def.name; - code += "` from value {} \", value),\n"; - code += Indent + Indent + "}\n"; - code += Indent + "}\n"; - code += "}\n\n"; -} - -// Enum Impl for From trait -// static void EnumFromRefImpl(const EnumDef &enum_def, std::string *code_ptr) { -// std::string &code = *code_ptr; -// code += "impl<'a> From<&'a "; -// code += GenTypeGet(enum_def.underlying_type); -// code += "> for &'a " + enum_def.name + " {\n"; -// code += Indent + "fn from(value: &"; -// code += GenTypeGet(enum_def.underlying_type); -// code += ") -> &" + enum_def.name; -// code += " {\n"; -// code += Indent + Indent; -// code += "unsafe {\n"; -// code += Indent + Indent + Indent; -// code += "use std::mem;\n"; -// code += Indent + Indent + Indent; -// code += "mem::transmute(value)\n"; -// code += Indent + Indent + "}\n"; -// code += Indent + "}\n"; -// code += "}\n\n"; -// } - - -// End enum code. -static void EndEnum(std::string *code_ptr) { - std::string &code = *code_ptr; - code += "}\n\n"; -} - -// Initialize a new struct or table from existing data. -static void NewRootTypeFromBuffer(const StructDef &struct_def, - std::string *code_ptr) { - std::string &code = *code_ptr; - code += Indent + "pub fn new"; - code += "(buf: &[u8], offset: flatbuffers::UOffsetT) -> "; - code += struct_def.name + " {\n"; - code += Indent + Indent; - code += struct_def.name + " {\n"; - code += Indent + Indent + Indent; - if (struct_def.fixed) { - code += "table: flatbuffers::Table::with_pos(buf, offset),\n"; - } else { - code += "table: flatbuffers::Table::from_offset(buf, offset),\n"; - } - code += Indent + Indent + "}\n"; - code += Indent + "}\n\n"; -} - // Most field accessors need to retrieve and test the field offset first, // this is the prefix code for that. std::string OffsetPrefix(const FieldDef &field) { @@ -333,206 +189,24 @@ std::string OffsetPrefix(const FieldDef &field) { " as u16);\n" + Indent + Indent + "if offset != 0 {\n"; } -//Get the value of a struct's scalar. -static void GetScalarFieldOfStruct(const FieldDef &field, - std::string *code_ptr) { - std::string &code = *code_ptr; - std::string getter = GenGetter(field.value.type); - std::string unsigned_type = TypeName(field); - bool is_enum = false; - if (field.value.type.enum_def) { - is_enum = true; - } - code += Indent + "pub fn "; - code += field.name + "(&self) -> "; - if (is_enum) { - code += field.value.type.enum_def->name; - } else { - code += TypeName(field); - } - code += " {\n"; - code += Indent + Indent; - code += "let offset = "; - code += GenFieldOffsetName(field, true) + " as u32;\n"; - code += Indent + Indent; - code += "return " + getter + "offset)"; - if (is_enum) { - code += ".into()"; - } - code += "\n"; - code += Indent + "}\n\n"; -} - -static std::string MapConstant(const FieldDef &field) { - if ( (IsScalar(field.value.type.base_type)) - && (TypeName(field).compare("bool") == 0) ) { - if (field.value.constant == "0") { - return "false"; - } - return "true"; - } - return field.value.constant; -} - -// Get the value of a table's scalar. -static void GetScalarFieldOfTable(const FieldDef &field, - std::string *code_ptr) { - std::string &code = *code_ptr; - std::string getter = GenGetter(field.value.type); - bool is_enum = false; - if (field.value.type.enum_def) { - is_enum = true; - } - code += Indent + "pub fn "; - code += field.name + "(&self) -> "; - if (is_enum) { - code += field.value.type.enum_def->name; - } else { - code += TypeName(field); - } - code += " {\n"; - code += OffsetPrefix(field); - code += Indent + Indent + Indent + "return " + getter; - code += "offset)"; - if (is_enum) { - code += ".into()"; - } - code += "\n"; - code += Indent + Indent + "}\n"; - code += Indent + Indent + MapConstant(field); - if (is_enum) { - code += ".into()"; - } - code += "\n" +Indent + "}\n\n"; -} - -// Get a struct by initializing an existing struct. -// Specific to Struct. -static void GetStructFieldOfStruct(const FieldDef &field, - std::string *code_ptr) { +// Begin the creator function signature. +static void BeginBuilderArgs(const StructDef &struct_def, + std::string *code_ptr) { std::string &code = *code_ptr; - code += Indent + "pub fn " + field.name; - code += "(&self) -> "+ TypeName(field) +" {\n"; - code += Indent + Indent; - code += "let offset = " + GenFieldOffsetName(field, true); - code += " as u32;\n"; - code += Indent + Indent + " return self.table.get_struct"; - code += "::<" + TypeName(field) + ">"; - code += "(offset)\n"; - code += Indent + "}\n\n"; + std::string lname = struct_def.name; + std::transform(lname.begin(), lname.end(), lname.begin(), ::tolower); + code += Indent + "fn build_" + lname; + code += "(&mut self"; } -// Get a struct by initializing an existing struct. -// Specific to Table. -static void GetStructFieldOfTable(const FieldDef &field, +static void BeginBuilderTraitArgs(const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; - code += Indent + "pub fn " + field.name; - code += "(&self) -> Option<"+ TypeName(field) + "> {\n"; - code += OffsetPrefix(field); - if (field.value.type.struct_def->fixed) { - /// struct stored inli - code += Indent + Indent + Indent + " return Some(self.table.get_struct"; - code += "::<" + TypeName(field) + ">"; - code += "(offset))\n"; - } else { - code += Indent + Indent + Indent; - code += "return Some(self.table.get_indirect_root(offset).into())\n"; - } - code += Indent + Indent + "};\n"; - code += Indent + Indent + "None\n"; - code += Indent + "}\n\n"; -} - -// Get the value of a string. -static void GetStringField(const FieldDef &field, - std::string *code_ptr) { - std::string &code = *code_ptr; - code += Indent + "pub fn " + field.name; - code += "(&self) -> &str {\n"; - code += OffsetPrefix(field); - code += Indent + Indent + Indent + "return " + GenGetter(field.value.type); - code += "offset)\n"; - code += Indent + Indent + "}\n"; - code += Indent + Indent + "\"\"\n"; - code += Indent + "}\n\n"; -} - -// Get the value of a union from an object. -static void GetUnionField(const FieldDef &field, - std::string *code_ptr) { - std::string &code = *code_ptr; - code += Indent + "pub fn " + field.name; - code += "(&self) -> "; - code += TypeName(field) + " {\n"; - code += OffsetPrefix(field); - code += Indent + Indent + Indent + "let t = self."; - code += field.name +"_type();\n"; - code += Indent + Indent + Indent; - code += Indent + Indent + Indent + "return "; - code += TypeName(field) + "::from_type(&self.table"; - code += ", t, offset as usize);\n"; - code += Indent + Indent + "}\n"; - code += Indent +Indent + TypeName(field) + "::None\n"; - code += Indent + "}\n\n"; -} - -// Get the value of a vector's struct member. -static void GetMemberOfVectorOfStruct(const FieldDef &field, - std::string *code_ptr) { - std::string &code = *code_ptr; - auto vectortype = field.value.type.VectorType(); - code += Indent + "pub fn " + field.name; - code += "(&self) -> flatbuffers::Iterator<"; - code += TypeName(field) + "> {\n"; - code += OffsetPrefix(field); - code += Indent + Indent + Indent; - if (!(vectortype.struct_def->fixed)) { - code += "return self.table"; - code += ".table_vector(offset)\n"; - } else { - code += "return self.table"; - code += ".struct_vector(offset)\n"; - } - code += Indent + Indent + "}\n"; - code += Indent +Indent + "flatbuffers::empty_iterator(&self.table)\n"; - code += Indent + "}\n\n"; -} - -// Get the value of a vector's non-struct member. -static void GetMemberOfVectorOfNonStruct(const FieldDef &field, - std::string *code_ptr) { - std::string &code = *code_ptr; - code += Indent + "pub fn " + field.name; - if (field.value.type.VectorType().base_type == BASE_TYPE_STRING) { - code += "(&self) -> flatbuffers::Iterator<"; - code += TypeName(field) + "> {\n"; - } else { - code += "(&self) -> &["; - code += TypeName(field) + "] {\n"; - } - - code += OffsetPrefix(field); - code += Indent + Indent + Indent; - code += "return " + GenGetter(field.value.type); - code += "offset);\n"; - code += Indent + Indent + "}\n"; - if (field.value.type.VectorType().base_type == BASE_TYPE_STRING) { - code += Indent + Indent + "flatbuffers::empty_iterator(&self.table)"; - } else { - code += Indent +Indent + "&[]\n"; - } - code += Indent + "}\n\n"; -} - -// Begin the creator function signature. -static void BeginBuilderArgs(const StructDef &struct_def, - std::string *code_ptr) { - std::string &code = *code_ptr; std::string lname = struct_def.name; std::transform(lname.begin(), lname.end(), lname.begin(), ::tolower); - code += "pub fn build_" + lname; - code += "(builder: &mut flatbuffers::Builder"; + code += "pub trait " + struct_def.name + "Builder {\n"; + code += Indent + "fn build_" + lname; + code += "(&mut self"; } // Recursively generate arguments for a constructor, to deal with nested @@ -569,26 +243,35 @@ static void EndBuilderArgs(std::string *code_ptr) { code += ") -> flatbuffers::UOffsetT {\n"; } +// End the creator function signature. +static void EndBuilderTraitArgs(const StructDef &struct_def, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += ") -> flatbuffers::UOffsetT;\n"; + code += "}\n\n"; + code += "impl " + struct_def.name + "Builder for flatbuffers::Builder {\n"; +} + // Recursively generate struct construction statements and instert manual // padding. static void StructBuilderBody(const StructDef &struct_def, const char *nameprefix, std::string *code_ptr) { std::string &code = *code_ptr; - code += " builder.prep(" + NumToString(struct_def.minalign) + ", "; + code += Indent + Indent + "self.prep(" + NumToString(struct_def.minalign) + ", "; code += NumToString(struct_def.bytesize) + ");\n"; for (auto it = struct_def.fields.vec.rbegin(); it != struct_def.fields.vec.rend(); ++it) { auto &field = **it; if (field.padding) - code += " builder.pad(" + NumToString(field.padding) + ");\n"; + code += Indent + Indent + "self.pad(" + NumToString(field.padding) + ");\n"; if (IsStruct(field.value.type)) { StructBuilderBody(*field.value.type.struct_def, (nameprefix + (field.name + "_")).c_str(), code_ptr); } else { - code += " builder.add_" + GenMethod(field) + "("; + code += Indent + Indent + "self.add_" + GenMethod(field) + "("; code += nameprefix + field.name + ");\n"; } } @@ -597,65 +280,46 @@ static void StructBuilderBody(const StructDef &struct_def, // End the builder function static void EndBuilderBody(std::string *code_ptr) { std::string &code = *code_ptr; - code += " builder.offset() as flatbuffers::UOffsetT \n"; - code += "}\n"; -} - -// Init functions for the table Builder object -static void GenTableBuilderInitFn(std::string *code_ptr) { - std::string &code = *code_ptr; - code += Indent + "/// Create a new builder.\n"; - code += Indent + "pub fn with_capacity(size: usize) -> Self {\n"; - code += Indent + Indent + "Builder {\n"; - code += Indent + Indent + Indent + "inner: flatbuffers"; - code += "::Builder::with_capacity(size),\n"; - code += Indent + Indent + "}\n"; - code += Indent + "}\n\n"; -} - - // Add Default, From, Into and ObjectBuilder traits. -static void GenTableBuilderBoilerPlate(std::string *code_ptr) { - std::string &code = *code_ptr; - // Default - code += "impl Default for Builder {\n"; - code += Indent + "fn default() -> Builder {\n"; - code += Indent + Indent +"Builder::with_capacity(1024)\n"; - code += Indent +"}\n"; - code += "}\n\n"; - // From - code += "impl From for Builder {\n"; - code += Indent + "fn from(b: flatbuffers::Builder) -> Builder {\n"; - code += Indent + Indent +"Builder {\n"; - code += Indent + Indent + Indent + "inner: b,\n"; - code += Indent + Indent + "}\n"; - code += Indent +"}\n"; - code += "}\n\n"; - // Into - code += "impl Into for Builder {\n"; - code += Indent + "fn into(self) -> flatbuffers::Builder {\n"; - code += Indent + Indent +"self.inner\n"; - code += Indent +"}\n"; + code += Indent + Indent +"self.offset() as flatbuffers::UOffsetT \n"; + code += Indent + "}\n"; code += "}\n\n"; - // ObjectBuilder - code += "impl flatbuffers::ObjectBuilder for Builder {}\n\n"; } // Get the value of a table's starting offset. static void GetStartOfTable(const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; + std::string lname = struct_def.name; + std::transform(lname.begin(), lname.end(), lname.begin(), ::tolower); code += Indent; - code += "/// Initialize a new `Builder` for a `"; - code += struct_def.name + "` table.\n"; - code += Indent; - code += "pub fn start(&mut self) {\n"; + code += "fn start_" + lname + "(&mut self) {\n"; code += Indent + Indent; - code += "self.inner.start_object("; + code += "self.start_object("; code += NumToString(struct_def.fields.vec.size()); code += ");\n"; code += Indent + "}\n\n"; } +static void BuildFieldOfTableDef(const StructDef &struct_def, + const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + std::string lname = struct_def.name; + std::transform(lname.begin(), lname.end(), lname.begin(), ::tolower); + code += Indent; + code += "/// Set the value for field `" + field.name + "`.\n"; + code += Indent; + code += "fn add_" + field.name; + code += "(&mut self, "; + code += field.name + ": "; + if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) { + code += "flatbuffers::UOffsetT"; + } else { + code += GenTypeBasic(field.value.type); + } + code += ");\n"; +} + // Set the value of a table's field. static void BuildFieldOfTable(const StructDef &struct_def, const FieldDef &field, @@ -665,9 +329,7 @@ static void BuildFieldOfTable(const StructDef &struct_def, std::string lname = struct_def.name; std::transform(lname.begin(), lname.end(), lname.begin(), ::tolower); code += Indent; - code += "/// Set the value for field `" + field.name + "`.\n"; - code += Indent; - code += "pub fn add_" + field.name; + code += "fn add_" + field.name; code += "(&mut self, "; code += field.name + ": "; if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) { @@ -677,7 +339,7 @@ static void BuildFieldOfTable(const StructDef &struct_def, } code += ") {\n"; code += Indent + Indent; - code += "self.inner.add_slot_"; + code += "self.add_slot_"; code += GenMethod(field) + "("; code += NumToString(offset) + ", "; code += field.name; @@ -686,6 +348,21 @@ static void BuildFieldOfTable(const StructDef &struct_def, code += Indent + "}\n\n"; } +// Set the value of one of the members of a table's vector. +static void BuildVectorOfTableDef(const FieldDef &field, + std::string *code_ptr) { + std::string &code = *code_ptr; + code += Indent; + code += "/// Initializes bookkeeping for writing a new `"; + code += field.name + "` vector.\n"; + code += Indent; + code += "fn start_"; + code += field.name; + code += "_vector(&mut self, numElems: usize);\n"; +} + + + // Set the value of one of the members of a table's vector. static void BuildVectorOfTable(const FieldDef &field, std::string *code_ptr) { @@ -694,11 +371,11 @@ static void BuildVectorOfTable(const FieldDef &field, code += "/// Initializes bookkeeping for writing a new `"; code += field.name + "` vector.\n"; code += Indent; - code += "pub fn start_"; + code += "fn start_"; code += field.name; code += "_vector(&mut self, numElems: usize) {\n"; code += Indent + Indent; - code += "self.inner.start_vector("; + code += "self.start_vector("; auto vector_type = field.value.type.VectorType(); auto alignment = InlineAlignment(vector_type); auto elem_size = InlineSize(vector_type); @@ -708,259 +385,40 @@ static void BuildVectorOfTable(const FieldDef &field, code += Indent + "}\n\n"; } -// Get the offset of the end of a table. -static void GenEndOfTable(std::string *code_ptr) { - std::string &code = *code_ptr; - code += Indent; - code += "/// Finalize the current object and return the offset.\n"; - code += Indent; - code += "pub fn end"; - code += "(&mut self) -> flatbuffers::UOffsetT {\n"; - code += Indent + Indent + "return self.inner.end_object()\n"; - code += Indent + "}\n\n"; -} - -// Get the offset of the end of a table. -static void GenFinishOnTable(std::string *code_ptr) { - std::string &code = *code_ptr; - code += Indent; - code += "/// Finish the buffer.\n"; - code += Indent; - code += "pub fn finish"; - code += "(&mut self, r: flatbuffers::UOffsetT) {\n"; - code += Indent + Indent + "return self.inner.finish(r)\n"; - code += Indent + "}\n\n"; -} - -// Generic builder functions. -// This table builder wraps an inner flatbuffers:Builder -// so these are conveniance functions that delegate to the -// inner builder -static void GenBuilderFns(std::string *code_ptr) { - std::string &code = *code_ptr; - std::string inner = "self.inner."; - code += Indent; - code += "pub fn create_string(&mut self, v: &str) -> flatbuffers::UOffsetT { "; - code += inner +"create_string(v) }\n"; - code += Indent; - code += "pub fn get_bytes(&self) -> &[u8] { "; - code += inner +"get_bytes() }\n"; - code += Indent; - code += "pub fn len(&self) -> usize { "; - code += inner +"len() }\n"; - code += Indent; - code += "pub fn offset(&self) -> usize { "; - code += inner +"offset() }\n"; - code += Indent; - code += "pub fn reset(&mut self) { "; - code += inner +"reset() }\n"; - code += Indent; - code += "pub fn prep(&mut self, s:usize, a: usize) { "; - code += inner +"prep(s,a) }\n"; - code += Indent; - code += "pub fn pad(&mut self, n:usize) { "; - code += inner +"pad(n) }\n"; - code += Indent; - code += "pub fn end_vector(&mut self) -> flatbuffers::UOffsetT { "; - code += inner +"end_vector() }\n"; - - code += Indent; - code += "pub fn add_bool(&mut self, v:bool) { "; - code += inner +"add_bool(v) }\n"; - code += Indent; - code += "pub fn add_u8(&mut self, v:u8) { "; - code += inner +"add_u8(v) }\n"; - code += Indent; - code += "pub fn add_i8(&mut self, v:i8) { "; - code += inner +"add_i8(v) }\n"; - code += Indent; - code += "pub fn add_u16(&mut self, v:u16) { "; - code += inner +"add_u16(v) }\n"; - code += Indent; - code += "pub fn add_i16(&mut self, v:i16) { "; - code += inner +"add_i16(v) }\n"; - code += Indent; - code += "pub fn add_u32(&mut self, v:u32) { "; - code += inner +"add_u32(v) }\n"; - code += Indent; - code += "pub fn add_i32(&mut self, v:i32) { "; - code += inner +"add_i32(v) }\n"; - code += Indent; - code += "pub fn add_u64(&mut self, v:u64) { "; - code += inner +"add_u64(v) }\n"; - code += Indent; - code += "pub fn add_i64(&mut self, v:i64) { "; - code += inner +"add_i64(v) }\n"; - code += Indent; - code += "pub fn add_f32(&mut self, v:f32) { "; - code += inner +"add_f32(v) }\n"; - code += Indent; - code += "pub fn add_f64(&mut self, v:f64) { "; - code += inner +"add_f64(v) }\n"; - code += Indent; - code += "pub fn add_uoffset(&mut self, v: flatbuffers::UOffsetT) { "; - code += inner +"add_uoffset(v) }\n"; - - code += Indent; - code += "pub fn add_slot_bool(&mut self, o: usize, v: bool, d: bool) { "; - code += inner +"add_slot_bool(o,v,d) }\n"; - code += Indent; - code += "pub fn add_slot_u8(&mut self, o: usize, v: u8, d: u8) { "; - code += inner +"add_slot_u8(o,v,d) }\n"; - code += Indent; - code += "pub fn add_slot_i8(&mut self, o: usize, v: i8, d: i8) { "; - code += inner +"add_slot_i8(o,v,d) }\n"; - code += Indent; - code += "pub fn add_slot_u16(&mut self, o: usize, v: u16, d: u16) { "; - code += inner +"add_slot_u16(o,v,d) }\n"; - code += Indent; - code += "pub fn add_slot_i16(&mut self, o: usize, v: i16, d: i16) { "; - code += inner +"add_slot_i16(o,v,d) }\n"; - code += Indent; - code += "pub fn add_slot_i32(&mut self, o: usize, v: i32, d: i32) { "; - code += inner +"add_slot_i32(o,v,d) }\n"; - code += Indent; - code += "pub fn add_slot_u32(&mut self, o: usize, v: u32, d: u32) { "; - code += inner +"add_slot_u32(o,v,d) }\n"; - code += Indent; - code += "pub fn add_slot_u64(&mut self, o: usize, v: u64, d: u64) { "; - code += inner +"add_slot_u64(o,v,d) }\n"; - code += Indent; - code += "pub fn add_slot_i64(&mut self, o: usize, v: i64, d: i64) { "; - code += inner +"add_slot_i64(o,v,d) }\n"; - code += Indent; - code += "pub fn add_slot_f32(&mut self, o: usize, v: f32, d: f32) { "; - code += inner +"add_slot_f32(o,v,d) }\n"; - code += Indent; - code += "pub fn add_slot_f64(&mut self, o: usize, v: f64, d: f64) { "; - code += inner +"add_slot_f64(o,v,d) }\n"; - code += Indent; - code += "pub fn add_slot_uoffset(&mut self, o: usize, v: "; - code += "flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { "; - code += inner +"add_slot_uoffset(o,v,d) }\n"; - code += Indent; - code += "pub fn add_slot_struct(&mut self, o: usize, v: "; - code += "flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { "; - code += inner +"add_slot_struct(o,v,d) }\n"; -} - -// Generate a struct field, conditioned on its child type(s). -static void GenStructAccessor(const StructDef &struct_def, - const FieldDef &field, - std::string *code_ptr) { - GenComment(field.doc_comment, code_ptr, nullptr, Indent.c_str()); - if (IsScalar(field.value.type.base_type)) { - if (struct_def.fixed) { - GetScalarFieldOfStruct(field, code_ptr); - } else { - GetScalarFieldOfTable(field, code_ptr); - } - } else { - switch (field.value.type.base_type) { - case BASE_TYPE_STRUCT: - if (struct_def.fixed) { - GetStructFieldOfStruct(field, code_ptr); - } else { - GetStructFieldOfTable(field, code_ptr); - } - break; - case BASE_TYPE_STRING: - GetStringField(field, code_ptr); - break; - case BASE_TYPE_VECTOR: { - auto vectortype = field.value.type.VectorType(); - if (vectortype.base_type == BASE_TYPE_STRUCT) { - GetMemberOfVectorOfStruct(field, code_ptr); - } else { - GetMemberOfVectorOfNonStruct(field, code_ptr); - } - break; - } - case BASE_TYPE_UNION: - GetUnionField(field, code_ptr); - break; - default: - assert(0); - } - } -} - // Generate table constructors, conditioned on its members' types. static void GenTableBuilderStructImpl(const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; - code += "/// Builder Object for `"+ struct_def.name + "` tables.\n"; - code += "pub struct Builder {\n"; - code += Indent + "inner: flatbuffers::Builder,\n"; - code += "}\n\n"; - code += "impl Builder {\n"; -} - -// Generate table constructors, conditioned on its members' types. -static void GenEndTableBuilderStructImpl(std::string *code_ptr) { - std::string &code = *code_ptr; - code += "}\n\n"; -} - -// Build helper functions for simple fixed structs -static void GenTableBuilderFxedFnImpl(const StructDef &struct_def, - std::string *code_ptr) { - std::string &code = *code_ptr; - std::string oname = struct_def.name; std::string lname = struct_def.name; - std::transform(lname.begin(), lname.end(), - lname.begin(), ::tolower); - code += Indent + "pub fn build_" + lname + "(&mut self "; - StructBuilderArgs(struct_def, "", code_ptr); - code += ") -> flatbuffers::UOffsetT {\n"; - code += Indent + Indent + ModName(oname) + "::build_"; - code += lname + "(&mut self.inner"; - StructBuilderArgs(struct_def, "", code_ptr, true); - code += ")\n"; - code += Indent + "}\n\n"; -} - - - -// Build helper functions for simple fixed structs -static void GenTableBuilderFxedFns(const StructDef &struct_def, - std::string *code_ptr) { - std::set generated; + std::transform(lname.begin(), lname.end(), lname.begin(), ::tolower); + code += "/// Builder Trait for `"+ struct_def.name + "` tables.\n"; + code += "pub trait " + struct_def.name + "Builder {\n"; + code += Indent + "fn start_"+lname+ "(&mut self);\n"; for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { auto &field = **it; if (field.deprecated) continue; + BuildFieldOfTableDef(struct_def, field, code_ptr); if (field.value.type.base_type == BASE_TYPE_VECTOR) { - if (field.value.type.element == BASE_TYPE_STRUCT) { - if (field.value.type.struct_def->fixed) { - std::string id = field.value.type.struct_def->name; - auto result_1 = generated.insert(id); - if (result_1.second) { - GenTableBuilderFxedFnImpl(*field.value.type.struct_def, code_ptr); - } - } - } - } - if (field.value.type.base_type == BASE_TYPE_STRUCT) { - if (field.value.type.struct_def->fixed) { - std::string id = field.value.type.struct_def->name; - auto result_1 = generated.insert(id); - if (result_1.second) { - GenTableBuilderFxedFnImpl(*field.value.type.struct_def, code_ptr); - } - } + BuildVectorOfTableDef(field, code_ptr); } } + code += "}\n\n"; + + code += "impl " + struct_def.name + "Builder for flatbuffers::Builder {\n"; } +// Generate table constructors, conditioned on its members' types. +static void GenEndTableBuilderStructImpl(std::string *code_ptr) { + std::string &code = *code_ptr; + code += "}\n\n";} + // Generate table constructors, conditioned on its members' types. static void GenTableBuilders(const StructDef &struct_def, std::string *code_ptr) { GenTableBuilderStructImpl(struct_def, code_ptr); - GenTableBuilderInitFn(code_ptr); GetStartOfTable(struct_def, code_ptr); - GenEndOfTable(code_ptr); for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); ++it) { @@ -973,52 +431,18 @@ static void GenTableBuilders(const StructDef &struct_def, BuildVectorOfTable(field, code_ptr); } } - GenTableBuilderFxedFns(struct_def, code_ptr); - GenFinishOnTable(code_ptr); - GenBuilderFns(code_ptr); + //GenTableBuilderFxedFns(struct_def, code_ptr); GenEndTableBuilderStructImpl(code_ptr); - GenTableBuilderBoilerPlate(code_ptr); } -// Generate a From<&framebuffer:Table> impl -static void GenTableFromImpl(const StructDef &struct_def, - std::string *code_ptr) { - std::string &code = *code_ptr; - code += "impl<'a> From> for "; - code += struct_def.name + "<'a> {\n"; - code += Indent + "fn from(table: flatbuffers::Table) -> "; - code += struct_def.name + " {\n"; - code += Indent + Indent + struct_def.name + "{\n"; - code += Indent + Indent + Indent + "table: table,\n"; - code += Indent + Indent + "}\n"; - code += Indent + "}\n"; - code += "}\n\n"; - } - // Generate struct or table methods. static void GenStruct(const StructDef &struct_def, std::string *code_ptr) { if (struct_def.generated) return; GenComment(struct_def.doc_comment, code_ptr, nullptr); - + TableStructDefinition(struct_def, code_ptr); - VtableDefinition(struct_def, code_ptr); - BeginTableImpl(struct_def, code_ptr); - NewRootTypeFromBuffer(struct_def, code_ptr); - // Generate the Init method that sets the field in a pre-existing - // accessor object. This is to allow object reuse. - //InitializeExisting(struct_def, code_ptr); - - for (auto it = struct_def.fields.vec.begin(); - it != struct_def.fields.vec.end(); - ++it) { - auto &field = **it; - if (field.deprecated) continue; - GenStructAccessor(struct_def, field, code_ptr); - } - EndImpl(code_ptr); - GenTableFromImpl(struct_def, code_ptr); - + if (struct_def.fixed) { // create a struct constructor function GenStructBuilder(struct_def, code_ptr); @@ -1031,44 +455,42 @@ static void GenStruct(const StructDef &struct_def, // Generate enum declarations. static void GenEnum(const EnumDef &enum_def, std::string *code_ptr) { if (enum_def.generated) return; - + std::string &code = *code_ptr; GenComment(enum_def.doc_comment, code_ptr, nullptr); - BeginEnum(enum_def, code_ptr); + if (enum_def.is_union) { + code += "union!{" + enum_def.name +","; + code += enum_def.name + "Type,"; + } else { + code += "simple_enum!{" + enum_def.name +","; + } + code += GenTypeGet(enum_def.underlying_type); + code += ", ["; + bool first = true; for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); ++it) { auto &ev = **it; - GenComment(ev.doc_comment, code_ptr, nullptr, Indent.c_str()); - EnumMember(ev, code_ptr); - } - EndEnum(code_ptr); - EnumImpl(enum_def, code_ptr); - EnumFromImpl(enum_def, code_ptr); - if (enum_def.is_union) { - EnumUnionImpl(enum_def, code_ptr); - } -} - -// Returns the function name that is able to read a value of the given type. -static std::string GenGetter(const Type &type) { - switch (type.base_type) { - case BASE_TYPE_STRING: return "self.table.get_str("; - case BASE_TYPE_UNION: return "let obj = self.table \ - .get_union::<"+ type.enum_def->name + ">("; - case BASE_TYPE_VECTOR: - if (type.VectorType().base_type == BASE_TYPE_STRING) { - return "self.table.str_vector("; - } else if (type.VectorType().base_type==BASE_TYPE_UCHAR) { - return "self.table.byte_vector("; - } else if (type.VectorType().base_type==BASE_TYPE_BOOL) { - return "self.table.bool_vector("; - } else if (type.VectorType().base_type==BASE_TYPE_CHAR) { - return "self.table.ibyte_vector("; + //GenComment(ev.doc_comment, code_ptr, nullptr, Indent.c_str()); + if (ev.name.compare("NONE") == 0) { + continue; + } + if (first) { + code += "\n"; + first = false; + } else { + code += ", \n"; + } + if (enum_def.is_union) { + code += Indent + "(" + ev.name +", "+NumToString(ev.value); + code += ", " + ev.name + "<'a>"; + code += ")"; + } + else { + code += Indent + "(" + ev.name +", "+NumToString(ev.value) +")"; } - default: - return "self.table.get_" + \ - GenTypeGet(type) + "("; } + code += "]}\n\n"; + } // Returns the method name for use with add/put calls. @@ -1106,15 +528,8 @@ static std::string GenNameSpaceExports(const Parser &parser_, std::string qname = struct_def.defined_namespace->components.back(); if (namespace_name.compare(qname) == 0) { code += "pub mod " + mod_name + ";\n"; - if (struct_def.fixed) { - std::string lname = struct_def.name; - std::transform(lname.begin(), lname.end(), lname.begin(), ::tolower); - re_exports += "pub use self::" + mod_name + "::{"; - re_exports += struct_def.name + ", build_" + lname +"};\n"; - } else { - re_exports += "pub use self::" + mod_name + "::"; - re_exports += struct_def.name + ";\n"; - } + re_exports += "pub use self::" + mod_name + "::{"; + re_exports += struct_def.name +", "+ struct_def.name +"Builder};\n"; } } std::vector components = parser_.namespaces_.back()->components; @@ -1134,8 +549,8 @@ static std::string GenNameSpaceExports(const Parser &parser_, // Save out the generated code for a Rust Table type. static bool SaveType(const Parser &parser, const Definition &def, - const std::string &classcode, const std::string &path, - bool needs_imports) { + const std::string &classcode, const std::string &path + ) { if (!classcode.length()) return true; std::string namespace_name; @@ -1161,7 +576,7 @@ static bool SaveType(const Parser &parser, const Definition &def, std::string code = ""; - BeginFile(needs_imports, &code); + BeginFile(&code); code += classcode; std::string filename = namespace_dir + kPathSeparator + def.name + ".rs"; if (parser.opts.strict_rust) { @@ -1191,8 +606,8 @@ static std::string GenTypePointer(const Type &type) { return type.struct_def->name; case BASE_TYPE_UNION: // fall through - default: - return type.enum_def->name + "Union"; + default: + return type.enum_def->name; } } @@ -1209,6 +624,12 @@ static std::string TypeName(const FieldDef &field) { // Create a struct with a builder and the struct's arguments. static void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr) { + + BeginBuilderTraitArgs(struct_def, code_ptr); + StructBuilderArgs(struct_def, "", code_ptr); + EndBuilderTraitArgs(struct_def, code_ptr); + + BeginBuilderArgs(struct_def, code_ptr); StructBuilderArgs(struct_def, "", code_ptr); EndBuilderArgs(code_ptr); @@ -1235,8 +656,7 @@ class RustGenerator : public BaseGenerator { auto &enum_def = **it; std::string enumcode; GenEnum(enum_def, &enumcode); - bool import = enum_def.is_union; - if (!SaveType(parser_, enum_def, enumcode, path_, import)) return false; + if (!SaveType(parser_, enum_def, enumcode, path_)) return false; } return true; } @@ -1247,7 +667,7 @@ class RustGenerator : public BaseGenerator { auto &struct_def = **it; std::string declcode; GenStruct(struct_def, &declcode); - if (!SaveType(parser_, struct_def, declcode, path_, true)) return false; + if (!SaveType(parser_, struct_def, declcode, path_)) return false; } return true; } diff --git a/tests/MyGame/Example/Any.rs b/tests/MyGame/Example/Any.rs index 24cc67be6f..35d2e150de 100644 --- a/tests/MyGame/Example/Any.rs +++ b/tests/MyGame/Example/Any.rs @@ -3,59 +3,7 @@ use flatbuffers; use super::*; -#[derive(PartialEq, Eq, Clone, Debug, Hash)] -#[repr(u8)] -pub enum Any { - NONE = 0, - Monster = 1, - TestSimpleTableWithEnum = 2, -} - -/// A List of all `Any` enum variants. -pub const ANY_LIST: [Any;3] = [Any::NONE,Any::Monster,Any::TestSimpleTableWithEnum,]; - -impl Any { - /// Returns a `str` representation of a `Any` enum. - pub fn name(&self) -> &'static str { - match *self { - Any::NONE => "NONE", - Any::Monster => "Monster", - Any::TestSimpleTableWithEnum => "TestSimpleTableWithEnum", - } - } -} - -impl From for Any { - fn from(value: u8) -> Any { - match value { - 0 => Any::NONE, - 1 => Any::Monster, - 2 => Any::TestSimpleTableWithEnum, - _ => unreachable!("Unable to create a `Any` from value {} ", value), - } - } -} - -#[derive(Debug)] -pub enum AnyUnion<'a> { - None, - Monster(Monster<'a>), - TestSimpleTableWithEnum(TestSimpleTableWithEnum<'a>), -} - -impl<'a> AnyUnion<'a> { - pub fn from_type(table: &'a flatbuffers::Table, t: Any, offset: usize) -> AnyUnion<'a> { - match t { - Any::NONE => { - AnyUnion::None - } - Any::Monster => { - AnyUnion::Monster(table.get_root(offset as u32).into()) - } - Any::TestSimpleTableWithEnum => { - AnyUnion::TestSimpleTableWithEnum(table.get_root(offset as u32).into()) - } - } - } -} +union!{Any,AnyType,u8, [ + (Monster, 1, Monster<'a>), + (TestSimpleTableWithEnum, 2, TestSimpleTableWithEnum<'a>)]} diff --git a/tests/MyGame/Example/Color.rs b/tests/MyGame/Example/Color.rs index d60b7ac5cb..219b29b8fb 100644 --- a/tests/MyGame/Example/Color.rs +++ b/tests/MyGame/Example/Color.rs @@ -1,35 +1,10 @@ //! Automatically generated, do not modify. -#[derive(PartialEq, Eq, Clone, Debug, Hash)] -#[repr(i8)] -pub enum Color { - Red = 1, - Green = 2, - Blue = 8, -} +use flatbuffers; +use super::*; -/// A List of all `Color` enum variants. -pub const COLOR_LIST: [Color;3] = [Color::Red,Color::Green,Color::Blue,]; - -impl Color { - /// Returns a `str` representation of a `Color` enum. - pub fn name(&self) -> &'static str { - match *self { - Color::Red => "Red", - Color::Green => "Green", - Color::Blue => "Blue", - } - } -} - -impl From for Color { - fn from(value: i8) -> Color { - match value { - 1 => Color::Red, - 2 => Color::Green, - 8 => Color::Blue, - _ => unreachable!("Unable to create a `Color` from value {} ", value), - } - } -} +simple_enum!{Color,i8, [ + (Red, 1), + (Green, 2), + (Blue, 8)]} diff --git a/tests/MyGame/Example/Monster.rs b/tests/MyGame/Example/Monster.rs index f89ff78d26..81b810a30a 100644 --- a/tests/MyGame/Example/Monster.rs +++ b/tests/MyGame/Example/Monster.rs @@ -4,531 +4,248 @@ use flatbuffers; use super::*; /// an example documentation comment: monster object -#[derive(Debug)] -pub struct Monster<'a> { - table: flatbuffers::Table<'a>, -} - -enum VT { - POS = 4, - MANA = 6, - HP = 8, - NAME = 10, - INVENTORY = 14, - COLOR = 16, - TEST_TYPE = 18, - TEST = 20, - TEST4 = 22, - TESTARRAYOFSTRING = 24, - TESTARRAYOFTABLES = 26, - ENEMY = 28, - TESTNESTEDFLATBUFFER = 30, - TESTEMPTY = 32, - TESTBOOL = 34, - TESTHASHS32_FNV1 = 36, - TESTHASHU32_FNV1 = 38, - TESTHASHS64_FNV1 = 40, - TESTHASHU64_FNV1 = 42, - TESTHASHS32_FNV1A = 44, - TESTHASHU32_FNV1A = 46, - TESTHASHS64_FNV1A = 48, - TESTHASHU64_FNV1A = 50, - TESTARRAYOFBOOLS = 52, - TESTF = 54, - TESTF2 = 56, - TESTF3 = 58, -} - -impl<'a> Monster<'a> { - pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> Monster { - Monster { - table: flatbuffers::Table::from_offset(buf, offset), - } - } - - pub fn pos(&self) -> Option { - let offset = self.table.field_offset(VT::POS as u16); - if offset != 0 { - return Some(self.table.get_struct::(offset)) - }; - None - } - - pub fn mana(&self) -> i16 { - let offset = self.table.field_offset(VT::MANA as u16); - if offset != 0 { - return self.table.get_i16(offset) - } - 150 - } - - pub fn hp(&self) -> i16 { - let offset = self.table.field_offset(VT::HP as u16); - if offset != 0 { - return self.table.get_i16(offset) - } - 100 - } - - pub fn name(&self) -> &str { - let offset = self.table.field_offset(VT::NAME as u16); - if offset != 0 { - return self.table.get_str(offset) - } - "" - } - - pub fn inventory(&self) -> &[u8] { - let offset = self.table.field_offset(VT::INVENTORY as u16); - if offset != 0 { - return self.table.byte_vector(offset); - } - &[] - } - - pub fn color(&self) -> Color { - let offset = self.table.field_offset(VT::COLOR as u16); - if offset != 0 { - return self.table.get_i8(offset).into() - } - 8.into() - } - - pub fn test_type(&self) -> Any { - let offset = self.table.field_offset(VT::TEST_TYPE as u16); - if offset != 0 { - return self.table.get_u8(offset).into() - } - 0.into() - } - - pub fn test(&self) -> AnyUnion { - let offset = self.table.field_offset(VT::TEST as u16); - if offset != 0 { - let t = self.test_type(); - return AnyUnion::from_type(&self.table, t, offset as usize); - } - AnyUnion::None - } - - pub fn test4(&self) -> flatbuffers::Iterator { - let offset = self.table.field_offset(VT::TEST4 as u16); - if offset != 0 { - return self.table.struct_vector(offset) - } - flatbuffers::empty_iterator(&self.table) - } - - pub fn testarrayofstring(&self) -> flatbuffers::Iterator<&str> { - let offset = self.table.field_offset(VT::TESTARRAYOFSTRING as u16); - if offset != 0 { - return self.table.str_vector(offset); - } - flatbuffers::empty_iterator(&self.table) } - - /// an example documentation comment: this will end up in the generated code - /// multiline too - pub fn testarrayoftables(&self) -> flatbuffers::Iterator { - let offset = self.table.field_offset(VT::TESTARRAYOFTABLES as u16); - if offset != 0 { - return self.table.table_vector(offset) - } - flatbuffers::empty_iterator(&self.table) - } - - pub fn enemy(&self) -> Option { - let offset = self.table.field_offset(VT::ENEMY as u16); - if offset != 0 { - return Some(self.table.get_indirect_root(offset).into()) - }; - None - } - - pub fn testnestedflatbuffer(&self) -> &[u8] { - let offset = self.table.field_offset(VT::TESTNESTEDFLATBUFFER as u16); - if offset != 0 { - return self.table.byte_vector(offset); - } - &[] - } - - pub fn testempty(&self) -> Option { - let offset = self.table.field_offset(VT::TESTEMPTY as u16); - if offset != 0 { - return Some(self.table.get_indirect_root(offset).into()) - }; - None - } - - pub fn testbool(&self) -> bool { - let offset = self.table.field_offset(VT::TESTBOOL as u16); - if offset != 0 { - return self.table.get_bool(offset) - } - false - } - - pub fn testhashs32_fnv1(&self) -> i32 { - let offset = self.table.field_offset(VT::TESTHASHS32_FNV1 as u16); - if offset != 0 { - return self.table.get_i32(offset) - } - 0 - } - - pub fn testhashu32_fnv1(&self) -> u32 { - let offset = self.table.field_offset(VT::TESTHASHU32_FNV1 as u16); - if offset != 0 { - return self.table.get_u32(offset) - } - 0 - } - - pub fn testhashs64_fnv1(&self) -> i64 { - let offset = self.table.field_offset(VT::TESTHASHS64_FNV1 as u16); - if offset != 0 { - return self.table.get_i64(offset) - } - 0 - } - - pub fn testhashu64_fnv1(&self) -> u64 { - let offset = self.table.field_offset(VT::TESTHASHU64_FNV1 as u16); - if offset != 0 { - return self.table.get_u64(offset) - } - 0 - } - - pub fn testhashs32_fnv1a(&self) -> i32 { - let offset = self.table.field_offset(VT::TESTHASHS32_FNV1A as u16); - if offset != 0 { - return self.table.get_i32(offset) - } - 0 - } - - pub fn testhashu32_fnv1a(&self) -> u32 { - let offset = self.table.field_offset(VT::TESTHASHU32_FNV1A as u16); - if offset != 0 { - return self.table.get_u32(offset) - } - 0 - } - - pub fn testhashs64_fnv1a(&self) -> i64 { - let offset = self.table.field_offset(VT::TESTHASHS64_FNV1A as u16); - if offset != 0 { - return self.table.get_i64(offset) - } - 0 - } - - pub fn testhashu64_fnv1a(&self) -> u64 { - let offset = self.table.field_offset(VT::TESTHASHU64_FNV1A as u16); - if offset != 0 { - return self.table.get_u64(offset) - } - 0 - } - - pub fn testarrayofbools(&self) -> &[bool] { - let offset = self.table.field_offset(VT::TESTARRAYOFBOOLS as u16); - if offset != 0 { - return self.table.bool_vector(offset); - } - &[] - } - - pub fn testf(&self) -> f32 { - let offset = self.table.field_offset(VT::TESTF as u16); - if offset != 0 { - return self.table.get_f32(offset) - } - 3.14159 - } - - pub fn testf2(&self) -> f32 { - let offset = self.table.field_offset(VT::TESTF2 as u16); - if offset != 0 { - return self.table.get_f32(offset) - } - 3.0 - } - - pub fn testf3(&self) -> f32 { - let offset = self.table.field_offset(VT::TESTF3 as u16); - if offset != 0 { - return self.table.get_f32(offset) - } - 0.0 - } - -} - -impl<'a> From> for Monster<'a> { - fn from(table: flatbuffers::Table) -> Monster { - Monster{ - table: table, - } - } -} - -/// Builder Object for `Monster` tables. -pub struct Builder { - inner: flatbuffers::Builder, +table_object!{Monster, 4, [ + (pos,get_struct, Vec3, 4), + (mana,get_i16, i16, 6, 150), + (hp,get_i16, i16, 8, 100), + (name,get_str, &str, 10, 0), + (inventory,vector, u8, 14), + (color,simple_enum,get_i8, i8, Color, 16, 8), + (test_type,simple_enum,get_u8, u8, AnyType, 18, 0), + (test,union,test_type, Any, Any, 20, 0), + (test4,vector, Test, 22), + (testarrayofstring,vector, &str, 24), + (testarrayoftables,vector, Monster, 26), + (enemy,get_struct, Monster, 28), + (testnestedflatbuffer,vector, u8, 30), + (testempty,get_struct, Stat, 32), + (testbool,get_bool, bool, 34, false), + (testhashs32_fnv1,get_i32, i32, 36, 0), + (testhashu32_fnv1,get_u32, u32, 38, 0), + (testhashs64_fnv1,get_i64, i64, 40, 0), + (testhashu64_fnv1,get_u64, u64, 42, 0), + (testhashs32_fnv1a,get_i32, i32, 44, 0), + (testhashu32_fnv1a,get_u32, u32, 46, 0), + (testhashs64_fnv1a,get_i64, i64, 48, 0), + (testhashu64_fnv1a,get_u64, u64, 50, 0), + (testarrayofbools,vector, bool, 52), + (testf,get_f32, f32, 54, 3.14159), + (testf2,get_f32, f32, 56, 3.0), + (testf3,get_f32, f32, 58, 0.0)]} + +/// Builder Trait for `Monster` tables. +pub trait MonsterBuilder { + fn start_monster(&mut self); + /// Set the value for field `pos`. + fn add_pos(&mut self, pos: flatbuffers::UOffsetT); + /// Set the value for field `mana`. + fn add_mana(&mut self, mana: i16); + /// Set the value for field `hp`. + fn add_hp(&mut self, hp: i16); + /// Set the value for field `name`. + fn add_name(&mut self, name: flatbuffers::UOffsetT); + /// Set the value for field `inventory`. + fn add_inventory(&mut self, inventory: flatbuffers::UOffsetT); + /// Initializes bookkeeping for writing a new `inventory` vector. + fn start_inventory_vector(&mut self, numElems: usize); + /// Set the value for field `color`. + fn add_color(&mut self, color: i8); + /// Set the value for field `test_type`. + fn add_test_type(&mut self, test_type: u8); + /// Set the value for field `test`. + fn add_test(&mut self, test: flatbuffers::UOffsetT); + /// Set the value for field `test4`. + fn add_test4(&mut self, test4: flatbuffers::UOffsetT); + /// Initializes bookkeeping for writing a new `test4` vector. + fn start_test4_vector(&mut self, numElems: usize); + /// Set the value for field `testarrayofstring`. + fn add_testarrayofstring(&mut self, testarrayofstring: flatbuffers::UOffsetT); + /// Initializes bookkeeping for writing a new `testarrayofstring` vector. + fn start_testarrayofstring_vector(&mut self, numElems: usize); + /// Set the value for field `testarrayoftables`. + fn add_testarrayoftables(&mut self, testarrayoftables: flatbuffers::UOffsetT); + /// Initializes bookkeeping for writing a new `testarrayoftables` vector. + fn start_testarrayoftables_vector(&mut self, numElems: usize); + /// Set the value for field `enemy`. + fn add_enemy(&mut self, enemy: flatbuffers::UOffsetT); + /// Set the value for field `testnestedflatbuffer`. + fn add_testnestedflatbuffer(&mut self, testnestedflatbuffer: flatbuffers::UOffsetT); + /// Initializes bookkeeping for writing a new `testnestedflatbuffer` vector. + fn start_testnestedflatbuffer_vector(&mut self, numElems: usize); + /// Set the value for field `testempty`. + fn add_testempty(&mut self, testempty: flatbuffers::UOffsetT); + /// Set the value for field `testbool`. + fn add_testbool(&mut self, testbool: bool); + /// Set the value for field `testhashs32_fnv1`. + fn add_testhashs32_fnv1(&mut self, testhashs32_fnv1: i32); + /// Set the value for field `testhashu32_fnv1`. + fn add_testhashu32_fnv1(&mut self, testhashu32_fnv1: u32); + /// Set the value for field `testhashs64_fnv1`. + fn add_testhashs64_fnv1(&mut self, testhashs64_fnv1: i64); + /// Set the value for field `testhashu64_fnv1`. + fn add_testhashu64_fnv1(&mut self, testhashu64_fnv1: u64); + /// Set the value for field `testhashs32_fnv1a`. + fn add_testhashs32_fnv1a(&mut self, testhashs32_fnv1a: i32); + /// Set the value for field `testhashu32_fnv1a`. + fn add_testhashu32_fnv1a(&mut self, testhashu32_fnv1a: u32); + /// Set the value for field `testhashs64_fnv1a`. + fn add_testhashs64_fnv1a(&mut self, testhashs64_fnv1a: i64); + /// Set the value for field `testhashu64_fnv1a`. + fn add_testhashu64_fnv1a(&mut self, testhashu64_fnv1a: u64); + /// Set the value for field `testarrayofbools`. + fn add_testarrayofbools(&mut self, testarrayofbools: flatbuffers::UOffsetT); + /// Initializes bookkeeping for writing a new `testarrayofbools` vector. + fn start_testarrayofbools_vector(&mut self, numElems: usize); + /// Set the value for field `testf`. + fn add_testf(&mut self, testf: f32); + /// Set the value for field `testf2`. + fn add_testf2(&mut self, testf2: f32); + /// Set the value for field `testf3`. + fn add_testf3(&mut self, testf3: f32); } -impl Builder { - /// Create a new builder. - pub fn with_capacity(size: usize) -> Self { - Builder { - inner: flatbuffers::Builder::with_capacity(size), - } - } - - /// Initialize a new `Builder` for a `Monster` table. - pub fn start(&mut self) { - self.inner.start_object(28); - } - - /// Finalize the current object and return the offset. - pub fn end(&mut self) -> flatbuffers::UOffsetT { - return self.inner.end_object() +impl MonsterBuilder for flatbuffers::Builder { + fn start_monster(&mut self) { + self.start_object(28); } - /// Set the value for field `pos`. - pub fn add_pos(&mut self, pos: flatbuffers::UOffsetT) { - self.inner.add_slot_struct(0, pos, 0) + fn add_pos(&mut self, pos: flatbuffers::UOffsetT) { + self.add_slot_struct(0, pos, 0) } - /// Set the value for field `mana`. - pub fn add_mana(&mut self, mana: i16) { - self.inner.add_slot_i16(1, mana, 150) + fn add_mana(&mut self, mana: i16) { + self.add_slot_i16(1, mana, 150) } - /// Set the value for field `hp`. - pub fn add_hp(&mut self, hp: i16) { - self.inner.add_slot_i16(2, hp, 100) + fn add_hp(&mut self, hp: i16) { + self.add_slot_i16(2, hp, 100) } - /// Set the value for field `name`. - pub fn add_name(&mut self, name: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(3, name, 0) + fn add_name(&mut self, name: flatbuffers::UOffsetT) { + self.add_slot_uoffset(3, name, 0) } - /// Set the value for field `inventory`. - pub fn add_inventory(&mut self, inventory: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(5, inventory, 0) + fn add_inventory(&mut self, inventory: flatbuffers::UOffsetT) { + self.add_slot_uoffset(5, inventory, 0) } /// Initializes bookkeeping for writing a new `inventory` vector. - pub fn start_inventory_vector(&mut self, numElems: usize) { - self.inner.start_vector(1, numElems, 1) + fn start_inventory_vector(&mut self, numElems: usize) { + self.start_vector(1, numElems, 1) } - /// Set the value for field `color`. - pub fn add_color(&mut self, color: i8) { - self.inner.add_slot_i8(6, color, 8) + fn add_color(&mut self, color: i8) { + self.add_slot_i8(6, color, 8) } - /// Set the value for field `test_type`. - pub fn add_test_type(&mut self, test_type: u8) { - self.inner.add_slot_u8(7, test_type, 0) + fn add_test_type(&mut self, test_type: u8) { + self.add_slot_u8(7, test_type, 0) } - /// Set the value for field `test`. - pub fn add_test(&mut self, test: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(8, test, 0) + fn add_test(&mut self, test: flatbuffers::UOffsetT) { + self.add_slot_uoffset(8, test, 0) } - /// Set the value for field `test4`. - pub fn add_test4(&mut self, test4: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(9, test4, 0) + fn add_test4(&mut self, test4: flatbuffers::UOffsetT) { + self.add_slot_uoffset(9, test4, 0) } /// Initializes bookkeeping for writing a new `test4` vector. - pub fn start_test4_vector(&mut self, numElems: usize) { - self.inner.start_vector(4, numElems, 2) + fn start_test4_vector(&mut self, numElems: usize) { + self.start_vector(4, numElems, 2) } - /// Set the value for field `testarrayofstring`. - pub fn add_testarrayofstring(&mut self, testarrayofstring: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(10, testarrayofstring, 0) + fn add_testarrayofstring(&mut self, testarrayofstring: flatbuffers::UOffsetT) { + self.add_slot_uoffset(10, testarrayofstring, 0) } /// Initializes bookkeeping for writing a new `testarrayofstring` vector. - pub fn start_testarrayofstring_vector(&mut self, numElems: usize) { - self.inner.start_vector(4, numElems, 4) + fn start_testarrayofstring_vector(&mut self, numElems: usize) { + self.start_vector(4, numElems, 4) } - /// Set the value for field `testarrayoftables`. - pub fn add_testarrayoftables(&mut self, testarrayoftables: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(11, testarrayoftables, 0) + fn add_testarrayoftables(&mut self, testarrayoftables: flatbuffers::UOffsetT) { + self.add_slot_uoffset(11, testarrayoftables, 0) } /// Initializes bookkeeping for writing a new `testarrayoftables` vector. - pub fn start_testarrayoftables_vector(&mut self, numElems: usize) { - self.inner.start_vector(4, numElems, 4) + fn start_testarrayoftables_vector(&mut self, numElems: usize) { + self.start_vector(4, numElems, 4) } - /// Set the value for field `enemy`. - pub fn add_enemy(&mut self, enemy: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(12, enemy, 0) + fn add_enemy(&mut self, enemy: flatbuffers::UOffsetT) { + self.add_slot_uoffset(12, enemy, 0) } - /// Set the value for field `testnestedflatbuffer`. - pub fn add_testnestedflatbuffer(&mut self, testnestedflatbuffer: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(13, testnestedflatbuffer, 0) + fn add_testnestedflatbuffer(&mut self, testnestedflatbuffer: flatbuffers::UOffsetT) { + self.add_slot_uoffset(13, testnestedflatbuffer, 0) } /// Initializes bookkeeping for writing a new `testnestedflatbuffer` vector. - pub fn start_testnestedflatbuffer_vector(&mut self, numElems: usize) { - self.inner.start_vector(1, numElems, 1) + fn start_testnestedflatbuffer_vector(&mut self, numElems: usize) { + self.start_vector(1, numElems, 1) } - /// Set the value for field `testempty`. - pub fn add_testempty(&mut self, testempty: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(14, testempty, 0) + fn add_testempty(&mut self, testempty: flatbuffers::UOffsetT) { + self.add_slot_uoffset(14, testempty, 0) } - /// Set the value for field `testbool`. - pub fn add_testbool(&mut self, testbool: bool) { - self.inner.add_slot_bool(15, testbool, false) + fn add_testbool(&mut self, testbool: bool) { + self.add_slot_bool(15, testbool, false) } - /// Set the value for field `testhashs32_fnv1`. - pub fn add_testhashs32_fnv1(&mut self, testhashs32_fnv1: i32) { - self.inner.add_slot_i32(16, testhashs32_fnv1, 0) + fn add_testhashs32_fnv1(&mut self, testhashs32_fnv1: i32) { + self.add_slot_i32(16, testhashs32_fnv1, 0) } - /// Set the value for field `testhashu32_fnv1`. - pub fn add_testhashu32_fnv1(&mut self, testhashu32_fnv1: u32) { - self.inner.add_slot_u32(17, testhashu32_fnv1, 0) + fn add_testhashu32_fnv1(&mut self, testhashu32_fnv1: u32) { + self.add_slot_u32(17, testhashu32_fnv1, 0) } - /// Set the value for field `testhashs64_fnv1`. - pub fn add_testhashs64_fnv1(&mut self, testhashs64_fnv1: i64) { - self.inner.add_slot_i64(18, testhashs64_fnv1, 0) + fn add_testhashs64_fnv1(&mut self, testhashs64_fnv1: i64) { + self.add_slot_i64(18, testhashs64_fnv1, 0) } - /// Set the value for field `testhashu64_fnv1`. - pub fn add_testhashu64_fnv1(&mut self, testhashu64_fnv1: u64) { - self.inner.add_slot_u64(19, testhashu64_fnv1, 0) + fn add_testhashu64_fnv1(&mut self, testhashu64_fnv1: u64) { + self.add_slot_u64(19, testhashu64_fnv1, 0) } - /// Set the value for field `testhashs32_fnv1a`. - pub fn add_testhashs32_fnv1a(&mut self, testhashs32_fnv1a: i32) { - self.inner.add_slot_i32(20, testhashs32_fnv1a, 0) + fn add_testhashs32_fnv1a(&mut self, testhashs32_fnv1a: i32) { + self.add_slot_i32(20, testhashs32_fnv1a, 0) } - /// Set the value for field `testhashu32_fnv1a`. - pub fn add_testhashu32_fnv1a(&mut self, testhashu32_fnv1a: u32) { - self.inner.add_slot_u32(21, testhashu32_fnv1a, 0) + fn add_testhashu32_fnv1a(&mut self, testhashu32_fnv1a: u32) { + self.add_slot_u32(21, testhashu32_fnv1a, 0) } - /// Set the value for field `testhashs64_fnv1a`. - pub fn add_testhashs64_fnv1a(&mut self, testhashs64_fnv1a: i64) { - self.inner.add_slot_i64(22, testhashs64_fnv1a, 0) + fn add_testhashs64_fnv1a(&mut self, testhashs64_fnv1a: i64) { + self.add_slot_i64(22, testhashs64_fnv1a, 0) } - /// Set the value for field `testhashu64_fnv1a`. - pub fn add_testhashu64_fnv1a(&mut self, testhashu64_fnv1a: u64) { - self.inner.add_slot_u64(23, testhashu64_fnv1a, 0) + fn add_testhashu64_fnv1a(&mut self, testhashu64_fnv1a: u64) { + self.add_slot_u64(23, testhashu64_fnv1a, 0) } - /// Set the value for field `testarrayofbools`. - pub fn add_testarrayofbools(&mut self, testarrayofbools: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(24, testarrayofbools, 0) + fn add_testarrayofbools(&mut self, testarrayofbools: flatbuffers::UOffsetT) { + self.add_slot_uoffset(24, testarrayofbools, 0) } /// Initializes bookkeeping for writing a new `testarrayofbools` vector. - pub fn start_testarrayofbools_vector(&mut self, numElems: usize) { - self.inner.start_vector(1, numElems, 1) + fn start_testarrayofbools_vector(&mut self, numElems: usize) { + self.start_vector(1, numElems, 1) } - /// Set the value for field `testf`. - pub fn add_testf(&mut self, testf: f32) { - self.inner.add_slot_f32(25, testf, 3.14159) - } - - /// Set the value for field `testf2`. - pub fn add_testf2(&mut self, testf2: f32) { - self.inner.add_slot_f32(26, testf2, 3.0) + fn add_testf(&mut self, testf: f32) { + self.add_slot_f32(25, testf, 3.14159) } - /// Set the value for field `testf3`. - pub fn add_testf3(&mut self, testf3: f32) { - self.inner.add_slot_f32(27, testf3, 0.0) - } - - pub fn build_vec3(&mut self , x: f32, y: f32, z: f32, test1: f64, test2: i8, test3_a: i16, test3_b: i8) -> flatbuffers::UOffsetT { - vec3::build_vec3(&mut self.inner, x, y, z, test1, test2, test3_a, test3_b) - } - - pub fn build_test(&mut self , a: i16, b: i8) -> flatbuffers::UOffsetT { - test::build_test(&mut self.inner, a, b) - } - - /// Finish the buffer. - pub fn finish(&mut self, r: flatbuffers::UOffsetT) { - return self.inner.finish(r) - } - - pub fn create_string(&mut self, v: &str) -> flatbuffers::UOffsetT { self.inner.create_string(v) } - pub fn get_bytes(&self) -> &[u8] { self.inner.get_bytes() } - pub fn len(&self) -> usize { self.inner.len() } - pub fn offset(&self) -> usize { self.inner.offset() } - pub fn reset(&mut self) { self.inner.reset() } - pub fn prep(&mut self, s:usize, a: usize) { self.inner.prep(s,a) } - pub fn pad(&mut self, n:usize) { self.inner.pad(n) } - pub fn end_vector(&mut self) -> flatbuffers::UOffsetT { self.inner.end_vector() } - pub fn add_bool(&mut self, v:bool) { self.inner.add_bool(v) } - pub fn add_u8(&mut self, v:u8) { self.inner.add_u8(v) } - pub fn add_i8(&mut self, v:i8) { self.inner.add_i8(v) } - pub fn add_u16(&mut self, v:u16) { self.inner.add_u16(v) } - pub fn add_i16(&mut self, v:i16) { self.inner.add_i16(v) } - pub fn add_u32(&mut self, v:u32) { self.inner.add_u32(v) } - pub fn add_i32(&mut self, v:i32) { self.inner.add_i32(v) } - pub fn add_u64(&mut self, v:u64) { self.inner.add_u64(v) } - pub fn add_i64(&mut self, v:i64) { self.inner.add_i64(v) } - pub fn add_f32(&mut self, v:f32) { self.inner.add_f32(v) } - pub fn add_f64(&mut self, v:f64) { self.inner.add_f64(v) } - pub fn add_uoffset(&mut self, v: flatbuffers::UOffsetT) { self.inner.add_uoffset(v) } - pub fn add_slot_bool(&mut self, o: usize, v: bool, d: bool) { self.inner.add_slot_bool(o,v,d) } - pub fn add_slot_u8(&mut self, o: usize, v: u8, d: u8) { self.inner.add_slot_u8(o,v,d) } - pub fn add_slot_i8(&mut self, o: usize, v: i8, d: i8) { self.inner.add_slot_i8(o,v,d) } - pub fn add_slot_u16(&mut self, o: usize, v: u16, d: u16) { self.inner.add_slot_u16(o,v,d) } - pub fn add_slot_i16(&mut self, o: usize, v: i16, d: i16) { self.inner.add_slot_i16(o,v,d) } - pub fn add_slot_i32(&mut self, o: usize, v: i32, d: i32) { self.inner.add_slot_i32(o,v,d) } - pub fn add_slot_u32(&mut self, o: usize, v: u32, d: u32) { self.inner.add_slot_u32(o,v,d) } - pub fn add_slot_u64(&mut self, o: usize, v: u64, d: u64) { self.inner.add_slot_u64(o,v,d) } - pub fn add_slot_i64(&mut self, o: usize, v: i64, d: i64) { self.inner.add_slot_i64(o,v,d) } - pub fn add_slot_f32(&mut self, o: usize, v: f32, d: f32) { self.inner.add_slot_f32(o,v,d) } - pub fn add_slot_f64(&mut self, o: usize, v: f64, d: f64) { self.inner.add_slot_f64(o,v,d) } - pub fn add_slot_uoffset(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_uoffset(o,v,d) } - pub fn add_slot_struct(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_struct(o,v,d) } -} - -impl Default for Builder { - fn default() -> Builder { - Builder::with_capacity(1024) + fn add_testf2(&mut self, testf2: f32) { + self.add_slot_f32(26, testf2, 3.0) } -} -impl From for Builder { - fn from(b: flatbuffers::Builder) -> Builder { - Builder { - inner: b, - } + fn add_testf3(&mut self, testf3: f32) { + self.add_slot_f32(27, testf3, 0.0) } -} -impl Into for Builder { - fn into(self) -> flatbuffers::Builder { - self.inner - } } -impl flatbuffers::ObjectBuilder for Builder {} - diff --git a/tests/MyGame/Example/Stat.rs b/tests/MyGame/Example/Stat.rs index 4bccf31436..a68dd0ed04 100644 --- a/tests/MyGame/Example/Stat.rs +++ b/tests/MyGame/Example/Stat.rs @@ -3,155 +3,38 @@ use flatbuffers; use super::*; -#[derive(Debug)] -pub struct Stat<'a> { - table: flatbuffers::Table<'a>, -} - -enum VT { - ID = 4, - VAL = 6, - COUNT = 8, -} - -impl<'a> Stat<'a> { - pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> Stat { - Stat { - table: flatbuffers::Table::from_offset(buf, offset), - } - } - - pub fn id(&self) -> &str { - let offset = self.table.field_offset(VT::ID as u16); - if offset != 0 { - return self.table.get_str(offset) - } - "" - } - - pub fn val(&self) -> i64 { - let offset = self.table.field_offset(VT::VAL as u16); - if offset != 0 { - return self.table.get_i64(offset) - } - 0 - } - - pub fn count(&self) -> u16 { - let offset = self.table.field_offset(VT::COUNT as u16); - if offset != 0 { - return self.table.get_u16(offset) - } - 0 - } - -} - -impl<'a> From> for Stat<'a> { - fn from(table: flatbuffers::Table) -> Stat { - Stat{ - table: table, - } - } -} - -/// Builder Object for `Stat` tables. -pub struct Builder { - inner: flatbuffers::Builder, -} - -impl Builder { - /// Create a new builder. - pub fn with_capacity(size: usize) -> Self { - Builder { - inner: flatbuffers::Builder::with_capacity(size), - } - } - - /// Initialize a new `Builder` for a `Stat` table. - pub fn start(&mut self) { - self.inner.start_object(3); - } - - /// Finalize the current object and return the offset. - pub fn end(&mut self) -> flatbuffers::UOffsetT { - return self.inner.end_object() - } - +table_object!{Stat, 4, [ + (id,get_str, &str, 4, 0), + (val,get_i64, i64, 6, 0), + (count,get_u16, u16, 8, 0)]} + +/// Builder Trait for `Stat` tables. +pub trait StatBuilder { + fn start_stat(&mut self); /// Set the value for field `id`. - pub fn add_id(&mut self, id: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(0, id, 0) - } - + fn add_id(&mut self, id: flatbuffers::UOffsetT); /// Set the value for field `val`. - pub fn add_val(&mut self, val: i64) { - self.inner.add_slot_i64(1, val, 0) - } - + fn add_val(&mut self, val: i64); /// Set the value for field `count`. - pub fn add_count(&mut self, count: u16) { - self.inner.add_slot_u16(2, count, 0) - } + fn add_count(&mut self, count: u16); +} - /// Finish the buffer. - pub fn finish(&mut self, r: flatbuffers::UOffsetT) { - return self.inner.finish(r) +impl StatBuilder for flatbuffers::Builder { + fn start_stat(&mut self) { + self.start_object(3); } - pub fn create_string(&mut self, v: &str) -> flatbuffers::UOffsetT { self.inner.create_string(v) } - pub fn get_bytes(&self) -> &[u8] { self.inner.get_bytes() } - pub fn len(&self) -> usize { self.inner.len() } - pub fn offset(&self) -> usize { self.inner.offset() } - pub fn reset(&mut self) { self.inner.reset() } - pub fn prep(&mut self, s:usize, a: usize) { self.inner.prep(s,a) } - pub fn pad(&mut self, n:usize) { self.inner.pad(n) } - pub fn end_vector(&mut self) -> flatbuffers::UOffsetT { self.inner.end_vector() } - pub fn add_bool(&mut self, v:bool) { self.inner.add_bool(v) } - pub fn add_u8(&mut self, v:u8) { self.inner.add_u8(v) } - pub fn add_i8(&mut self, v:i8) { self.inner.add_i8(v) } - pub fn add_u16(&mut self, v:u16) { self.inner.add_u16(v) } - pub fn add_i16(&mut self, v:i16) { self.inner.add_i16(v) } - pub fn add_u32(&mut self, v:u32) { self.inner.add_u32(v) } - pub fn add_i32(&mut self, v:i32) { self.inner.add_i32(v) } - pub fn add_u64(&mut self, v:u64) { self.inner.add_u64(v) } - pub fn add_i64(&mut self, v:i64) { self.inner.add_i64(v) } - pub fn add_f32(&mut self, v:f32) { self.inner.add_f32(v) } - pub fn add_f64(&mut self, v:f64) { self.inner.add_f64(v) } - pub fn add_uoffset(&mut self, v: flatbuffers::UOffsetT) { self.inner.add_uoffset(v) } - pub fn add_slot_bool(&mut self, o: usize, v: bool, d: bool) { self.inner.add_slot_bool(o,v,d) } - pub fn add_slot_u8(&mut self, o: usize, v: u8, d: u8) { self.inner.add_slot_u8(o,v,d) } - pub fn add_slot_i8(&mut self, o: usize, v: i8, d: i8) { self.inner.add_slot_i8(o,v,d) } - pub fn add_slot_u16(&mut self, o: usize, v: u16, d: u16) { self.inner.add_slot_u16(o,v,d) } - pub fn add_slot_i16(&mut self, o: usize, v: i16, d: i16) { self.inner.add_slot_i16(o,v,d) } - pub fn add_slot_i32(&mut self, o: usize, v: i32, d: i32) { self.inner.add_slot_i32(o,v,d) } - pub fn add_slot_u32(&mut self, o: usize, v: u32, d: u32) { self.inner.add_slot_u32(o,v,d) } - pub fn add_slot_u64(&mut self, o: usize, v: u64, d: u64) { self.inner.add_slot_u64(o,v,d) } - pub fn add_slot_i64(&mut self, o: usize, v: i64, d: i64) { self.inner.add_slot_i64(o,v,d) } - pub fn add_slot_f32(&mut self, o: usize, v: f32, d: f32) { self.inner.add_slot_f32(o,v,d) } - pub fn add_slot_f64(&mut self, o: usize, v: f64, d: f64) { self.inner.add_slot_f64(o,v,d) } - pub fn add_slot_uoffset(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_uoffset(o,v,d) } - pub fn add_slot_struct(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_struct(o,v,d) } -} - -impl Default for Builder { - fn default() -> Builder { - Builder::with_capacity(1024) + fn add_id(&mut self, id: flatbuffers::UOffsetT) { + self.add_slot_uoffset(0, id, 0) } -} -impl From for Builder { - fn from(b: flatbuffers::Builder) -> Builder { - Builder { - inner: b, - } + fn add_val(&mut self, val: i64) { + self.add_slot_i64(1, val, 0) } -} -impl Into for Builder { - fn into(self) -> flatbuffers::Builder { - self.inner + fn add_count(&mut self, count: u16) { + self.add_slot_u16(2, count, 0) } -} -impl flatbuffers::ObjectBuilder for Builder {} +} diff --git a/tests/MyGame/Example/Test.rs b/tests/MyGame/Example/Test.rs index 55f3baf290..8cf0fa5c3f 100644 --- a/tests/MyGame/Example/Test.rs +++ b/tests/MyGame/Example/Test.rs @@ -3,47 +3,21 @@ use flatbuffers; use super::*; -#[derive(Debug)] -pub struct Test<'a> { - table: flatbuffers::Table<'a>, -} - -enum VT { - A = 0, - B = 2,// Padding1 -} - -impl<'a> Test<'a> { - pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> Test { - Test { - table: flatbuffers::Table::with_pos(buf, offset), - } - } - - pub fn a(&self) -> i16 { - let offset = VT::A as u32; - return self.table.get_i16(offset) - } - - pub fn b(&self) -> i8 { - let offset = VT::B as u32; - return self.table.get_i8(offset) - } +struct_object!{Test, 4, [ + (a,get_i16, i16, 0, 0), + (b,get_i8, i8, 2, 0)]} +pub trait TestBuilder { + fn build_test(&mut self, a: i16, b: i8) -> flatbuffers::UOffsetT; } -impl<'a> From> for Test<'a> { - fn from(table: flatbuffers::Table) -> Test { - Test{ - table: table, - } +impl TestBuilder for flatbuffers::Builder { + fn build_test(&mut self, a: i16, b: i8) -> flatbuffers::UOffsetT { + self.prep(2, 4); + self.pad(1); + self.add_i8(b); + self.add_i16(a); + self.offset() as flatbuffers::UOffsetT } } -pub fn build_test(builder: &mut flatbuffers::Builder, a: i16, b: i8) -> flatbuffers::UOffsetT { - builder.prep(2, 4); - builder.pad(1); - builder.add_i8(b); - builder.add_i16(a); - builder.offset() as flatbuffers::UOffsetT -} diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.rs b/tests/MyGame/Example/TestSimpleTableWithEnum.rs index b6ccba8914..6a2248446d 100644 --- a/tests/MyGame/Example/TestSimpleTableWithEnum.rs +++ b/tests/MyGame/Example/TestSimpleTableWithEnum.rs @@ -3,127 +3,24 @@ use flatbuffers; use super::*; -#[derive(Debug)] -pub struct TestSimpleTableWithEnum<'a> { - table: flatbuffers::Table<'a>, -} - -enum VT { - COLOR = 4, -} - -impl<'a> TestSimpleTableWithEnum<'a> { - pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> TestSimpleTableWithEnum { - TestSimpleTableWithEnum { - table: flatbuffers::Table::from_offset(buf, offset), - } - } - - pub fn color(&self) -> Color { - let offset = self.table.field_offset(VT::COLOR as u16); - if offset != 0 { - return self.table.get_i8(offset).into() - } - 2.into() - } - -} - -impl<'a> From> for TestSimpleTableWithEnum<'a> { - fn from(table: flatbuffers::Table) -> TestSimpleTableWithEnum { - TestSimpleTableWithEnum{ - table: table, - } - } -} - -/// Builder Object for `TestSimpleTableWithEnum` tables. -pub struct Builder { - inner: flatbuffers::Builder, -} - -impl Builder { - /// Create a new builder. - pub fn with_capacity(size: usize) -> Self { - Builder { - inner: flatbuffers::Builder::with_capacity(size), - } - } - - /// Initialize a new `Builder` for a `TestSimpleTableWithEnum` table. - pub fn start(&mut self) { - self.inner.start_object(1); - } - - /// Finalize the current object and return the offset. - pub fn end(&mut self) -> flatbuffers::UOffsetT { - return self.inner.end_object() - } +table_object!{TestSimpleTableWithEnum, 4, [ + (color,simple_enum,get_i8, i8, Color, 4, 2)]} +/// Builder Trait for `TestSimpleTableWithEnum` tables. +pub trait TestSimpleTableWithEnumBuilder { + fn start_testsimpletablewithenum(&mut self); /// Set the value for field `color`. - pub fn add_color(&mut self, color: i8) { - self.inner.add_slot_i8(0, color, 2) - } - - /// Finish the buffer. - pub fn finish(&mut self, r: flatbuffers::UOffsetT) { - return self.inner.finish(r) - } - - pub fn create_string(&mut self, v: &str) -> flatbuffers::UOffsetT { self.inner.create_string(v) } - pub fn get_bytes(&self) -> &[u8] { self.inner.get_bytes() } - pub fn len(&self) -> usize { self.inner.len() } - pub fn offset(&self) -> usize { self.inner.offset() } - pub fn reset(&mut self) { self.inner.reset() } - pub fn prep(&mut self, s:usize, a: usize) { self.inner.prep(s,a) } - pub fn pad(&mut self, n:usize) { self.inner.pad(n) } - pub fn end_vector(&mut self) -> flatbuffers::UOffsetT { self.inner.end_vector() } - pub fn add_bool(&mut self, v:bool) { self.inner.add_bool(v) } - pub fn add_u8(&mut self, v:u8) { self.inner.add_u8(v) } - pub fn add_i8(&mut self, v:i8) { self.inner.add_i8(v) } - pub fn add_u16(&mut self, v:u16) { self.inner.add_u16(v) } - pub fn add_i16(&mut self, v:i16) { self.inner.add_i16(v) } - pub fn add_u32(&mut self, v:u32) { self.inner.add_u32(v) } - pub fn add_i32(&mut self, v:i32) { self.inner.add_i32(v) } - pub fn add_u64(&mut self, v:u64) { self.inner.add_u64(v) } - pub fn add_i64(&mut self, v:i64) { self.inner.add_i64(v) } - pub fn add_f32(&mut self, v:f32) { self.inner.add_f32(v) } - pub fn add_f64(&mut self, v:f64) { self.inner.add_f64(v) } - pub fn add_uoffset(&mut self, v: flatbuffers::UOffsetT) { self.inner.add_uoffset(v) } - pub fn add_slot_bool(&mut self, o: usize, v: bool, d: bool) { self.inner.add_slot_bool(o,v,d) } - pub fn add_slot_u8(&mut self, o: usize, v: u8, d: u8) { self.inner.add_slot_u8(o,v,d) } - pub fn add_slot_i8(&mut self, o: usize, v: i8, d: i8) { self.inner.add_slot_i8(o,v,d) } - pub fn add_slot_u16(&mut self, o: usize, v: u16, d: u16) { self.inner.add_slot_u16(o,v,d) } - pub fn add_slot_i16(&mut self, o: usize, v: i16, d: i16) { self.inner.add_slot_i16(o,v,d) } - pub fn add_slot_i32(&mut self, o: usize, v: i32, d: i32) { self.inner.add_slot_i32(o,v,d) } - pub fn add_slot_u32(&mut self, o: usize, v: u32, d: u32) { self.inner.add_slot_u32(o,v,d) } - pub fn add_slot_u64(&mut self, o: usize, v: u64, d: u64) { self.inner.add_slot_u64(o,v,d) } - pub fn add_slot_i64(&mut self, o: usize, v: i64, d: i64) { self.inner.add_slot_i64(o,v,d) } - pub fn add_slot_f32(&mut self, o: usize, v: f32, d: f32) { self.inner.add_slot_f32(o,v,d) } - pub fn add_slot_f64(&mut self, o: usize, v: f64, d: f64) { self.inner.add_slot_f64(o,v,d) } - pub fn add_slot_uoffset(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_uoffset(o,v,d) } - pub fn add_slot_struct(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_struct(o,v,d) } + fn add_color(&mut self, color: i8); } -impl Default for Builder { - fn default() -> Builder { - Builder::with_capacity(1024) +impl TestSimpleTableWithEnumBuilder for flatbuffers::Builder { + fn start_testsimpletablewithenum(&mut self) { + self.start_object(1); } -} -impl From for Builder { - fn from(b: flatbuffers::Builder) -> Builder { - Builder { - inner: b, - } + fn add_color(&mut self, color: i8) { + self.add_slot_i8(0, color, 2) } -} -impl Into for Builder { - fn into(self) -> flatbuffers::Builder { - self.inner - } } -impl flatbuffers::ObjectBuilder for Builder {} - diff --git a/tests/MyGame/Example/Vec3.rs b/tests/MyGame/Example/Vec3.rs index f1714a9fdc..65adddf354 100644 --- a/tests/MyGame/Example/Vec3.rs +++ b/tests/MyGame/Example/Vec3.rs @@ -3,80 +3,34 @@ use flatbuffers; use super::*; -#[derive(Debug)] -pub struct Vec3<'a> { - table: flatbuffers::Table<'a>, +struct_object!{Vec3, 32, [ + (x,get_f32, f32, 0, 0.0), + (y,get_f32, f32, 4, 0.0), + (z,get_f32, f32, 8, 0.0), + (test1,get_f64, f64, 16, 0.0), + (test2,simple_enum,get_i8, i8, Color, 24, 0), + (test3,get_struct, Test, 26)]} + +pub trait Vec3Builder { + fn build_vec3(&mut self, x: f32, y: f32, z: f32, test1: f64, test2: i8, test3_a: i16, test3_b: i8) -> flatbuffers::UOffsetT; } -enum VT { - X = 0, - Y = 4, - Z = 8,// Padding4 - TEST1 = 16, - TEST2 = 24,// Padding1 - TEST3 = 26,// Padding2 -} - -impl<'a> Vec3<'a> { - pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> Vec3 { - Vec3 { - table: flatbuffers::Table::with_pos(buf, offset), - } - } - - pub fn x(&self) -> f32 { - let offset = VT::X as u32; - return self.table.get_f32(offset) - } - - pub fn y(&self) -> f32 { - let offset = VT::Y as u32; - return self.table.get_f32(offset) - } - - pub fn z(&self) -> f32 { - let offset = VT::Z as u32; - return self.table.get_f32(offset) - } - - pub fn test1(&self) -> f64 { - let offset = VT::TEST1 as u32; - return self.table.get_f64(offset) +impl Vec3Builder for flatbuffers::Builder { + fn build_vec3(&mut self, x: f32, y: f32, z: f32, test1: f64, test2: i8, test3_a: i16, test3_b: i8) -> flatbuffers::UOffsetT { + self.prep(16, 32); + self.pad(2); + self.prep(2, 4); + self.pad(1); + self.add_i8(test3_b); + self.add_i16(test3_a); + self.pad(1); + self.add_i8(test2); + self.add_f64(test1); + self.pad(4); + self.add_f32(z); + self.add_f32(y); + self.add_f32(x); + self.offset() as flatbuffers::UOffsetT } - - pub fn test2(&self) -> Color { - let offset = VT::TEST2 as u32; - return self.table.get_i8(offset).into() - } - - pub fn test3(&self) -> Test { - let offset = VT::TEST3 as u32; - return self.table.get_struct::(offset) - } - } -impl<'a> From> for Vec3<'a> { - fn from(table: flatbuffers::Table) -> Vec3 { - Vec3{ - table: table, - } - } -} - -pub fn build_vec3(builder: &mut flatbuffers::Builder, x: f32, y: f32, z: f32, test1: f64, test2: i8, test3_a: i16, test3_b: i8) -> flatbuffers::UOffsetT { - builder.prep(16, 32); - builder.pad(2); - builder.prep(2, 4); - builder.pad(1); - builder.add_i8(test3_b); - builder.add_i16(test3_a); - builder.pad(1); - builder.add_i8(test2); - builder.add_f64(test1); - builder.pad(4); - builder.add_f32(z); - builder.add_f32(y); - builder.add_f32(x); - builder.offset() as flatbuffers::UOffsetT -} diff --git a/tests/MyGame/Example/mod.rs b/tests/MyGame/Example/mod.rs index 657a1baab1..f117a8e5e0 100644 --- a/tests/MyGame/Example/mod.rs +++ b/tests/MyGame/Example/mod.rs @@ -11,8 +11,8 @@ pub mod monster; pub use self::color::*; pub use self::any::*; -pub use self::test::{Test, build_test}; -pub use self::testsimpletablewithenum::TestSimpleTableWithEnum; -pub use self::vec3::{Vec3, build_vec3}; -pub use self::stat::Stat; -pub use self::monster::Monster; +pub use self::test::{Test, TestBuilder}; +pub use self::testsimpletablewithenum::{TestSimpleTableWithEnum, TestSimpleTableWithEnumBuilder}; +pub use self::vec3::{Vec3, Vec3Builder}; +pub use self::stat::{Stat, StatBuilder}; +pub use self::monster::{Monster, MonsterBuilder}; From 9c1234cf7ac59e43d5ddb5e60c26ff1f19d501f8 Mon Sep 17 00:00:00 2001 From: Joseph Dunne Date: Sun, 5 Jun 2016 20:57:10 +0100 Subject: [PATCH 4/7] Refactor iter and table methods --- include/flatbuffers/idl.h | 26 +-- rust/Cargo.lock | 2 +- rust/Cargo.toml | 2 +- rust/src/bin/test/MyGame/Example/.#Color.rs | 1 - rust/src/builder.rs | 22 ++- rust/src/iter.rs | 173 ++++++++------------ rust/src/lib.rs | 2 +- rust/src/macros.rs | 52 +++--- rust/src/table.rs | 11 +- 9 files changed, 136 insertions(+), 155 deletions(-) delete mode 120000 rust/src/bin/test/MyGame/Example/.#Color.rs diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 26f37864f5..2be1296ea9 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -35,19 +35,19 @@ namespace flatbuffers { // Additionally, Parser::ParseType assumes bool..string is a contiguous range // of type tokens. #define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \ - TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8) \ - TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8) /* begin scalar/int */ \ - TD(BOOL, "bool", uint8_t, boolean,byte, bool, bool, bool) \ - TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8) \ - TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, u8, u8) \ - TD(SHORT, "short", int16_t, short, int16, short, i16, i16) \ - TD(USHORT, "ushort", uint16_t, short, uint16, ushort, u16, u16) \ - TD(INT, "int", int32_t, int, int32, int, i32, i32) \ - TD(UINT, "uint", uint32_t, int, uint32, uint, u32, u32) \ - TD(LONG, "long", int64_t, long, int64, long, i64, i64) \ - TD(ULONG, "ulong", uint64_t, long, uint64, ulong, u64, u64) /* end int */ \ - TD(FLOAT, "float", float, float, float32, float, f32, f32) /* begin float */ \ - TD(DOUBLE, "double", double, double, float64, double, f64, f64) /* end float/scalar */ + TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8) \ + TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8) /* begin scalar/int */ \ + TD(BOOL, "bool", uint8_t, boolean,byte, bool, bool, bool) \ + TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8) \ + TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8) \ + TD(SHORT, "short", int16_t, short, int16, short, int16, i16) \ + TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16) \ + TD(INT, "int", int32_t, int, int32, int, int32, i32) \ + TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32) \ + TD(LONG, "long", int64_t, long, int64, long, int64, i64) \ + TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64) /* end int */ \ + TD(FLOAT, "float", float, float, float32, float, float32, f32) /* begin float */ \ + TD(DOUBLE, "double", double, double, float64, double, float64, f64) /* end float/scalar */ #define FLATBUFFERS_GEN_TYPES_POINTER(TD) \ TD(STRING, "string", Offset, int, int, StringOffset, int, i32) \ TD(VECTOR, "", Offset, int, int, VectorOffset, int, i32) \ diff --git a/rust/Cargo.lock b/rust/Cargo.lock index b151104a40..0985e001d4 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "flatbuffers" -version = "0.2.0" +version = "0.2.1" dependencies = [ "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 01f8698076..93e6a38886 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "flatbuffers" -version = "0.2.0" +version = "0.2.1" authors = ["Joseph Dunne "] description = "Memory Efficient Serialization Library. Flatbuffers runtime for Rust." keywords = ["flatbuffers", "serialization", "deserialization"] diff --git a/rust/src/bin/test/MyGame/Example/.#Color.rs b/rust/src/bin/test/MyGame/Example/.#Color.rs deleted file mode 120000 index 1bbcfe1b33..0000000000 --- a/rust/src/bin/test/MyGame/Example/.#Color.rs +++ /dev/null @@ -1 +0,0 @@ -jo@MULTIVAC.local.11340 \ No newline at end of file diff --git a/rust/src/builder.rs b/rust/src/builder.rs index 7fe4df81e1..ccc873e09a 100644 --- a/rust/src/builder.rs +++ b/rust/src/builder.rs @@ -236,10 +236,14 @@ impl Builder { /// pad places zeros at the current offset. pub fn pad(&mut self, n: usize) { - for _ in 0..n { - self.space -= 1; - let pos = self.space; - self.place_u8(pos, 0) + use std::ptr; + unsafe { + let mut ptr = self.bytes.as_mut_ptr().offset(self.space as isize); + for _ in 0..n { + self.space -= 1; + ptr = ptr.offset(-1); + ptr::write(ptr, 0); + } } } } @@ -542,7 +546,9 @@ impl Builder { pub fn add_slot_struct(&mut self, o: usize, value: UOffsetT, d: UOffsetT) { if value != d { self.assert_nested(); - assert!(value == self.offset() as u32, "Inline data write outside of object"); + assert!(value == self.offset() as u32, "Inline data write outside of object.\ + Write the slot_struct immediatly after \ + writing the struct slot."); self.slot(o) } } @@ -550,7 +556,11 @@ impl Builder { /// Place a `u8` at `pos` relative to the beginning /// of the underlaying buffer. pub fn place_u8(&mut self, pos: usize, value: u8) { - self.bytes[pos] = value; + use std::ptr; + unsafe { + let ptr = self.bytes.as_mut_ptr().offset(pos as isize); + ptr::write(ptr,value) + } } /// Place a `u32` with `LittleEndian` encoding at `pos` diff --git a/rust/src/iter.rs b/rust/src/iter.rs index 19ba511e58..6f5d204adc 100644 --- a/rust/src/iter.rs +++ b/rust/src/iter.rs @@ -1,18 +1,10 @@ -use std::fmt::Debug; use std::iter; +use std::mem; use std::marker::PhantomData; use byteorder::{ByteOrder, LittleEndian}; use table; -use table::Table; - -/// A trait for Structs and Tables to implement. -pub trait VectorItem { - /// Table Objects require indirection. Structs do not. - fn indirect_lookup() -> bool; - /// The size of the object in the vector. - fn inline_size() -> usize; -} +use table::{Table,TableObject}; /// An iterator over flatbuffer vectors. #[derive(Debug)] @@ -32,86 +24,6 @@ pub trait LittleEndianReader<'a> { fn size() -> usize; } -impl<'a> LittleEndianReader<'a>for u8 { - fn read(buffer: &[u8], index: usize) -> u8 { buffer[index] } - fn size() -> usize { 1 } -} - -impl<'a> LittleEndianReader<'a>for i8 { - fn read(buffer: &[u8], index: usize) -> i8 { buffer[index] as i8 } - fn size() -> usize { 1 } -} - -impl<'a> LittleEndianReader<'a>for bool { - fn read(buffer: &[u8], index: usize) -> bool { buffer[index] == 0 } - fn size() -> usize { 1 } -} - -impl<'a> LittleEndianReader<'a>for u16 { - fn read(buffer: &[u8], index: usize) -> u16 { LittleEndian::read_u16(&buffer[index..]) } - fn size() -> usize { 2 } -} - -impl<'a> LittleEndianReader<'a>for i16 { - fn read(buffer: &[u8], index: usize) -> i16 { LittleEndian::read_i16(&buffer[index..]) } - fn size() -> usize { 2 } -} - -impl<'a> LittleEndianReader<'a>for u32 { - fn read(buffer: &[u8], index: usize) -> u32 { LittleEndian::read_u32(&buffer[index..]) } - fn size() -> usize { 4 } -} - -impl<'a> LittleEndianReader<'a>for i32 { - fn read(buffer: &[u8], index: usize) -> i32 { LittleEndian::read_i32(&buffer[index..]) } - fn size() -> usize { 4 } -} - -impl<'a> LittleEndianReader<'a>for u64 { - fn read(buffer: &[u8], index: usize) -> u64 { LittleEndian::read_u64(&buffer[index..]) } - fn size() -> usize { 8 } -} - -impl<'a> LittleEndianReader<'a>for i64 { - fn read(buffer: &[u8], index: usize) -> i64 { LittleEndian::read_i64(&buffer[index..]) } - fn size() -> usize { 8 } -} - -impl<'a> LittleEndianReader<'a>for f32 { - fn read(buffer: &[u8], index: usize) -> f32 { LittleEndian::read_f32(&buffer[index..]) } - fn size() -> usize { 4 } -} - -impl<'a> LittleEndianReader<'a>for f64 { - fn read(buffer: &[u8], index: usize) -> f64 { LittleEndian::read_f64(&buffer[index..]) } - fn size() -> usize { 8 } -} - -impl<'a> LittleEndianReader<'a>for &'a str { - fn read(buffer: &[u8], index:usize) -> &str { - use std::str; - let offset = LittleEndian::read_u32(&buffer[index..]) as usize + index; - let start = offset as usize + 4; - let length = table::read_uoffset(buffer, offset as usize) as usize; - let s = &buffer[start..start+length]; - unsafe { str::from_utf8_unchecked(s) } - } - fn size() -> usize { 4 } -} - - -impl<'a, T: From> + VectorItem> LittleEndianReader<'a>for T { - fn read(buffer: &'a [u8], index: usize) -> T { - let table = if T::indirect_lookup() { - Table::from_offset(buffer, index as usize) - } else { - Table::with_pos(&buffer, index as usize) - }; - table.into() - } - fn size() -> usize { T::inline_size() } -} - impl<'a, T: LittleEndianReader<'a>> iter::Iterator for Iterator<'a, T> { type Item = T; @@ -129,12 +41,26 @@ impl<'a, T: LittleEndianReader<'a>> iter::Iterator for Iterator<'a, T> { } } -impl<'a, T: LittleEndianReader<'a> + Debug> ExactSizeIterator for Iterator<'a, T> { +impl<'a, T: LittleEndianReader<'a>> ExactSizeIterator for Iterator<'a, T> { fn len(&self) -> usize { self.len } } +impl<'a, T> Iterator<'a, T> { + /// Create a new Iterator for type `T` starting at `index` with + /// a length of `len` items of size `T`. + pub fn new(buffer: &[u8], index: usize, len: usize) -> Iterator { + Iterator { + buffer: buffer, + index: index, + len: len, + i: 0, + _marker: PhantomData + } + } +} + impl<'a, T> Default for Iterator<'a, T> { fn default() -> Iterator<'a, T> { Iterator { @@ -147,16 +73,61 @@ impl<'a, T> Default for Iterator<'a, T> { } } -impl<'a, T> Iterator<'a, T> { - /// Create a new Iterator for type `T` starting at `index` with - /// a length of `len` items of size `T`. - pub fn new(buffer: &[u8], index: usize, len: usize) -> Iterator { - Iterator { - buffer: buffer, - index: index, - len: len, - i: 0, - _marker: PhantomData +macro_rules! little_reader { + ($ty:ty) => { + impl<'a> LittleEndianReader<'a> for $ty { + fn read(buffer: &[u8], index: usize) -> $ty { buffer[index] as $ty } + fn size() -> usize { mem::size_of::<$ty>() } + } + }; + ($ty:ty, $fun:ident) => { + impl<'a> LittleEndianReader<'a> for $ty { + fn read(buffer: &[u8], index: usize) -> $ty { LittleEndian::$fun(&buffer[index..]) } + fn size() -> usize { mem::size_of::<$ty>() } } } } + +little_reader!(u8); +little_reader!(i8); +little_reader!(u16, read_u16); +little_reader!(i16, read_i16); +little_reader!(u32, read_u32); +little_reader!(i32, read_i32); +little_reader!(u64, read_u64); +little_reader!(i64, read_i64); +little_reader!(f32, read_f32); +little_reader!(f64, read_f64); + +impl<'a> LittleEndianReader<'a> for bool { + fn read(buffer: &[u8], index: usize) -> bool { buffer[index] == 0 } + fn size() -> usize { 1 } +} + +impl<'a> LittleEndianReader<'a> for &'a str { + fn read(buffer: &[u8], index:usize) -> &str { + use std::str; + let offset = LittleEndian::read_u32(&buffer[index..]) as usize + index; + let start = offset as usize + 4; + let length = table::read_uoffset(buffer, offset as usize) as usize; + let s = &buffer[start..start+length]; + unsafe { str::from_utf8_unchecked(s) } + } + fn size() -> usize { 4 } +} + + +impl<'a, T: TableObject<'a>> LittleEndianReader<'a> for T { + fn read(buffer: &'a [u8], index: usize) -> T { + let table = if T::is_struct() { + Table::with_pos(&buffer, index as usize) + } else { + Table::from_offset(buffer, index as usize) + }; + table.into() + } + fn size() -> usize { T::inline_size() } +} + + + diff --git a/rust/src/lib.rs b/rust/src/lib.rs index d6c91b9a56..a744595981 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -22,7 +22,7 @@ pub mod macros; pub use self::builder::Builder; pub use self::types::{UOffsetT, VOffsetT, SOffsetT}; -pub use self::table::Table; +pub use self::table::*; pub use self::iter::*; diff --git a/rust/src/macros.rs b/rust/src/macros.rs index fd1357a4b1..76e98af5c7 100644 --- a/rust/src/macros.rs +++ b/rust/src/macros.rs @@ -1,4 +1,4 @@ -//! TODO +//! Macros to generate code for Flatbuffer objects. #[macro_export] macro_rules! table_fn { @@ -93,11 +93,17 @@ macro_rules! struct_get_fn { } #[macro_export] -macro_rules! table_struct { +macro_rules! basic_struct_def { ($name:ident) => { #[derive(Debug)] pub struct $name<'a>($crate::Table<'a>); + impl<'a> $name<'a> { + pub fn new(table: $crate::Table) -> $name { + $name ( table ) + } + } + impl<'a> From<$crate::Table<'a>> for $name<'a> { fn from(table: $crate::Table) -> $name { $name(table) @@ -107,10 +113,10 @@ macro_rules! table_struct { } #[macro_export] -macro_rules! vector_item { +macro_rules! table_object_trait { ($name:ident, $indirect:expr, $inline_size:expr) => { - impl<'a> $crate::VectorItem for $name<'a> { - fn indirect_lookup() -> bool { + impl<'a> $crate::TableObject<'a> for $name<'a> { + fn is_struct() -> bool { $indirect } @@ -124,28 +130,24 @@ macro_rules! vector_item { #[macro_export] macro_rules! table_object { ($name:ident, $inline_size:expr, [ $( $f:tt ),* ]) => { - table_struct!{$name} + + basic_struct_def!{$name} impl<'a> $name<'a> { - pub fn new(table: $crate::Table) -> $name { - $name ( table ) - } $( table_get_fn!{$f} )* } - vector_item!{ $name, true, $inline_size } + table_object_trait!{ $name, false, $inline_size } } } #[macro_export] macro_rules! struct_object { ($name:ident, $inline_size:expr, [ $( $f:tt ),* ]) => { - table_struct!{$name} + + basic_struct_def!{$name} impl<'a> $name<'a> { - pub fn new(table: $crate::Table) -> $name { - $name ( table ) - } $( struct_get_fn!{$f} )* } - vector_item!{ $name, false, $inline_size } + table_object_trait!{ $name, true, $inline_size } } } @@ -153,6 +155,7 @@ macro_rules! struct_object { macro_rules! simple_enum { ($type_name:ident, $repr:ident, [ $( ($e_name:ident, $value:expr) ),+ ]) => { + #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] #[repr($repr)] pub enum $type_name { @@ -172,7 +175,11 @@ macro_rules! simple_enum { #[macro_export] macro_rules! union { - ($name:ident, $type_name:ident, $repr:ident, [ $( ($e_name:ident, $value:expr, $ty:ty) ),+ ]) => { + ($name:ident, + $type_name:ident, + $repr:ident, + [ $( ($e_name:ident, $value:expr, $ty:ty) ),+ ]) => { + #[derive(Debug)] pub enum $name<'a> { None, @@ -191,16 +198,3 @@ macro_rules! union { simple_enum!($type_name, $repr, [ $( ($e_name, $value) ),+ ]); }; } - -// union!{Any, AnyType, u8, [(Monster, 1, Monster<'a>)]} - - -// table!{Monster, [ (get_u16, u16, hp, 8, 150), -// (get_i16, i16, mana, 10, 150), -// (byte_vector, u8, test, 11), -// (ibyte_vector, i8, test2, 11), -// (bool_vector, bool, test3, 11) -// ]} - -// simple_struct!{Vec3, BuildVec3, build_vec3, [ (get_u16, u16, hp, 8, 150), -// (get_i16, i16, mana, 10, 150)]} diff --git a/rust/src/table.rs b/rust/src/table.rs index 68fa5d5059..aacdb331f3 100644 --- a/rust/src/table.rs +++ b/rust/src/table.rs @@ -3,6 +3,15 @@ use byteorder::{ByteOrder, LittleEndian}; use types::*; use iter::Iterator; +/// A trait for Structs and Tables to implement. +pub trait TableObject<'a>: From> { + /// Table Objects require indirection. Structs do not. + fn is_struct() -> bool; + /// The size of the object in the vector. + fn inline_size() -> usize; +} + + /// Table provides functions to read Flatbuffer data. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub struct Table<'a> { @@ -218,8 +227,6 @@ impl<'a> Table<'a> { "" } - - /// Returns the struct `T` value of the field at the offset written in the /// vtable `slot`. pub fn get_slot_struct>>(&self, slot: VOffsetT) -> Option { From cda4752db2bc9d0458bca581b5e2b269c527dfc3 Mon Sep 17 00:00:00 2001 From: Joseph Dunne Date: Tue, 7 Jun 2016 00:43:41 +0100 Subject: [PATCH 5/7] Refactored Table ownership and iterators --- rust/Cargo.lock | 2 +- rust/Cargo.toml | 2 +- rust/src/bin/test.rs | 13 ++- rust/src/builder.rs | 61 ++---------- rust/src/iter.rs | 191 +++++++++++++++++++++--------------- rust/src/macros.rs | 16 +-- rust/src/table.rs | 51 +++++----- src/idl_gen_rust.cpp | 2 +- tests/MyGame/Example/Any.rs | 4 +- 9 files changed, 166 insertions(+), 176 deletions(-) diff --git a/rust/Cargo.lock b/rust/Cargo.lock index 0985e001d4..49b38e5a13 100644 --- a/rust/Cargo.lock +++ b/rust/Cargo.lock @@ -1,6 +1,6 @@ [root] name = "flatbuffers" -version = "0.2.1" +version = "0.3.0" dependencies = [ "byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 93e6a38886..50901d2823 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "flatbuffers" -version = "0.2.1" +version = "0.3.0" authors = ["Joseph Dunne "] description = "Memory Efficient Serialization Library. Flatbuffers runtime for Rust." keywords = ["flatbuffers", "serialization", "deserialization"] diff --git a/rust/src/bin/test.rs b/rust/src/bin/test.rs index b6936fc132..68bb876fab 100644 --- a/rust/src/bin/test.rs +++ b/rust/src/bin/test.rs @@ -9,6 +9,7 @@ fn main() { #[cfg(test)] #[cfg(feature = "test_idl_gen")] mod test { + use std::rc::Rc; #[allow(non_snake_case,dead_code,unused_imports, non_camel_case_types)] mod MyGame; @@ -162,7 +163,8 @@ mod test { let mut reader = BufReader::new(f1); let mut buf: Vec = Vec::new(); reader.read_to_end(&mut buf).unwrap(); - let table = Table::from_offset(&buf, 0); + let rc = Rc::new(buf); + let table = Table::from_offset(rc.clone(), 0); let monster = example::monster::Monster::new(table); let got = monster.hp(); assert!(got == 80, "bad {}: want {:?} got {:?}", "HP", 80, got); @@ -203,14 +205,15 @@ mod test { panic!( "bad {}: want {:?} got {:?}", "Test", "Monster Union", got) } let got = monster.inventory(); - assert!(got.len() == 5, "bad {}: want {:?} got {:?}", + + assert!(got.size_hint() == (5, Some(5)), "bad {}: want {:?} got {:?}", "Inventory", "Byte Vector of length 5", got); use std::ops::Add; let got: u8 = got.fold(0, Add::add); assert!(got == 10, "bad {}: want {:?} got {:?}", "Inventory Sum", "10", got); // Test4 let mut got = monster.test4(); - assert!(got.len() == 2, "bad {}: want {:?} got {:?}", "Test4 vector length", "4", got.len()); + assert!(got.size_hint() == (2, Some(2)), "bad {}: want {:?} got {:?}", "Test4 vector length", "4", got.size_hint()); let test1 = got.next().unwrap(); let test2 = got.next().unwrap(); assert!(test1.a() == 10, "bad {}: want {:?} got {:?}", "Test4 array test1.a", "10", test1.a()); @@ -219,14 +222,14 @@ mod test { assert!(test2.b() == 40, "bad {}: want {:?} got {:?}", "Test4 array test2.b", "40", test2.b()); // Test Array of string let mut got = monster.testarrayofstring(); - assert!(got.len() == 2, "bad {}: want {:?} got {:?}", "Test4 string vector length", "2", got.len()); + assert!(got.size_hint() == (2, Some(2)), "bad {}: want {:?} got {:?}", "Test4 string vector length", "2", got.size_hint()); let str1 = got.next().unwrap(); let str2 = got.next().unwrap(); assert!(str1 == "test1", "bad {}: want {:?} got {:?}", "Test string array 1", "test1", str1); assert!(str2 == "test2", "bad {}: want {:?} got {:?}", "Test string array 2", "test2", str2); // array of tables let got = monster.testarrayoftables(); - assert_eq!(got.len(),0); + assert_eq!(got.size_hint(),(0, Some(0))); } diff --git a/rust/src/builder.rs b/rust/src/builder.rs index ccc873e09a..b7ca379508 100644 --- a/rust/src/builder.rs +++ b/rust/src/builder.rs @@ -5,7 +5,6 @@ use byteorder::{ByteOrder, LittleEndian}; use types::*; -use table::Table; /// Builder provides functions to build Flatbuffer data. /// @@ -76,20 +75,6 @@ impl Builder { self.write_vtable() } - /// Read a completed object at offset. - /// - /// The offset is the `UOffsetT` returned by `end_object`. - pub fn read_object(&self, offset: UOffsetT) -> Table { - Table::with_pos(&self.bytes, self.bytes.len() - offset as usize) - } - - /// Read a completed object at offset. - /// - /// The offset is the `UOffsetT` returned by `end_table`. - pub fn read_table(&self, offset: UOffsetT) -> Table { - Table::from_offset(&self.bytes, self.bytes.len() - offset as usize) - } - /// Initializes bookkeeping for writing a new vector. pub fn start_vector(&mut self, elem_size: usize, num_elems: usize, alignment: usize) { self.assert_not_nested(); @@ -870,7 +855,7 @@ mod test { b.start_object(1); check(&b, 30, &[]); b.add_slot_bool(0, true, false); - let obj = b.end_object(); + b.end_object(); check(&b, 31, &[ 6, 0, // vtable bytes 8, 0, // length of object including vtable offset @@ -879,14 +864,6 @@ mod test { 0, 0, 0, // padded to 4 bytes 1, // bool value ]); - { - let read_obj = b.read_object(obj); - let o = read_obj.field_offset(4); - let got = read_obj.get_bool(o); - assert!(got == true, "Failed to read back last object - got {:?} expected true", got); - let got = read_obj.get_u8(o); - assert!(got == 1, "Failed to read back last object. wrong value expected 1 got {}", got); - } // test 9: vtable with one default bool @@ -1099,14 +1076,14 @@ mod test { b.add_slot_i8(0, 33, 0); b.add_slot_i8(1, 44, 0); let obj1 = b.end_object(); - let table1 = b.finish_table(obj1); + b.finish_table(obj1); b.start_object(3); b.add_slot_i8(0, 55, 0); b.add_slot_i8(1, 66, 0); b.add_slot_i8(2, 77, 0); let obj2 = b.end_object(); - let table2 = b.finish_table(obj2); + b.finish_table(obj2); check(&b, 43, &[ 16, 0, 0, 0, // root of table: points to object @@ -1135,29 +1112,6 @@ mod test { 33, // value 0 ]); assert!(b.offset() as usize + b.pos() == b.len()); - { - let read_obj = b.read_object(obj1); - let o = read_obj.field_offset(4); - let got = read_obj.get_u8(o); - assert!(got == 33, "Failed to read back last object - got {:?} expected 33", got); - let read_table = b.read_table(table1); - let o = read_table.field_offset(6); - let got = read_table.get_u8(o); - assert!(got == 44, "Failed to read back last object - got {:?} expected 44", got); - - let read_obj = b.read_object(obj2); - let o = read_obj.field_offset(4); - let got = read_obj.get_u8(o); - assert!(got == 55, "Failed to read back last object - got {:?} expected 55", got); - let read_table = b.read_table(table2); - let o = read_table.field_offset(6); - let got = read_table.get_u8(o); - assert!(got == 66, "Failed to read back last object - got {:?} expected 66", got); - let o = read_table.field_offset(8); - let got = read_table.get_u8(o); - assert!(got == 77, "Failed to read back last object - got {:?} expected 77", got); - } - // test 18: a bunch of bools b = Builder::with_capacity(0); @@ -1291,11 +1245,12 @@ mod test { ]; assert!(got == want, "testVtableDeduplication want:\n{} {:?}\nbut got:\n{} {:?}\n", want.len(), want, got.len(), got); - + use std::rc::Rc; let len = got.len(); - let table0 = Table::with_pos(got, len - obj0 as usize); - let table1 = Table::with_pos(got, len - obj1 as usize); - let table2 = Table::with_pos(got, len - obj2 as usize); + let rc = Rc::new(got.to_vec()); + let table0 = Table::with_pos(rc.clone(), len - obj0 as usize); + let table1 = Table::with_pos(rc.clone(), len - obj1 as usize); + let table2 = Table::with_pos(rc, len - obj2 as usize); fn test_table(tab: &Table, a: VOffsetT, b: u8, c: u8, d: u8) { let got = tab.read_voffset_slot(0, 0); if 12 != got { diff --git a/rust/src/iter.rs b/rust/src/iter.rs index 6f5d204adc..fd2fc4b2aa 100644 --- a/rust/src/iter.rs +++ b/rust/src/iter.rs @@ -1,5 +1,5 @@ use std::iter; -use std::mem; +use std::rc::Rc; use std::marker::PhantomData; use byteorder::{ByteOrder, LittleEndian}; @@ -9,50 +9,19 @@ use table::{Table,TableObject}; /// An iterator over flatbuffer vectors. #[derive(Debug)] pub struct Iterator<'a, T> { - buffer: &'a [u8], + buffer: Option<&'a Rc>>, index: usize, len: usize, i: usize, - _marker: PhantomData<[T]> -} - -/// A trait for handling little endian encoding of byte arrays. -pub trait LittleEndianReader<'a> { - /// Read the first byte from buffer and return type `Self`. - fn read(buffer: &'a [u8], index: usize) -> Self; - /// Provide the size in bytes of type `Self`. - fn size() -> usize; -} - -impl<'a, T: LittleEndianReader<'a>> iter::Iterator for Iterator<'a, T> { - type Item = T; - - fn next(&mut self) -> Option { - if self.i < self.len { - self.i += 1; - let slice = &self.buffer[self.index..]; - if slice.len() >= T::size() { - let res = T::read(self.buffer, self.index); - self.index += T::size(); - return Some(res) - } - } - None - } -} - -impl<'a, T: LittleEndianReader<'a>> ExactSizeIterator for Iterator<'a, T> { - fn len(&self) -> usize { - self.len - } + _marker: PhantomData } impl<'a, T> Iterator<'a, T> { /// Create a new Iterator for type `T` starting at `index` with /// a length of `len` items of size `T`. - pub fn new(buffer: &[u8], index: usize, len: usize) -> Iterator { + pub fn new(buffer: &Rc>, index: usize, len: usize) -> Iterator { Iterator { - buffer: buffer, + buffer: Some(buffer), index: index, len: len, i: 0, @@ -64,7 +33,7 @@ impl<'a, T> Iterator<'a, T> { impl<'a, T> Default for Iterator<'a, T> { fn default() -> Iterator<'a, T> { Iterator { - buffer: &[], + buffer: None, index: 0, len: 0, i: 0, @@ -73,61 +42,123 @@ impl<'a, T> Default for Iterator<'a, T> { } } -macro_rules! little_reader { - ($ty:ty) => { - impl<'a> LittleEndianReader<'a> for $ty { - fn read(buffer: &[u8], index: usize) -> $ty { buffer[index] as $ty } - fn size() -> usize { mem::size_of::<$ty>() } - } - }; - ($ty:ty, $fun:ident) => { - impl<'a> LittleEndianReader<'a> for $ty { - fn read(buffer: &[u8], index: usize) -> $ty { LittleEndian::$fun(&buffer[index..]) } - fn size() -> usize { mem::size_of::<$ty>() } +macro_rules! size_hint { + () => { + fn size_hint(&self) -> (usize, Option) { + (self.len, Some(self.len)) } } } -little_reader!(u8); -little_reader!(i8); -little_reader!(u16, read_u16); -little_reader!(i16, read_i16); -little_reader!(u32, read_u32); -little_reader!(i32, read_i32); -little_reader!(u64, read_u64); -little_reader!(i64, read_i64); -little_reader!(f32, read_f32); -little_reader!(f64, read_f64); - -impl<'a> LittleEndianReader<'a> for bool { - fn read(buffer: &[u8], index: usize) -> bool { buffer[index] == 0 } - fn size() -> usize { 1 } -} +impl<'a> iter::Iterator for Iterator<'a, &'a str> { + type Item = &'a str; -impl<'a> LittleEndianReader<'a> for &'a str { - fn read(buffer: &[u8], index:usize) -> &str { + fn next(&mut self) -> Option<&'a str> { use std::str; - let offset = LittleEndian::read_u32(&buffer[index..]) as usize + index; - let start = offset as usize + 4; - let length = table::read_uoffset(buffer, offset as usize) as usize; - let s = &buffer[start..start+length]; - unsafe { str::from_utf8_unchecked(s) } + if self.i < self.len { + self.i += 1; + if self.buffer.unwrap().len() >= self.index + 4 { + let offset = LittleEndian::read_u32(&self.buffer.unwrap()[self.index..]) as usize + self.index; + let start = offset as usize + 4; + let length = table::read_uoffset(self.buffer.unwrap(), offset as usize) as usize; + let s = &self.buffer.unwrap()[start..start+length]; + let res = unsafe { str::from_utf8_unchecked(s) }; + self.index += 4; + return Some(res) + } + } + None } - fn size() -> usize { 4 } + size_hint!(); } +impl<'a, T: TableObject> iter::Iterator for Iterator<'a, T> { + type Item = T; + + fn next(&mut self) -> Option { + if self.i < self.len { + self.i += 1; + if self.buffer.unwrap().len() >= self.index + T::inline_size() { + let table = if T::is_struct() { + Table::with_pos(self.buffer.unwrap().clone(), self.index as usize) + } else { + Table::from_offset(self.buffer.unwrap().clone(), self.index as usize) + }; + let res = table.into(); + self.index += T::inline_size(); + return Some(res) + } + } + None + } + size_hint!(); +} -impl<'a, T: TableObject<'a>> LittleEndianReader<'a> for T { - fn read(buffer: &'a [u8], index: usize) -> T { - let table = if T::is_struct() { - Table::with_pos(&buffer, index as usize) - } else { - Table::from_offset(buffer, index as usize) - }; - table.into() +impl<'a> iter::Iterator for Iterator<'a, bool> { + type Item = bool; + + fn next(&mut self) -> Option { + if self.i < self.len { + self.i += 1; + if self.buffer.unwrap().len() >= self.index + 1 { + let res = self.buffer.unwrap()[self.index] == 0; + self.index += 1; + return Some(res) + } + } + None + } + size_hint!(); +} + +macro_rules! little_iterator { + ($ty:ty) => { + impl<'a> iter::Iterator for Iterator<'a, $ty> { + type Item = $ty; + + fn next(&mut self) -> Option<$ty> { + if self.i < self.len { + self.i += 1; + if self.buffer.unwrap().len() >= self.index + 1 { + let res = self.buffer.unwrap()[self.index] as $ty; + self.index += 1; + return Some(res) + } + } + None + } + size_hint!(); + } + }; + ($ty:ty, $size:expr, $fun:ident) => { + impl<'a> iter::Iterator for Iterator<'a, $ty> { + type Item = $ty; + + fn next(&mut self) -> Option<$ty> { + if self.i < self.len { + self.i += 1; + if self.buffer.unwrap().len() >= self.index + $size { + let res = LittleEndian::$fun(&self.buffer.unwrap()[self.index..]); + self.index += $size; + return Some(res) + } + } + None + } + size_hint!(); + } } - fn size() -> usize { T::inline_size() } } +little_iterator!(u8); +little_iterator!(i8); +little_iterator!(u16, 2, read_u16); +little_iterator!(i16, 2, read_i16); +little_iterator!(u32, 4, read_u32); +little_iterator!(i32, 4, read_i32); +little_iterator!(u64, 8, read_u64); +little_iterator!(i64, 8, read_i64); +little_iterator!(f32, 4, read_f32); +little_iterator!(f64, 8, read_f64); diff --git a/rust/src/macros.rs b/rust/src/macros.rs index 76e98af5c7..f274b7dd4d 100644 --- a/rust/src/macros.rs +++ b/rust/src/macros.rs @@ -96,15 +96,15 @@ macro_rules! struct_get_fn { macro_rules! basic_struct_def { ($name:ident) => { #[derive(Debug)] - pub struct $name<'a>($crate::Table<'a>); + pub struct $name($crate::Table); - impl<'a> $name<'a> { + impl $name { pub fn new(table: $crate::Table) -> $name { $name ( table ) } } - impl<'a> From<$crate::Table<'a>> for $name<'a> { + impl From<$crate::Table> for $name { fn from(table: $crate::Table) -> $name { $name(table) } @@ -115,7 +115,7 @@ macro_rules! basic_struct_def { #[macro_export] macro_rules! table_object_trait { ($name:ident, $indirect:expr, $inline_size:expr) => { - impl<'a> $crate::TableObject<'a> for $name<'a> { + impl $crate::TableObject for $name { fn is_struct() -> bool { $indirect } @@ -132,7 +132,7 @@ macro_rules! table_object { ($name:ident, $inline_size:expr, [ $( $f:tt ),* ]) => { basic_struct_def!{$name} - impl<'a> $name<'a> { + impl $name { $( table_get_fn!{$f} )* } table_object_trait!{ $name, false, $inline_size } @@ -144,7 +144,7 @@ macro_rules! struct_object { ($name:ident, $inline_size:expr, [ $( $f:tt ),* ]) => { basic_struct_def!{$name} - impl<'a> $name<'a> { + impl $name { $( struct_get_fn!{$f} )* } table_object_trait!{ $name, true, $inline_size } @@ -181,12 +181,12 @@ macro_rules! union { [ $( ($e_name:ident, $value:expr, $ty:ty) ),+ ]) => { #[derive(Debug)] - pub enum $name<'a> { + pub enum $name { None, $( $e_name( $ty ) ),+ } - impl<'a> $name<'a> { + impl $name { pub fn new(table: $crate::Table, utype: Option<$type_name>) -> Option<$name> { match utype { $( Some($type_name::$e_name) => Some( $name::$e_name( table.into() ) ), )* diff --git a/rust/src/table.rs b/rust/src/table.rs index aacdb331f3..aa441520b6 100644 --- a/rust/src/table.rs +++ b/rust/src/table.rs @@ -1,10 +1,11 @@ +use std::rc::Rc; use byteorder::{ByteOrder, LittleEndian}; use types::*; use iter::Iterator; /// A trait for Structs and Tables to implement. -pub trait TableObject<'a>: From> { +pub trait TableObject: From { /// Table Objects require indirection. Structs do not. fn is_struct() -> bool; /// The size of the object in the vector. @@ -13,13 +14,13 @@ pub trait TableObject<'a>: From> { /// Table provides functions to read Flatbuffer data. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Table<'a> { - buffer: &'a [u8], - pos: usize +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct Table { + buffer: Rc>, + pos: usize, } -impl<'a> Table<'a> { +impl Table { /// Create a table using from a slice using data starting at `pos`. /// First `UOffsetT` should indicate the offset from the root /// of the table to the begining of the object. @@ -39,11 +40,11 @@ impl<'a> Table<'a> { /// 66, // value 1 /// 55, // value 0 /// ``` - pub fn from_offset(buffer: &[u8], pos: usize) -> Table { + pub fn from_offset(buffer: Rc>, pos: usize) -> Table { let n = read_uoffset(&buffer, pos); Table { buffer: buffer, - pos: n as usize + pos + pos: n as usize + pos } } @@ -66,7 +67,7 @@ impl<'a> Table<'a> { /// 66, // value 1 /// 55, // value 0 /// ``` - pub fn with_pos(buffer: &[u8], pos: usize) -> Table { + pub fn with_pos(buffer: Rc>, pos: usize) -> Table { Table { buffer: buffer, pos: pos @@ -76,13 +77,13 @@ impl<'a> Table<'a> { /// Return an object table at offset. /// See `from_offset`. pub fn get_root(&self, offset: UOffsetT) -> Table { - Table::from_offset(self.buffer, self.pos + offset as usize) + Table::from_offset(self.buffer.clone(), self.pos + offset as usize) } /// Return an object table at offset specified by offset. pub fn get_indirect_root(&self, offset: UOffsetT) -> Table { let actual_offset = self.pos as u32 + offset + self.get_u32(offset); - Table::with_pos(&self.buffer, actual_offset as usize) + Table::with_pos(self.buffer.clone(), actual_offset as usize) } @@ -229,7 +230,7 @@ impl<'a> Table<'a> { /// Returns the struct `T` value of the field at the offset written in the /// vtable `slot`. - pub fn get_slot_struct>>(&self, slot: VOffsetT) -> Option { + pub fn get_slot_struct>(&self, slot: VOffsetT) -> Option { let offset = self.field_offset(slot); if offset != 0 { return Some(self.get_struct(offset)) @@ -239,7 +240,7 @@ impl<'a> Table<'a> { /// Returns the unsigned byte vector value of the field at the offset written in the /// vtable `slot`. - pub fn get_slot_vector(&self, slot: VOffsetT) -> Iterator<'a, T> { + pub fn get_slot_vector(&self, slot: VOffsetT) -> Iterator { let offset = self.field_offset(slot); if offset != 0 { return self.get_vector::(offset) @@ -249,11 +250,11 @@ impl<'a> Table<'a> { /// ByteVector gets an unsigned byte slice from data stored inside /// the flatbuffer. - pub fn get_vector(&self, offset: UOffsetT) -> Iterator<'a, T> { + pub fn get_vector(&self, offset: UOffsetT) -> Iterator { let mut offset = offset as usize + self.pos; - offset += read_uoffset(self.buffer, offset) as usize; + offset += read_uoffset(&*self.buffer, offset) as usize; let start = offset + UOFFSETT_SIZE; - let length = read_uoffset(self.buffer, offset) as usize; + let length = read_uoffset(&*self.buffer, offset) as usize; Iterator::new(&self.buffer, start, length) } @@ -327,18 +328,18 @@ impl<'a> Table<'a> { pub fn get_str(&self, offset: UOffsetT) -> &str { use std::str; let mut offset = offset + self.pos as UOffsetT; - offset += read_uoffset(self.buffer, offset as usize); + offset += read_uoffset(&*self.buffer, offset as usize); let start = offset as usize + 4 as usize; - let length = read_uoffset(self.buffer, offset as usize) as usize; + let length = read_uoffset(&*self.buffer, offset as usize) as usize; let s = &self.buffer[start..start+length]; unsafe { str::from_utf8_unchecked(s) } } /// Retrieve a struct table from offset. Offset should point to then /// first usable byte of data i.e. the Vtable offset. - pub fn get_struct>>(&self, offset: UOffsetT) -> T { + pub fn get_struct>(&self, offset: UOffsetT) -> T { let pos = self.pos as UOffsetT + offset; - let table = Table::with_pos(self.buffer, pos as usize); + let table = Table::with_pos(self.buffer.clone(), pos as usize); table.into() } @@ -350,12 +351,12 @@ impl<'a> Table<'a> { /// Reads an `UOffsetT` at exact position. pub fn read_uoffset(&self, offset: UOffsetT) -> UOffsetT { - read_uoffset(self.buffer, offset as usize) + read_uoffset(&*self.buffer, offset as usize) } /// Reads an `VOffsetT` at exact position. pub fn read_voffset(&self, offset: UOffsetT) -> VOffsetT { - read_voffset(self.buffer, offset as usize) + read_voffset(&*self.buffer, offset as usize) } /// Retrieves the `VOffsetT` in the vtable `slot`. @@ -371,7 +372,7 @@ impl<'a> Table<'a> { /// Get a reference to the raw buffer #[inline] pub fn get_bytes(&self) -> &[u8] { - self.buffer + &*self.buffer } } @@ -390,8 +391,8 @@ pub fn read_voffset(buf: &[u8], offset: usize) -> VOffsetT { LittleEndian::read_u16(&buf[offset as usize..]) } -impl<'a> From<&'a [u8]> for Table<'a> { - fn from(buf: &[u8]) -> Table { +impl From>> for Table { + fn from(buf: Rc>,) -> Table { Table::from_offset(buf, 0) } } diff --git a/src/idl_gen_rust.cpp b/src/idl_gen_rust.cpp index 0cf532fb76..b300da58b9 100644 --- a/src/idl_gen_rust.cpp +++ b/src/idl_gen_rust.cpp @@ -482,7 +482,7 @@ static void GenEnum(const EnumDef &enum_def, std::string *code_ptr) { } if (enum_def.is_union) { code += Indent + "(" + ev.name +", "+NumToString(ev.value); - code += ", " + ev.name + "<'a>"; + code += ", " + ev.name; code += ")"; } else { diff --git a/tests/MyGame/Example/Any.rs b/tests/MyGame/Example/Any.rs index 35d2e150de..68a45e9b9e 100644 --- a/tests/MyGame/Example/Any.rs +++ b/tests/MyGame/Example/Any.rs @@ -4,6 +4,6 @@ use flatbuffers; use super::*; union!{Any,AnyType,u8, [ - (Monster, 1, Monster<'a>), - (TestSimpleTableWithEnum, 2, TestSimpleTableWithEnum<'a>)]} + (Monster, 1, Monster), + (TestSimpleTableWithEnum, 2, TestSimpleTableWithEnum)]} From 74f0676fefb6922ebdbd8130d82723587d63bbe6 Mon Sep 17 00:00:00 2001 From: Joseph Dunne Date: Thu, 16 Jun 2016 06:34:23 +0100 Subject: [PATCH 6/7] next refactor --- rust/macros/Cargo.toml | 22 + rust/macros/src/lib.rs | 385 ++++++++ rust/macros/src/table.rs | 85 ++ rust/macros/src/union.rs | 101 +++ rust/macros/src/utils.rs | 287 ++++++ rust/macros/tests/compile-fail/empty_field.rs | 11 + .../tests/compile-fail/expected_field.rs | 11 + rust/macros/tests/compile-fail/fat_arrow.rs | 9 + .../tests/compile-fail/fat_arrow_name.rs | 8 + rust/macros/tests/compile-fail/first_ident.rs | 9 + .../tests/compile-fail/invalid_field.rs | 11 + .../tests/compile-fail/invalid_field_attr.rs | 14 + .../tests/compile-fail/invalid_other_field.rs | 15 + .../macros/tests/compile-fail/missing_name.rs | 11 + .../tests/compile-fail/name_no_fields.rs | 9 + rust/macros/tests/compile-fail/slot_int.rs | 11 + rust/macros/tests/run-pass/enum.rs | 12 + rust/macros/tests/run-pass/no_fields.rs | 14 + rust/macros/tests/run-pass/struct.rs | 34 + rust/macros/tests/run-pass/table.rs | 37 + rust/macros/tests/run-pass/union.rs | 15 + rust/macros/tests/tests.rs | 21 + rust/src/bin/test.rs | 482 +++++----- rust/src/bin/test/MyGame/Example/Any.rs | 61 -- rust/src/bin/test/MyGame/Example/Color.rs | 35 - rust/src/bin/test/MyGame/Example/Monster.rs | 534 ----------- rust/src/bin/test/MyGame/Example/Stat.rs | 157 ---- rust/src/bin/test/MyGame/Example/Test.rs | 49 - .../MyGame/Example/TestSimpleTableWithEnum.rs | 129 --- rust/src/bin/test/MyGame/Example/Vec3.rs | 82 -- rust/src/bin/test/MyGame/Example/mod.rs | 18 - rust/src/bin/test/MyGame/mod.rs | 5 - rust/src/builder.rs | 708 +++++++-------- rust/src/iter.rs | 236 +++-- rust/src/lib.rs | 7 +- rust/src/macros.rs | 29 +- rust/src/new_macros.rs | 285 ++++++ rust/src/table.rs | 288 +++--- samples/rust/Cargo.toml | 7 + samples/rust/src/main.rs | 3 + src/idl_gen_rust.cpp | 181 ++-- tests/MyGame/Example/Any.cs | 14 - tests/MyGame/Example/Any.java | 15 - tests/MyGame/Example/Any.php | 25 - tests/MyGame/Example/Any.py | 9 - tests/MyGame/Example/Any.rs | 4 +- tests/MyGame/Example/Color.cs | 14 - tests/MyGame/Example/Color.java | 15 - tests/MyGame/Example/Color.php | 25 - tests/MyGame/Example/Color.py | 9 - tests/MyGame/Example/Color.rs | 5 +- tests/MyGame/Example/Monster.cs | 130 --- tests/MyGame/Example/Monster.java | 134 --- tests/MyGame/Example/Monster.php | 835 ------------------ tests/MyGame/Example/Monster.py | 320 ------- tests/MyGame/Example/Monster.rs | 128 ++- tests/MyGame/Example/Stat.cs | 43 - tests/MyGame/Example/Stat.java | 43 - tests/MyGame/Example/Stat.php | 136 --- tests/MyGame/Example/Stat.py | 39 - tests/MyGame/Example/Stat.rs | 17 +- tests/MyGame/Example/Test.cs | 27 - tests/MyGame/Example/Test.java | 27 - tests/MyGame/Example/Test.php | 53 -- tests/MyGame/Example/Test.py | 24 - tests/MyGame/Example/Test.rs | 13 +- .../MyGame/Example/TestSimpleTableWithEnum.cs | 33 - .../Example/TestSimpleTableWithEnum.java | 33 - .../Example/TestSimpleTableWithEnum.php | 99 --- .../MyGame/Example/TestSimpleTableWithEnum.py | 23 - .../MyGame/Example/TestSimpleTableWithEnum.rs | 7 +- tests/MyGame/Example/Vec3.cs | 44 - tests/MyGame/Example/Vec3.java | 44 - tests/MyGame/Example/Vec3.php | 96 -- tests/MyGame/Example/Vec3.py | 44 - tests/MyGame/Example/Vec3.rs | 34 +- tests/MyGame/Example/__init__.py | 0 tests/MyGame/__init__.py | 0 tests/RustTest.sh | 2 + 79 files changed, 2560 insertions(+), 4431 deletions(-) create mode 100644 rust/macros/Cargo.toml create mode 100644 rust/macros/src/lib.rs create mode 100644 rust/macros/src/table.rs create mode 100644 rust/macros/src/union.rs create mode 100644 rust/macros/src/utils.rs create mode 100644 rust/macros/tests/compile-fail/empty_field.rs create mode 100644 rust/macros/tests/compile-fail/expected_field.rs create mode 100644 rust/macros/tests/compile-fail/fat_arrow.rs create mode 100644 rust/macros/tests/compile-fail/fat_arrow_name.rs create mode 100644 rust/macros/tests/compile-fail/first_ident.rs create mode 100644 rust/macros/tests/compile-fail/invalid_field.rs create mode 100644 rust/macros/tests/compile-fail/invalid_field_attr.rs create mode 100644 rust/macros/tests/compile-fail/invalid_other_field.rs create mode 100644 rust/macros/tests/compile-fail/missing_name.rs create mode 100644 rust/macros/tests/compile-fail/name_no_fields.rs create mode 100644 rust/macros/tests/compile-fail/slot_int.rs create mode 100644 rust/macros/tests/run-pass/enum.rs create mode 100644 rust/macros/tests/run-pass/no_fields.rs create mode 100644 rust/macros/tests/run-pass/struct.rs create mode 100644 rust/macros/tests/run-pass/table.rs create mode 100644 rust/macros/tests/run-pass/union.rs create mode 100644 rust/macros/tests/tests.rs delete mode 100644 rust/src/bin/test/MyGame/Example/Any.rs delete mode 100644 rust/src/bin/test/MyGame/Example/Color.rs delete mode 100644 rust/src/bin/test/MyGame/Example/Monster.rs delete mode 100644 rust/src/bin/test/MyGame/Example/Stat.rs delete mode 100644 rust/src/bin/test/MyGame/Example/Test.rs delete mode 100644 rust/src/bin/test/MyGame/Example/TestSimpleTableWithEnum.rs delete mode 100644 rust/src/bin/test/MyGame/Example/Vec3.rs delete mode 100644 rust/src/bin/test/MyGame/Example/mod.rs delete mode 100644 rust/src/bin/test/MyGame/mod.rs create mode 100644 rust/src/new_macros.rs create mode 100644 samples/rust/Cargo.toml create mode 100644 samples/rust/src/main.rs delete mode 100644 tests/MyGame/Example/Any.cs delete mode 100644 tests/MyGame/Example/Any.java delete mode 100644 tests/MyGame/Example/Any.php delete mode 100644 tests/MyGame/Example/Any.py delete mode 100644 tests/MyGame/Example/Color.cs delete mode 100644 tests/MyGame/Example/Color.java delete mode 100644 tests/MyGame/Example/Color.php delete mode 100644 tests/MyGame/Example/Color.py delete mode 100644 tests/MyGame/Example/Monster.cs delete mode 100644 tests/MyGame/Example/Monster.java delete mode 100644 tests/MyGame/Example/Monster.php delete mode 100644 tests/MyGame/Example/Monster.py delete mode 100644 tests/MyGame/Example/Stat.cs delete mode 100644 tests/MyGame/Example/Stat.java delete mode 100644 tests/MyGame/Example/Stat.php delete mode 100644 tests/MyGame/Example/Stat.py delete mode 100644 tests/MyGame/Example/Test.cs delete mode 100644 tests/MyGame/Example/Test.java delete mode 100644 tests/MyGame/Example/Test.php delete mode 100644 tests/MyGame/Example/Test.py delete mode 100644 tests/MyGame/Example/TestSimpleTableWithEnum.cs delete mode 100644 tests/MyGame/Example/TestSimpleTableWithEnum.java delete mode 100644 tests/MyGame/Example/TestSimpleTableWithEnum.php delete mode 100644 tests/MyGame/Example/TestSimpleTableWithEnum.py delete mode 100644 tests/MyGame/Example/Vec3.cs delete mode 100644 tests/MyGame/Example/Vec3.java delete mode 100644 tests/MyGame/Example/Vec3.php delete mode 100644 tests/MyGame/Example/Vec3.py delete mode 100644 tests/MyGame/Example/__init__.py delete mode 100644 tests/MyGame/__init__.py diff --git a/rust/macros/Cargo.toml b/rust/macros/Cargo.toml new file mode 100644 index 0000000000..986c6a52df --- /dev/null +++ b/rust/macros/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "flatbuffers_macros" +version = "0.1.0" +authors = ["Joseph Dunne "] +license = "Apache-2.0" +description = "Macros for generating flatbuffer objects" +keywords = ["flatbuffers"] + + +[lib] +plugin = true + +[dependencies] +regex = "*" + +[dev-dependencies] +compiletest_rs = "*" + +[dev-dependencies.flatbuffers] +path = "../" +version = ">=0.0" + diff --git a/rust/macros/src/lib.rs b/rust/macros/src/lib.rs new file mode 100644 index 0000000000..2709791fb7 --- /dev/null +++ b/rust/macros/src/lib.rs @@ -0,0 +1,385 @@ +#![crate_type = "dylib"] +#![feature(quote, plugin_registrar, rustc_private)] +extern crate rustc_plugin; +extern crate syntax; +extern crate regex; + +use syntax::ast; +use syntax::codemap; +use syntax::print; +use syntax::ext::base::{ExtCtxt, MacResult, DummyResult}; +use syntax::parse::token; +use std::ops::Deref; +use rustc_plugin::Registry; + +mod table; +mod utils; +mod union; + +use self::utils::*; + +const EXPECTED_IDENT_TABLE_ETC: &'static str = "Expected one of 'Table', 'Struct', 'Enum' or 'Union'"; +const EXPECTED_FAT_ARROW: &'static str = "Expected '=>'"; +const EXPECTED_COLON: &'static str = "Expected ':'"; +const EXPECTED_TABLE_FIELDS: &'static str = "Expected a list of fields"; +const EXPECTED_FIELD_DEF: &'static str = "Expected field"; +const INVALID_FIELD_DEF: &'static str = "Invalid field definition"; +const EXPECTED_SLOT_INT: &'static str = "Slot must be an integer"; +const UNKNOWN_ATTRIBUTE: &'static str = "Unknown attribute"; +const EXPECTED_SIZE_INT: &'static str = "Size must be an integer"; +const EXPECTED_ENUM_ITEMS: &'static str = "Expected Enum items"; +const EXPECTED_UNION_ITEMS: &'static str = "Expected Union items"; +const EXPECTED_ENUM_TYPE: &'static str = "Expected one of ubyte, byte, ushort, short, uint, int, ulong, or long"; + + +#[plugin_registrar] +pub fn plugin_registrar(registry: &mut Registry) { + registry.register_macro("flatbuffers_object", expand) +} + +fn expand(cx: &mut ExtCtxt, sp: codemap::Span, ast: &[ast::TokenTree]) -> Box { + if let Ok(res) = expand_impl(cx, sp, ast) { + res + } else { + DummyResult::any(sp) + } +} + +fn expand_impl(cx: &mut ExtCtxt, sp: codemap::Span, ast: &[ast::TokenTree]) -> Result, ()> { + if ast.len() == 0 { + cx.span_err(sp, EXPECTED_IDENT_TABLE_ETC); + return Err(()); + } + let ident = try!(expect_ident(cx, sp, &ast[0], &["Table", "Struct", "Enum", "Union"], EXPECTED_IDENT_TABLE_ETC)); + if ast.len() < 2 { + cx.span_err(sp, EXPECTED_FAT_ARROW); + return Err(()); + } + try!(consume_fat_arrow(cx, sp, &ast[1], EXPECTED_FAT_ARROW)); + let ast = &ast[2..]; + match try!(object_type(ident)) { + ObjectType::Table => expand_table_object(cx, sp, ast), + ObjectType::Struct => expand_struct_object(cx, sp, ast), + ObjectType::Enum => expand_enum_object(cx, sp, ast), + ObjectType::Union => expand_union_object(cx, sp, ast), + } +} + + +fn object_type(ident: ast::Ident) -> Result { + match ident.name.as_str().deref() { + "Table" => Ok(ObjectType::Table), + "Struct" => Ok(ObjectType::Struct), + "Enum" => Ok(ObjectType::Enum), + "Union" => Ok(ObjectType::Union), + _ => Err(()) + } +} + +fn expand_table_object(cx: &mut ExtCtxt, sp: codemap::Span, ast: &[ast::TokenTree]) -> Result, ()> { + let name = try!(get_name(cx, sp, ast, &format!("Expected a name for the {}", "Table"))); + let attributes = try!(get_attributes(cx, sp, &ast[1..])); + let ast = if attributes.len() > 0 { + &ast[2..] + } else { + &ast[1..] + }; + let fields = try!(get_obj_fields(cx, sp, ast, EXPECTED_TABLE_FIELDS, ObjectType::Table)); + table::build_table_items(cx, name, fields, attributes) +} + +fn expand_struct_object(cx: &mut ExtCtxt, sp: codemap::Span, ast: &[ast::TokenTree]) -> Result, ()> { + let name = try!(get_name(cx, sp, ast, &format!("Expected a name for the {}", "Struct"))); + let attributes = try!(get_attributes(cx, sp, &ast[1..])); + let ast = if attributes.len() > 0 { + &ast[2..] + } else { + &ast[1..] + }; + let fields = try!(get_obj_fields(cx, sp, ast, EXPECTED_TABLE_FIELDS, ObjectType::Struct)); + table::build_struct_items(cx, name, fields, attributes) +} + +fn expand_enum_object(cx: &mut ExtCtxt, sp: codemap::Span, ast: &[ast::TokenTree]) -> Result, ()> { + let name = try!(get_name(cx, sp, ast, &format!("Expected a name for the {}", "Enum"))); + let items = try!(get_enum_items(cx, sp, &ast[1], EXPECTED_ENUM_ITEMS)); + let ty = try!(get_enum_repr(cx, &ast[3], EXPECTED_ENUM_TYPE)); + union::build_simple_enum(cx, name, ty, items) +} + +fn expand_union_object(cx: &mut ExtCtxt, sp: codemap::Span, ast: &[ast::TokenTree]) -> Result, ()> { + let name = try!(get_name(cx, sp, ast, &format!("Expected a name for the {}", "Union"))); + let items = try!(get_enum_items(cx, sp, &ast[1], EXPECTED_UNION_ITEMS)); + union::build_union(cx, name, items) +} + +fn get_name(cx: &mut ExtCtxt, sp: codemap::Span, ast: &[ast::TokenTree], msg: &str) -> Result { + if ast.len() > 0 { + match ast[0] { + ast::TokenTree::Token(_, token::Token::Ident(ident)) => { + return Ok(ident.name.as_str()) + } + _ => {} + } + } + cx.span_err(sp, msg); + Err(()) +} + +fn get_attributes(cx: &mut ExtCtxt, sp: codemap::Span, ast: &[ast::TokenTree]) -> Result, ()> { + if ast.len() == 0 { + return Ok(vec![]) + } + match ast[0] { + ast::TokenTree::Delimited(_, ref delemented) => { + if delemented.delim == token::DelimToken::Paren { + return get_obj_attributes(cx, sp, delemented.as_ref()) + } + } + _ => {} + } + return Ok(vec![]) +} + +fn get_obj_attributes(cx: &mut ExtCtxt, sp: codemap::Span, ast: &ast::Delimited) -> Result, ()> { + let tts = &ast.tts; + let mut res = Vec::new(); + if tts.len() == 0 { + return Ok(res); + } + let mut i = 0; + loop { + if tts.len() < i + 3 { + cx.span_err(ast.open_span, INVALID_FIELD_DEF); + return Err(()) + } + let attribute = try!(expect_ident(cx, tts[i].get_span(), &tts[i], &["size"], EXPECTED_FIELD_DEF)); + let attribute = attribute.name.as_str().deref().to_string(); + try!(consume_colon(cx, sp, &tts[i+1], EXPECTED_COLON)); + match &*attribute { + "size" => { + let lit = try!(get_lit(cx, tts[i+2].get_span(), &tts[i+2], EXPECTED_SIZE_INT)); + if let token::Lit::Integer(size) = lit { + res.push( ObjAttribute{ + name: attribute, + value: size.as_str().deref().to_string() + } ) + } else { + cx.span_err(tts[i+2].get_span(), EXPECTED_SIZE_INT); + return Err(()) + } + } + _ => { + cx.span_warn(ast.open_span, UNKNOWN_ATTRIBUTE); + } + } + if tts.len() >= i + 4 && maybe_comma(&tts[i+3]) { + i += 4; + } else { + i += 3; + } + if tts.len() <= i { + break; + } + } + Ok(res) +} + +fn get_obj_fields(cx: &mut ExtCtxt, sp: codemap::Span, ast: &[ast::TokenTree], msg: &str, objty: ObjectType) -> Result, ()> { + if ast.len() == 0 { + cx.span_warn(sp, msg); + return Err(()) + } + match ast[0] { + ast::TokenTree::Delimited(_, ref delemented) => { + return get_obj_fields_impl(cx, sp, delemented.as_ref(), objty); + } + _ => {} + } + cx.span_err(sp, msg); + Err(()) +} + +fn get_obj_fields_impl(cx: &mut ExtCtxt, sp: codemap::Span, ast: &ast::Delimited, objty: ObjectType) -> Result, ()> { + let tts = &ast.tts; + let mut res = Vec::new(); + if tts.len() == 0 { + return Ok(res); + } + let mut i = 0; + loop { + if tts.len() < i + 3 { + cx.span_err(ast.open_span, INVALID_FIELD_DEF); + return Err(()) + } + try!(expect_ident(cx, tts[i].get_span(), &tts[i], &["field"], EXPECTED_FIELD_DEF)); + try!(consume_fat_arrow(cx, sp, &tts[i+1], EXPECTED_FAT_ARROW)); + let def = try!(get_field_def(cx, &tts[i+2], &objty)); + res.push(def); + if tts.len() >= i + 4 && maybe_comma(&tts[i+3]) { + i += 4; + } else { + i += 3; + } + if tts.len() <= i { + break; + } + } + Ok(res) +} + +fn get_field_def(cx: &mut ExtCtxt, ast: &ast::TokenTree, objty: &ObjectType) -> Result { + if let &ast::TokenTree::Delimited(_, ref delemented) = ast { + let fieldef_str = print::pprust::tts_to_string(&delemented.tts); + return parse_field_names(cx, ast.get_span(), fieldef_str, objty) + } + cx.span_err(ast.get_span(), INVALID_FIELD_DEF); + Err(()) +} + +fn parse_field_names(cx: &mut ExtCtxt, sp: codemap::Span, ast: String, objty: &ObjectType) -> Result { + if ast.len() == 0 { + cx.span_err(sp, INVALID_FIELD_DEF); + return Err(()) + } + let def = FieldDef { + name: "".to_string(), + ty: Default::default(), + slot: "".to_string(), + default: "".to_string(), + comments: Vec::new(), + padding: None + }; + let mut required = if *objty == ObjectType::Table { + vec!["default", "name", "slot", "typeOf"] + } else { + vec!["name", "slot", "typeOf"] + }; + let list = required.clone(); + let iter = ast.split(','); + let mut error = false; + let def = iter.fold(def, |mut acc, attr| { + if error { return acc } + let mut iter = attr.split('='); + match iter.next().unwrap().trim() { + "name" => { + acc.name = iter.next().unwrap().trim().to_string(); + remove_required(&mut required, "name"); + } + "typeOf" => { + let ty = map_ty(iter.next().unwrap().trim().to_string()); + if ty.is_none() { + cx.span_err(sp, INVALID_FIELD_DEF); + error = true; + return acc; + } + remove_required(&mut required, "typeOf"); + acc.ty = ty.unwrap(); + } + "default" => { + acc.default = iter.next().unwrap().trim().to_string(); + remove_required(&mut required, "default"); + } + "slot" => { + let slot = iter.next().unwrap().trim().to_string(); + if slot.parse::().is_err() { + cx.span_err(sp, EXPECTED_SLOT_INT); + error = true; + return acc + } + acc.slot = slot; + remove_required(&mut required, "slot"); + } + "comment" => { + let comment = iter.next().unwrap().trim().to_string(); + acc.comments.push(comment); + } + "padding" => { + let padding = iter.next().unwrap().trim().to_string(); + acc.padding = Some(padding); + } + a => { + error = true; + cx.span_err(sp, &format!("{}: {}", UNKNOWN_ATTRIBUTE, a)); + } + } + acc + }); + if error { + return Err(()) + } + if required.len() > 0 { + fn tokens_to_string(tokens: &[&str]) -> String { + let mut i = tokens.iter(); + let b = i.next() + .map_or("".to_string(), |t| t.to_string()); + i.enumerate().fold(b, |mut b, (i, ref a)| { + if tokens.len() > 2 && i == tokens.len() - 2 { + b.push_str(", and "); + } else if tokens.len() == 2 && i == tokens.len() - 2 { + b.push_str(" and "); + } else { + b.push_str(", "); + } + b.push_str(&a.to_string()); + b + }) + } + let msg = format!("Expected {}, missing {}", + tokens_to_string(&list), + tokens_to_string(&required)); + cx.span_err(sp, &msg); + return Err(()) + } + Ok(def) +} + + +fn remove_required(required: &mut Vec<&str>, found: &str) { + if let Ok(i) = required.binary_search(&&found) { + required.remove(i); + } +} + +fn get_enum_items(cx: &mut ExtCtxt, sp: codemap::Span, ast: &ast::TokenTree, msg: &str) -> Result,()> { + if let &ast::TokenTree::Delimited(_, ref delemented) = ast { + let fieldef_str = print::pprust::tts_to_string(&delemented.tts); + return get_enum_items_impl(cx, ast.get_span(), fieldef_str, msg) + } + cx.span_err(sp, INVALID_FIELD_DEF); + Err(()) +} + +fn get_enum_items_impl(cx: &mut ExtCtxt, sp: codemap::Span, ast: String, msg: &str) -> Result ,()> { + if ast.len() == 0 { + cx.span_err(sp, msg); + return Err(()) + } + let items = Vec::new(); + let iter = ast.split(','); + let items = iter.fold(items, |mut acc, attr| { + let mut iter = attr.split('='); + let enum_name = iter.next().unwrap().trim(); + let enum_value = iter.next().unwrap().trim(); + let item = EnumItem { + name: enum_name.to_string(), + value: enum_value.to_string() + }; + acc.push(item); + acc + }); + Ok(items) +} + +fn get_enum_repr(cx: &mut ExtCtxt, ast: &ast::TokenTree, msg: &str) -> Result { + if let &ast::TokenTree::Token(_, token::Token::Ident(ident))= ast { + let ty = ident.name.as_str(); + if let Some(ty) = map_ty(ty.to_string()) { + if ty.is_scalar() { + return Ok(ty) + } + } + } + cx.span_err(ast.get_span(), msg); + Err(()) +} diff --git a/rust/macros/src/table.rs b/rust/macros/src/table.rs new file mode 100644 index 0000000000..cd4793d83c --- /dev/null +++ b/rust/macros/src/table.rs @@ -0,0 +1,85 @@ +use syntax::ext::base::{ExtCtxt, MacResult, MacEager}; +use syntax::parse::token; +use syntax::util::small_vector::SmallVector; +use syntax::ext::quote::rt::ExtParseUtils; + +use utils::*; + +pub fn build_table_items(cx: &mut ExtCtxt, + name: token::InternedString, + fields: Vec, + attributes: Vec) + -> Result, ()> { + let struct_def = cx.parse_item(build_struct_def(&name)); + let build_impl = cx.parse_item(build_impl(&name, &fields)); + let from_impl = cx.parse_item(build_from(&name)); + let vtype = cx.parse_item(build_vector_type(&name, &attributes)); + Ok(MacEager::items(SmallVector::many(vec![struct_def, build_impl, from_impl, vtype]))) +} + +pub fn build_struct_items(cx: &mut ExtCtxt, + name: token::InternedString, + fields: Vec, + attributes: Vec) + -> Result, ()> { + let struct_def = cx.parse_item(build_struct_def(&name)); + let build_impl = cx.parse_item(build_struct_impl(&name, &fields)); + let from_impl = cx.parse_item(build_from(&name)); + let vtype = cx.parse_item(build_vector_type(&name, &attributes)); + Ok(MacEager::items(SmallVector::many(vec![struct_def, build_impl, from_impl, vtype]))) +} + +fn build_struct_def(name: &token::InternedString) -> String { + format!("#[derive(Debug, Clone, PartialEq, Eq)] pub struct {}>(flatbuffers::Table);", + name) +} + +fn build_impl(name: &token::InternedString, fields: &Vec) -> String { + let mut str1 = format!("impl> {} {{\n", name); + for field in fields { + str1 = format!("{} fn {}(&self) -> {} {{ {} }}", + str1, + name, + field.ty.base_type(), + field.ty.get_table_accessor(&field.slot, &field.default)); + } + format!("{} }}", str1) +} + +fn build_struct_impl(name: &token::InternedString, fields: &Vec) -> String { + let mut str1 = format!("impl> {} {{ \n", name); + for field in fields { + str1 = format!("{} fn {}(&self) -> {} {{ {} }}", + str1, + field.name.to_lowercase(), + field.ty.base_type(), + field.ty.get_struct_accessor(&field.slot)); + } + format!("{} }}", str1) +} + +fn build_from(name: &token::InternedString) -> String { + format!("impl> From> for {} {{ fn from(table: \ + flatbuffers::Table) -> {} {{ {}(table) }}}}", + name, + name, + name) + +} + +fn build_vector_type(name: &token::InternedString, attributes: &[ObjAttribute]) -> String { + let size = find_attribute("size", attributes).unwrap_or("4".to_string()); + let size = size.parse::().unwrap(); + format!("impl<'a, T: AsRef<[u8]>> flatbuffers::VectorType<'a> for {} {{ \ + type Item = {}<&'a [u8]>; + fn inline_size() -> usize {{ \ + {} \ + }} \ + fn read_next(buffer:&'a [u8]) -> Self::Item {{ \ + let table = flatbuffers::Table::get_indirect_root(buffer, 0); \ + table.into() \ + }} }}", + name, + name, + size) +} diff --git a/rust/macros/src/union.rs b/rust/macros/src/union.rs new file mode 100644 index 0000000000..2cf0024867 --- /dev/null +++ b/rust/macros/src/union.rs @@ -0,0 +1,101 @@ +use syntax::ext::base::{ExtCtxt, MacResult, MacEager}; +use syntax::parse::token; +use syntax::util::small_vector::SmallVector; +use syntax::ext::quote::rt::ExtParseUtils; + +use utils::*; + +pub fn build_simple_enum(cx: &mut ExtCtxt, + name: token::InternedString, + ty: FieldType, + items: Vec) + -> Result, ()> { + let enum_def = cx.parse_item(build_enum_def(&name, &ty.base_type(), &items)); + let from_def = cx.parse_item(build_from_def(&name, &ty.base_type(), &items)); + let vtype = try!(build_enum_vector_type(&name, &ty)); + let vtype_def = cx.parse_item(vtype); + Ok(MacEager::items(SmallVector::many(vec![enum_def, from_def, vtype_def]))) +} + +pub fn build_union(cx: &mut ExtCtxt, + name: token::InternedString, + items: Vec) + -> Result, ()> { + let union_def = cx.parse_item(build_union_enum_def(&name, &items)); + let type_name = format!("{}Type", &name); + let union_new_def = cx.parse_item(build_union_new_def(&name, &type_name, &items)); + let enum_def = cx.parse_item(build_enum_def(&type_name, "u8", &items)); + let from_def = cx.parse_item(build_from_def(&type_name, "u8", &items)); + Ok(MacEager::items(SmallVector::many(vec![union_def, union_new_def, enum_def, from_def]))) +} + +fn build_union_enum_def(name: &str, items: &[EnumItem]) -> String { + let mut str1 = format!("#[derive(Debug)] \ + pub enum {}> {{\n", + name); + for item in items { + str1 = format!("{} {}({}),\n", str1, item.name, item.name); + } + format!("{} }}", str1) +} + +fn build_union_new_def(name: &str, type_name: &str, items: &[EnumItem]) -> String { + let mut str1 = format!("impl> {} {{ \ + pub fn new(table: flatbuffers::Table, utype: Option<{}>) -> Option<{}> {{ + match utype {{", name, type_name, name); + for item in items { + str1 = format!("{} Some({}::{}) => Some( {}::{}(table.into() ) ), ", str1, type_name, + item.name, name, item.name); + } + format!("{} _ => None }} }} }}", str1) +} + + +fn build_enum_def(name: &str, ty: &str, items: &[EnumItem]) -> String { + let mut str1 = format!("#[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)]\n \ + #[repr({})]\n \ + pub enum {} {{\n", + ty, + name); + for item in items { + str1 = format!("{} {} = {},\n", str1, item.name, item.value); + } + format!("{} }}", str1) +} + +fn build_from_def(name: &str, ty: &str, items: &[EnumItem]) -> String { + let mut str1 = + format!("impl {} {{ pub fn from(value: {}) -> Option<{}> {{ match value {{ ", + name, + ty, + name); + for item in items { + str1 = format!("{} {} => Some({}::{}),\n", + str1, + item.value, + name, + item.name); + } + format!("{} _ => None }}}}}}", str1) +} + +fn build_enum_vector_type(name: &token::InternedString, ty: &FieldType) -> Result { + let (base_ty, size) = match *ty { + FieldType::Scalar(ref base_ty, size) => (base_ty.clone(), size), + _ => return Err(()), + }; + let str1 = + format!("impl<'a> flatbuffers::VectorType<'a> for {} {{ type Item = \ + Option<{}>; + fn inline_size() -> usize {{ {} }} fn \ + read_next(buffer:&'a [u8]) -> Self::Item {{ \ + let i = {}::read_next(buffer); + {}::from(i) \ + }} }}", + name, + name, + size, + base_ty, + name); + Ok(str1) +} diff --git a/rust/macros/src/utils.rs b/rust/macros/src/utils.rs new file mode 100644 index 0000000000..e157e3c3a2 --- /dev/null +++ b/rust/macros/src/utils.rs @@ -0,0 +1,287 @@ +use syntax::ast; +use syntax::codemap; +use syntax::ext::base::ExtCtxt; +use syntax::parse::token; + +#[derive(Debug, PartialEq, Eq)] +pub enum ObjectType { + Table, + Struct, + Enum, + Union, +} + +#[derive(Debug)] +pub struct ObjAttribute { + pub name: String, + pub value: String, +} + +#[derive(Debug)] +pub struct FieldDef { + pub name: String, + pub ty: FieldType, + pub slot: String, + pub default: String, + pub comments: Vec, + pub padding: Option +} + +#[derive(Debug)] +pub enum FieldType { + Scalar(String, u8), + Enum(String, Box), + Union(String), + Table(String), + Vector(Box), +} + +#[derive(Debug)] +pub struct EnumItem { + pub name: String, + pub value: String, +} + +pub fn map_ty(other: String) -> Option { + let ft = match &*other { + "byte" => FieldType::Scalar("i8".to_string(), 1), + "ubyte" => FieldType::Scalar("u8".to_string(), 1), + "short" => FieldType::Scalar("i16".to_string(), 2), + "ushort" => FieldType::Scalar("u16".to_string(), 2), + "int" => FieldType::Scalar("i32".to_string(), 4), + "uint" => FieldType::Scalar("u32".to_string(), 4), + "long" => FieldType::Scalar("i64".to_string(), 8), + "ulong" => FieldType::Scalar("u64".to_string(), 8), + "float" => FieldType::Scalar("f32".to_string(), 4), + "double" => FieldType::Scalar("f64".to_string(), 8), + "bool" => FieldType::Scalar("bool".to_string(), 1), + "string" => FieldType::Scalar("&str".to_string(), 4), + _ => { + let otherc = other.clone(); + let mut chars = otherc.chars(); + if chars.next() == Some('[') && chars.next_back() == Some(']') { + // vector + let ty = chars.as_str() + .to_string(); + let ty = map_ty(ty); + if ty.is_none() { + return None; + } + FieldType::Vector(Box::new(ty.unwrap())) + } else if other.starts_with("union ") { + let mut iter = other.split_whitespace(); + let md = iter.nth(1); + if md.is_none() { + return None; + } + FieldType::Union(md.unwrap().to_string()) + } else if other.starts_with("enum ") { + let mut iter = other.split_whitespace(); + let _ = iter.next(); + let md = iter.next(); + let ty = iter.next(); + if md.is_none() || ty.is_none() { + return None; + } + let ty = map_ty(ty.unwrap().to_string()); + if ty.is_none() { + return None; + } + FieldType::Enum(md.unwrap().to_string(), Box::new(ty.unwrap())) + } else { + FieldType::Table(other) + } + } + }; + Some(ft) +} + +impl Default for FieldType { + fn default() -> FieldType { + FieldType::Scalar("I8".to_string(), 1) + } +} + +impl FieldType { + pub fn get_table_accessor(&self, slot: &str, default: &str) -> String { + match *self { + FieldType::Scalar(ref ty, _) => scalar_accessor(ty, slot, default), + FieldType::Enum(ref md, ref ty) => enum_accessor(md, &ty, slot, default), + FieldType::Union(ref md) => union_accessor(md, slot), + FieldType::Table(_) => table_accessor(slot), + FieldType::Vector(ref ty) => vector_accessor(&ty, slot), + } + } + + pub fn get_struct_accessor(&self, slot: &str) -> String { + match *self { + FieldType::Scalar(ref ty, _) => struct_scalar_accessor(ty, slot), + FieldType::Enum(ref md, ref ty) => struct_enum_accessor(md, &ty, slot), + FieldType::Table(_) => struct_table_accessor(slot), + _ => panic!("Structs do not have Union or Vector fields"), + } + } + + + pub fn base_type(&self) -> String { + match *self { + FieldType::Scalar(ref ty, _) => ty.to_string(), + FieldType::Table(ref ty) => format!("{}<&[u8]>", ty.to_string()), + FieldType::Vector(ref ty) => format!("Iter<'a,{}>", ty.base_type()), + FieldType::Union(ref ty) => ty.to_string(), + FieldType::Enum(ref md, _) => format!("Option<{}>", md.to_string()), + } + } + + pub fn is_scalar(&self) -> bool { + if let FieldType::Scalar(_,_) = *self { + true + } else { + false + } + } +} + +fn enum_accessor(md: &str, ty: &FieldType, slot: &str, default: &str) -> String { + let fun = ty.get_table_accessor(slot, default); + format!("let v = {}; {}::from(v)", fun, md) +} + +fn struct_enum_accessor(md: &str, ty: &FieldType, slot: &str) -> String { + let fun = ty.get_struct_accessor(slot); + format!("let v = {}; {}::from(v)", fun, md) +} + +fn union_accessor(md: &str, slot: &str) -> String { + let fun = format!("self.{}_type();", md.to_lowercase()); + let table = format!("let table = ($i.0).get_slot_table({});", slot); + format!("{} {} {}::new(table, ty)", fun, table, md.to_lowercase()) +} + +fn table_accessor(slot: &str) -> String { + let fun = format!("let t = (self.0).get_slot_table({})", slot); + format!("{} if t.is_some() {{ return t.unwrap().into(); }} None", + fun) +} + +fn struct_table_accessor(slot: &str) -> String { + format!("(self.0).get_struct({})", slot) +} + +fn vector_accessor(ty: &FieldType, slot: &str) -> String { + let ty = ty.base_type(); + format!("(self.0).get_slot_vector::<{}>({})", ty, slot) +} + +fn scalar_accessor(ty: &str, slot: &str, default: &str) -> String { + match &*ty { + "i8" => format!("(self.0).get_slot_i8({},{})", slot, default), + "u8" => format!("(self.0).get_slot_u8({},{})", slot, default), + "i16" => format!("(self.0).get_slot_i16({},{})", slot, default), + "u16" => format!("(self.0).get_slot_u16({},{})", slot, default), + "i32" => format!("(self.0).get_slot_i32({},{})", slot, default), + "u32" => format!("(self.0).get_slot_u32({},{})", slot, default), + "i64" => format!("(self.0).get_slot_i64({},{})", slot, default), + "u64" => format!("(self.0).get_slot_u64({},{})", slot, default), + "f32" => format!("(self.0).get_slot_f32({},{})", slot, default), + "f64" => format!("(self.0).get_slot_f64({},{})", slot, default), + "bool" => format!("(self.0).get_slot_bool({},{})", slot, default), + "&str" => format!("(self.0).get_slot_str({},{})", slot, default), + otherwise => panic!("Unknow scalar type {}", otherwise), + } +} + +fn struct_scalar_accessor(ty: &str, slot: &str) -> String { + match &*ty { + "i8" => format!("(self.0).get_i8({})", slot), + "u8" => format!("(self.0).get_u8({})", slot), + "i16" => format!("(self.0).get_i16({})", slot), + "u16" => format!("(self.0).get_u16({})", slot), + "i32" => format!("(self.0).get_i32({})", slot), + "u32" => format!("(self.0).get_u32({})", slot), + "i64" => format!("(self.0).get_i64({})", slot), + "u64" => format!("(self.0).get_u64({})", slot), + "f32" => format!("(self.0).get_f32({})", slot), + "f64" => format!("(self.0).get_f64({})", slot), + "bool" => format!("(self.0).get_bool({})", slot), + "&str" => format!("(self.0).get_str({})", slot), + otherwise => panic!("Unknow scalar type {}", otherwise), + } +} + +pub fn find_attribute(name: &str, attributes: &[ObjAttribute]) -> Option { + for attr in attributes { + if attr.name == name { + return Some(attr.value.clone()); + } + } + None +} + +pub fn consume_fat_arrow(cx: &mut ExtCtxt, + sp: codemap::Span, + ast: &ast::TokenTree, + msg: &str) + -> Result<(), ()> { + match *ast { + ast::TokenTree::Token(_, token::Token::FatArrow) => return Ok(()), + _ => {} + } + cx.span_err(sp, msg); + Err(()) +} + +pub fn consume_colon(cx: &mut ExtCtxt, + sp: codemap::Span, + ast: &ast::TokenTree, + msg: &str) + -> Result<(), ()> { + match *ast { + ast::TokenTree::Token(_, token::Token::Colon) => return Ok(()), + _ => {} + } + cx.span_err(sp, msg); + Err(()) +} + + +pub fn maybe_comma(ast: &ast::TokenTree) -> bool { + match *ast { + ast::TokenTree::Token(_, token::Token::Comma) => return true, + _ => {} + } + false +} + +pub fn get_lit(cx: &mut ExtCtxt, + sp: codemap::Span, + ast: &ast::TokenTree, + msg: &str) + -> Result { + match ast { + &ast::TokenTree::Token(_, token::Token::Literal(lit, _)) => return Ok(lit), + _ => { + cx.span_err(sp, msg); + return Err(()); + } + } +} + +pub fn expect_ident(cx: &mut ExtCtxt, + sp: codemap::Span, + ast: &ast::TokenTree, + name: &[&str], + msg: &str) + -> Result { + match ast { + &ast::TokenTree::Token(_, token::Token::Ident(ident)) => { + let res = name.iter().any(|x| *x == ident.name.as_str()); + if res { + return Ok(ident); + } + } + _ => {} + } + cx.span_err(sp, msg); + Err(()) +} diff --git a/rust/macros/tests/compile-fail/empty_field.rs b/rust/macros/tests/compile-fail/empty_field.rs new file mode 100644 index 0000000000..c760ea4505 --- /dev/null +++ b/rust/macros/tests/compile-fail/empty_field.rs @@ -0,0 +1,11 @@ +#![feature(plugin)] +#![plugin(flatbuffers_macros)] + +extern crate flatbuffers_macros; + +flatbuffers_object!{Table => Monster [ + field => {} + //~^ Error: Invalid field definition +]} + +fn main() {} diff --git a/rust/macros/tests/compile-fail/expected_field.rs b/rust/macros/tests/compile-fail/expected_field.rs new file mode 100644 index 0000000000..730f8e1e20 --- /dev/null +++ b/rust/macros/tests/compile-fail/expected_field.rs @@ -0,0 +1,11 @@ +#![feature(plugin)] +#![plugin(flatbuffers_macros)] + +extern crate flatbuffers_macros; + +flatbuffers_object!{Table => Monster [//~ Error: Invalid field def + pos +]} + + +fn main() {} diff --git a/rust/macros/tests/compile-fail/fat_arrow.rs b/rust/macros/tests/compile-fail/fat_arrow.rs new file mode 100644 index 0000000000..c63dbc585a --- /dev/null +++ b/rust/macros/tests/compile-fail/fat_arrow.rs @@ -0,0 +1,9 @@ +#![feature(plugin)] +#![plugin(flatbuffers_macros)] + +extern crate flatbuffers_macros; + +flatbuffers_object!{Table} +//~^ ERROR: Expected '=>' + +fn main() {} diff --git a/rust/macros/tests/compile-fail/fat_arrow_name.rs b/rust/macros/tests/compile-fail/fat_arrow_name.rs new file mode 100644 index 0000000000..8b0673b5c4 --- /dev/null +++ b/rust/macros/tests/compile-fail/fat_arrow_name.rs @@ -0,0 +1,8 @@ +#![feature(plugin)] +#![plugin(flatbuffers_macros)] +extern crate flatbuffers_macros; + +flatbuffers_object!{Table =>} +//~^ ERROR: Expected a name for the Table + +fn main() {} diff --git a/rust/macros/tests/compile-fail/first_ident.rs b/rust/macros/tests/compile-fail/first_ident.rs new file mode 100644 index 0000000000..273cbaa9c0 --- /dev/null +++ b/rust/macros/tests/compile-fail/first_ident.rs @@ -0,0 +1,9 @@ +#![feature(plugin)] +#![plugin(flatbuffers_macros)] + +extern crate flatbuffers_macros; + +flatbuffers_object!{Monster, []} +//~^ ERROR: Expected one of 'Table', 'Struct', 'Enum' or 'Union' + +fn main() {} diff --git a/rust/macros/tests/compile-fail/invalid_field.rs b/rust/macros/tests/compile-fail/invalid_field.rs new file mode 100644 index 0000000000..5fce66b07f --- /dev/null +++ b/rust/macros/tests/compile-fail/invalid_field.rs @@ -0,0 +1,11 @@ +#![feature(plugin)] +#![plugin(flatbuffers_macros)] + +extern crate flatbuffers_macros; + +flatbuffers_object!{Table => Monster [//~ Error: Invalid field definition + field +]} + + +fn main() {} diff --git a/rust/macros/tests/compile-fail/invalid_field_attr.rs b/rust/macros/tests/compile-fail/invalid_field_attr.rs new file mode 100644 index 0000000000..d531420354 --- /dev/null +++ b/rust/macros/tests/compile-fail/invalid_field_attr.rs @@ -0,0 +1,14 @@ +#![feature(plugin)] +#![plugin(flatbuffers_macros)] + +extern crate flatbuffers_macros; + +flatbuffers_object!{Table => Monster [ + field => { name = pos, + //~^ Error: Unknown attribute: wierd + typeOf = Vec3, + wierd = true, + slot = 4 } +]} + +fn main() {} diff --git a/rust/macros/tests/compile-fail/invalid_other_field.rs b/rust/macros/tests/compile-fail/invalid_other_field.rs new file mode 100644 index 0000000000..e7af80eb38 --- /dev/null +++ b/rust/macros/tests/compile-fail/invalid_other_field.rs @@ -0,0 +1,15 @@ +#![feature(plugin)] +#![plugin(flatbuffers_macros)] + +extern crate flatbuffers_macros; + +flatbuffers_object!{Table => Monster [ + field => { name = pos, + typeOf = Vec3, + slot = 4, + default = true }, + field => { typeOf = pos } + //~^ Error: Expected default, name, slot, and typeOf, missing default, name, and slot +]} + +fn main() {} diff --git a/rust/macros/tests/compile-fail/missing_name.rs b/rust/macros/tests/compile-fail/missing_name.rs new file mode 100644 index 0000000000..3146330f81 --- /dev/null +++ b/rust/macros/tests/compile-fail/missing_name.rs @@ -0,0 +1,11 @@ +#![feature(plugin)] +#![plugin(flatbuffers_macros)] + +extern crate flatbuffers_macros; + +flatbuffers_object!{Table => Monster [ + field => { typeOf = pos } + //~^ Error: Expected default, name, slot, and typeOf, missing default, name, and slot +]} + +fn main() {} diff --git a/rust/macros/tests/compile-fail/name_no_fields.rs b/rust/macros/tests/compile-fail/name_no_fields.rs new file mode 100644 index 0000000000..92dfdd6d46 --- /dev/null +++ b/rust/macros/tests/compile-fail/name_no_fields.rs @@ -0,0 +1,9 @@ +#![feature(plugin)] +#![plugin(flatbuffers_macros)] + +extern crate flatbuffers_macros; + +flatbuffers_object!{Table => Monster,} +//~^ Error: Expected a list of fields + +fn main() {} diff --git a/rust/macros/tests/compile-fail/slot_int.rs b/rust/macros/tests/compile-fail/slot_int.rs new file mode 100644 index 0000000000..1d2677c5e6 --- /dev/null +++ b/rust/macros/tests/compile-fail/slot_int.rs @@ -0,0 +1,11 @@ +#![feature(plugin)] +#![plugin(flatbuffers_macros)] + +extern crate flatbuffers_macros; + +flatbuffers_object!{Table => Monster [ + field => { slot = me } + //~^ Error: Slot must be an integer +]} + +fn main() {} diff --git a/rust/macros/tests/run-pass/enum.rs b/rust/macros/tests/run-pass/enum.rs new file mode 100644 index 0000000000..b85447eb16 --- /dev/null +++ b/rust/macros/tests/run-pass/enum.rs @@ -0,0 +1,12 @@ +#![feature(plugin)] +#![plugin(flatbuffers_macros)] + +extern crate flatbuffers_macros; +extern crate flatbuffers; + +flatbuffers_object!{Enum => Color {Red = 1, Blue = 2} as byte} + +fn main() { + let x = Color::Red; + let y = Color::from(2).unwrap(); +} diff --git a/rust/macros/tests/run-pass/no_fields.rs b/rust/macros/tests/run-pass/no_fields.rs new file mode 100644 index 0000000000..e610d31cdf --- /dev/null +++ b/rust/macros/tests/run-pass/no_fields.rs @@ -0,0 +1,14 @@ +#![feature(plugin)] +#![plugin(flatbuffers_macros)] + +extern crate flatbuffers_macros; +extern crate flatbuffers; + +flatbuffers_object!{Table => Vec3 []} +//~^ WARNING: Expected a list of fields + + +flatbuffers_object!{Table => Monster} +//~^ WARNING: Expected a list of fields + +fn main() {} diff --git a/rust/macros/tests/run-pass/struct.rs b/rust/macros/tests/run-pass/struct.rs new file mode 100644 index 0000000000..62d04b6292 --- /dev/null +++ b/rust/macros/tests/run-pass/struct.rs @@ -0,0 +1,34 @@ +#![feature(plugin)] +#![plugin(flatbuffers_macros)] + +extern crate flatbuffers_macros; +extern crate flatbuffers; + +flatbuffers_object!{Enum => Color {Red = 1, Blue = 2} as ubyte} + +flatbuffers_object!{Struct => Vec3 ( size:32 ) [ + field => { name = x, + typeOf = float, + slot = 0, + default = 0.0 }, + field => { name = y, + typeOf = float, + slot = 4, + default = 0.0 }, + field => { name = z, + typeOf = float, + slot = 8, + default = 0.0 }, + field => { name = test1, + typeOf = double, + slot = 16, + default = 0.0 }, + field => { name = test2, + typeOf = enum Color ubyte, + slot = 24, + default = 0 }, + field => { name = test3, + typeOf = Vec3, + slot = 26 }]} + +fn main() {} diff --git a/rust/macros/tests/run-pass/table.rs b/rust/macros/tests/run-pass/table.rs new file mode 100644 index 0000000000..de28c5c904 --- /dev/null +++ b/rust/macros/tests/run-pass/table.rs @@ -0,0 +1,37 @@ +#![feature(plugin)] +#![plugin(flatbuffers_macros)] + +extern crate flatbuffers_macros; +extern crate flatbuffers; + +use flatbuffers::VectorType; + +flatbuffers_object!{Table => Monster [ + field => { name = pos, + typeOf = bool, + slot = 4, + comment = "test", + default = true } +]} + +fn main() { + let buf = + vec![72, 0, 0, 0, 77, 79, 78, 83, 0, 0, 0, 0, 60, 0, 128, 0, 8, 0, 0, 0, 6, 0, 52, 0, 0, + 0, 56, 0, 0, 0, 5, 0, 60, 0, 64, 0, 68, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 76, 0, 80, + 0, 96, 0, 104, 0, 84, 0, 88, 0, 112, 0, 120, 0, 92, 0, 0, 0, 0, 0, 0, 0, 60, 0, 0, 0, + 0, 1, 80, 0, 0, 0, 128, 63, 0, 0, 0, 64, 0, 0, 64, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 8, 64, 2, 0, 5, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 244, 0, 0, 0, 228, + 0, 0, 0, 204, 0, 0, 0, 128, 0, 0, 0, 88, 0, 0, 0, 64, 0, 0, 0, 65, 201, 121, 221, 65, + 201, 121, 221, 113, 164, 129, 142, 113, 164, 129, 142, 36, 0, 0, 0, 129, 145, 123, + 242, 205, 128, 15, 110, 129, 145, 123, 242, 205, 128, 15, 110, 241, 221, 103, 199, + 220, 72, 249, 67, 241, 221, 103, 199, 220, 72, 249, 67, 3, 0, 0, 0, 1, 0, 1, 0, 188, + 255, 255, 255, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 2, 0, 0, 0, 20, + 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 116, 101, 115, 116, 50, 0, 0, 0, 5, 0, 0, 0, 116, + 101, 115, 116, 49, 0, 0, 0, 2, 0, 0, 0, 10, 0, 20, 0, 30, 0, 40, 0, 60, 0, 8, 0, 0, + 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 60, + 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 70, 114, 101, 100, 0, 0, 0, 0, 5, 0, 0, 0, 0, 1, 2, + 3, 4, 0, 0, 0, 9, 0, 0, 0, 77, 121, 77, 111, 110, 115, 116, 101, 114, 0, 0, 0]; + let table = flatbuffers::Table::get_root(buf, 0); + let mon: Monster<_> = table.into(); +} diff --git a/rust/macros/tests/run-pass/union.rs b/rust/macros/tests/run-pass/union.rs new file mode 100644 index 0000000000..e7b6b44e34 --- /dev/null +++ b/rust/macros/tests/run-pass/union.rs @@ -0,0 +1,15 @@ + +#![feature(plugin)] +#![plugin(flatbuffers_macros)] + +extern crate flatbuffers_macros; +extern crate flatbuffers; + +flatbuffers_object!{Struct => Vec3 ( size:32 ) []} + +flatbuffers_object!{Table => Monster []} + +flatbuffers_object!{Union => Any { Monster = 1, Vec3 = 2 }} + +fn main() { +} diff --git a/rust/macros/tests/tests.rs b/rust/macros/tests/tests.rs new file mode 100644 index 0000000000..333c8ce7a7 --- /dev/null +++ b/rust/macros/tests/tests.rs @@ -0,0 +1,21 @@ +extern crate compiletest_rs as compiletest; + +use std::path::PathBuf; + +fn run_mode(mode: &'static str) { + + let mut config = compiletest::default_config(); + let cfg_mode = mode.parse().ok().expect("Invalid mode"); + + config.mode = cfg_mode; + config.src_base = PathBuf::from(format!("tests/{}", mode)); + config.target_rustcflags = Some("-L target/debug -L target/debug/deps".to_string()); + + compiletest::run_tests(&config); +} + +#[test] +fn compile_test() { + run_mode("compile-fail"); + run_mode("run-pass"); +} diff --git a/rust/src/bin/test.rs b/rust/src/bin/test.rs index 68bb876fab..8687693c86 100644 --- a/rust/src/bin/test.rs +++ b/rust/src/bin/test.rs @@ -1,247 +1,247 @@ +// #![feature(trace_macros)] +// #[macro_use] +// extern crate flatbuffers; -#[macro_use] -extern crate flatbuffers; - -fn main() { +// fn main() { -} - -#[cfg(test)] -#[cfg(feature = "test_idl_gen")] -mod test { - use std::rc::Rc; - - #[allow(non_snake_case,dead_code,unused_imports, non_camel_case_types)] - mod MyGame; - - use flatbuffers::*; - use self::MyGame::*; - - #[test] - fn manual_monster_build() { - let mut b = Builder::with_capacity(0); - let str = b.create_string("MyMonster"); - - b.start_vector(1, 5, 1); - b.add_u8(4); - b.add_u8(3); - b.add_u8(2); - b.add_u8(1); - b.add_u8(0); - let inv = b.end_vector(); - - b.start_object(13); - b.add_slot_i16(2, 20, 100); - let mon2 = b.end_object(); - - // Test4Vector - b.start_vector(4, 2, 1); - - // Test 0 - b.prep(2, 4); - b.pad(1); - b.add_i8(20); - b.add_i16(10); - - // Test 1 - b.prep(2, 4); - b.pad(1); - b.add_i8(40); - b.add_i16(30); - - // end testvector - let test4 = b.end_vector(); - - b.start_object(13); - - // a vec3 - b.prep(16, 32); - b.pad(2); - b.prep(2, 4); - b.pad(1); - b.add_u8(6); - b.add_i16(5); - b.pad(1); - b.add_u8(4); - b.add_f64(3.0); - b.pad(4); - b.add_f32(3.0); - b.add_f32(2.0); - b.add_f32(1.0); - let vec3_loc = b.offset(); - // end vec3 - - b.add_slot_struct(0, vec3_loc as u32, 0); // vec3. noop - b.add_slot_i16(2, 80, 100); // hp - b.add_slot_uoffset(3, str as u32, 0); - b.add_slot_uoffset(5, inv as u32, 0); // inventory - b.add_slot_u8(7, 1, 0); - b.add_slot_uoffset(8, mon2 as u32, 0); - b.add_slot_uoffset(9, test4 as u32, 0); - let mon = b.end_object(); +// } + +// #[cfg(test)] +// #[cfg(feature = "test_idl_gen")] +// mod test { +// use std::rc::Rc; + +// #[allow(non_snake_case,dead_code,unused_imports, non_camel_case_types)] +// mod MyGame; + +// use flatbuffers::*; +// use self::MyGame::*; + +// #[test] +// fn manual_monster_build() { +// let mut b = Builder::with_capacity(0); +// let str = b.create_string("MyMonster"); + +// b.start_vector(1, 5, 1); +// b.add_u8(4); +// b.add_u8(3); +// b.add_u8(2); +// b.add_u8(1); +// b.add_u8(0); +// let inv = b.end_vector(); + +// b.start_object(13); +// b.add_slot_i16(2, 20, 100); +// let mon2 = b.end_object(); + +// // Test4Vector +// b.start_vector(4, 2, 1); + +// // Test 0 +// b.prep(2, 4); +// b.pad(1); +// b.add_i8(20); +// b.add_i16(10); + +// // Test 1 +// b.prep(2, 4); +// b.pad(1); +// b.add_i8(40); +// b.add_i16(30); + +// // end testvector +// let test4 = b.end_vector(); + +// b.start_object(13); + +// // a vec3 +// b.prep(16, 32); +// b.pad(2); +// b.prep(2, 4); +// b.pad(1); +// b.add_u8(6); +// b.add_i16(5); +// b.pad(1); +// b.add_u8(4); +// b.add_f64(3.0); +// b.pad(4); +// b.add_f32(3.0); +// b.add_f32(2.0); +// b.add_f32(1.0); +// let vec3_loc = b.offset(); +// // end vec3 + +// b.add_slot_struct(0, vec3_loc as u32, 0); // vec3. noop +// b.add_slot_i16(2, 80, 100); // hp +// b.add_slot_uoffset(3, str as u32, 0); +// b.add_slot_uoffset(5, inv as u32, 0); // inventory +// b.add_slot_u8(7, 1, 0); +// b.add_slot_uoffset(8, mon2 as u32, 0); +// b.add_slot_uoffset(9, test4 as u32, 0); +// let mon = b.end_object(); - b.finish_table(mon); - } - - fn build_monster() { - use self::MyGame::example::monster::MonsterBuilder; - - let mut b = Builder::with_capacity(0); - let name = b.create_string("MyMonster"); - let test1 = b.create_string("test1"); - let test2 = b.create_string("test2"); - let fred = b.create_string("Fred"); - b.start_inventory_vector(5); - b.add_u8(4); - b.add_u8(3); - b.add_u8(2); - b.add_u8(1); - b.add_u8(0); - let inv = b.end_vector(); - - b.start_monster(); - b.add_name(fred); - let mon2 = b.end_object(); - - - use self::MyGame::example::test::TestBuilder; - b.start_test4_vector(2); - b.build_test(10, 20); - b.build_test(30, 40); - let test4 = b.end_vector(); - - b.start_testarrayofstring_vector(2); - b.add_uoffset(test2); - b.add_uoffset(test1); - let test_array = b.end_vector(); - use self::MyGame::example::stat::StatBuilder; - let mut stat = b; - let stat_id = stat.create_string("way out..statistical"); - stat.start_stat(); - stat.add_id(stat_id); - stat.add_val(20); - stat.add_count(0); - let stat_offset = stat.end_object(); - b = stat; - - - use self::MyGame::example::vec3::Vec3Builder; - b.start_monster(); - let pos = b.build_vec3(1.0, 2.0, 3.0, 3.0, 2, 5, 6); - b.add_pos(pos); - - b.add_hp(80); - b.add_name(name); - b.add_inventory(inv); - b.add_test_type(1); - b.add_test(mon2); - b.add_test4(test4); - b.add_testempty(stat_offset); - b.add_testarrayofstring(test_array); - let mon = b.end_object(); - - b.finish_table(mon); - } - - #[test] - fn build_monster_with_generated() { - build_monster(); - } - - #[test] - fn can_read_monster() { - use std::env; - use std::path::Path; - use std::io::{Read, BufReader}; - use std::fs::File; - let mut data_path = env::current_exe().unwrap(); - data_path.pop(); - data_path.pop(); - data_path.pop(); //create root - data_path.push(Path::new("monsterdata_test.mon")); - let f1 = File::open(data_path).unwrap(); - let mut reader = BufReader::new(f1); - let mut buf: Vec = Vec::new(); - reader.read_to_end(&mut buf).unwrap(); - let rc = Rc::new(buf); - let table = Table::from_offset(rc.clone(), 0); - let monster = example::monster::Monster::new(table); - let got = monster.hp(); - assert!(got == 80, "bad {}: want {:?} got {:?}", "HP", 80, got); - let got = monster.mana(); - assert!(got == 150, "bad {}: want {:?} got {:?}", "Mana", 150, got); - let got = monster.name(); - assert!(got == "MyMonster", "bad {}: want {:?} got {:?}", "Name", "MyMonster", got); - let vec3 = monster.pos(); - assert!(vec3.is_some(), "bad {}: want {:?} got {:?}", "Pos", "Vec3", "None"); - // verify the properties of the Vec3 - let vec3 = vec3.unwrap(); - let got = vec3.x(); - assert!(got == 1.0, "bad {}: want {:?} got {:?}", "Vec3.x", "1.0", got); - let got = vec3.y(); - assert!(got == 2.0, "bad {}: want {:?} got {:?}", "Vec3.x", "2.0", got); - let got = vec3.z(); - assert!(got == 3.0, "bad {}: want {:?} got {:?}", "Vec3.x", "3.0", got); - let got = vec3.test1(); - assert!(got == 3.0, "bad {}: want {:?} got {:?}", "Vec3.test1", "3.0", got); - let got = vec3.test2(); - assert!(got == Some(example::Color::Green), "bad {}: want {:?} got {:?}", - "Vec3.test2", "Color::Green", got); - // Verify properties of test3 - let test3 = vec3.test3(); - let got = test3.a(); - assert!(got == 5, "bad {}: want {:?} got {:?}", "Test.a", "5", got); - let got = test3.b(); - assert!(got == 6, "bad {}: want {:?} got {:?}", "Test.b", "6", got); - // Verify test type - let got = monster.test_type(); - assert!(got == Some(example::AnyType::Monster), "bad {}: want {:?} got {:?}", "TestType", "Monster", got); - // initialize a Table from a union field - let got = monster.test(); - if let Some(example::Any::Monster(monster2)) = got { - let got = monster2.name(); - assert!(got == "Fred", "bad {}: want {:?} got {:?}", "Name", "Fred", got); - } else { - panic!( "bad {}: want {:?} got {:?}", "Test", "Monster Union", got) - } - let got = monster.inventory(); - - assert!(got.size_hint() == (5, Some(5)), "bad {}: want {:?} got {:?}", - "Inventory", "Byte Vector of length 5", got); - use std::ops::Add; - let got: u8 = got.fold(0, Add::add); - assert!(got == 10, "bad {}: want {:?} got {:?}", "Inventory Sum", "10", got); - // Test4 - let mut got = monster.test4(); - assert!(got.size_hint() == (2, Some(2)), "bad {}: want {:?} got {:?}", "Test4 vector length", "4", got.size_hint()); - let test1 = got.next().unwrap(); - let test2 = got.next().unwrap(); - assert!(test1.a() == 10, "bad {}: want {:?} got {:?}", "Test4 array test1.a", "10", test1.a()); - assert!(test1.b() == 20, "bad {}: want {:?} got {:?}", "Test4 array test1.b", "20", test1.b()); - assert!(test2.a() == 30, "bad {}: want {:?} got {:?}", "Test4 array test2.a", "30", test2.a()); - assert!(test2.b() == 40, "bad {}: want {:?} got {:?}", "Test4 array test2.b", "40", test2.b()); - // Test Array of string - let mut got = monster.testarrayofstring(); - assert!(got.size_hint() == (2, Some(2)), "bad {}: want {:?} got {:?}", "Test4 string vector length", "2", got.size_hint()); - let str1 = got.next().unwrap(); - let str2 = got.next().unwrap(); - assert!(str1 == "test1", "bad {}: want {:?} got {:?}", "Test string array 1", "test1", str1); - assert!(str2 == "test2", "bad {}: want {:?} got {:?}", "Test string array 2", "test2", str2); - // array of tables - let got = monster.testarrayoftables(); - assert_eq!(got.size_hint(),(0, Some(0))); - } +// b.finish_table(mon); +// } + +// fn build_monster() { +// use self::MyGame::example::monster::MonsterBuilder; + +// let mut b = Builder::with_capacity(0); +// let name = b.create_string("MyMonster"); +// let test1 = b.create_string("test1"); +// let test2 = b.create_string("test2"); +// let fred = b.create_string("Fred"); +// b.start_inventory_vector(5); +// b.add_u8(4); +// b.add_u8(3); +// b.add_u8(2); +// b.add_u8(1); +// b.add_u8(0); +// let inv = b.end_vector(); + +// b.start_monster(); +// b.add_name(fred); +// let mon2 = b.end_object(); + + +// use self::MyGame::example::test::TestBuilder; +// b.start_test4_vector(2); +// b.build_test(10, 20); +// b.build_test(30, 40); +// let test4 = b.end_vector(); + +// b.start_testarrayofstring_vector(2); +// b.add_uoffset(test2); +// b.add_uoffset(test1); +// let test_array = b.end_vector(); +// use self::MyGame::example::stat::StatBuilder; +// let mut stat = b; +// let stat_id = stat.create_string("way out..statistical"); +// stat.start_stat(); +// stat.add_id(stat_id); +// stat.add_val(20); +// stat.add_count(0); +// let stat_offset = stat.end_object(); +// b = stat; + + +// use self::MyGame::example::vec3::Vec3Builder; +// b.start_monster(); +// let pos = b.build_vec3(1.0, 2.0, 3.0, 3.0, 2, 5, 6); +// b.add_pos(pos); + +// b.add_hp(80); +// b.add_name(name); +// b.add_inventory(inv); +// b.add_test_type(1); +// b.add_test(mon2); +// b.add_test4(test4); +// b.add_testempty(stat_offset); +// b.add_testarrayofstring(test_array); +// let mon = b.end_object(); + +// b.finish_table(mon); +// } + +// #[test] +// fn build_monster_with_generated() { +// build_monster(); +// } + +// #[test] +// fn can_read_monster() { +// use std::env; +// use std::path::Path; +// use std::io::{Read, BufReader}; +// use std::fs::File; +// let mut data_path = env::current_exe().unwrap(); +// data_path.pop(); +// data_path.pop(); +// data_path.pop(); //create root +// data_path.push(Path::new("monsterdata_test.mon")); +// let f1 = File::open(data_path).unwrap(); +// let mut reader = BufReader::new(f1); +// let mut buf: Vec = Vec::new(); +// reader.read_to_end(&mut buf).unwrap(); +// let rc = Rc::new(buf); +// let table = Table::from_offset(rc.clone(), 0); +// let monster = example::monster::Monster::new(table); +// let got = monster.hp(); +// assert!(got == 80, "bad {}: want {:?} got {:?}", "HP", 80, got); +// let got = monster.mana(); +// assert!(got == 150, "bad {}: want {:?} got {:?}", "Mana", 150, got); +// let got = monster.name(); +// assert!(got == "MyMonster", "bad {}: want {:?} got {:?}", "Name", "MyMonster", got); +// let vec3 = monster.pos(); +// assert!(vec3.is_some(), "bad {}: want {:?} got {:?}", "Pos", "Vec3", "None"); +// // verify the properties of the Vec3 +// let vec3 = vec3.unwrap(); +// let got = vec3.x(); +// assert!(got == 1.0, "bad {}: want {:?} got {:?}", "Vec3.x", "1.0", got); +// let got = vec3.y(); +// assert!(got == 2.0, "bad {}: want {:?} got {:?}", "Vec3.x", "2.0", got); +// let got = vec3.z(); +// assert!(got == 3.0, "bad {}: want {:?} got {:?}", "Vec3.x", "3.0", got); +// let got = vec3.test1(); +// assert!(got == 3.0, "bad {}: want {:?} got {:?}", "Vec3.test1", "3.0", got); +// let got = vec3.test2(); +// assert!(got == Some(example::Color::Green), "bad {}: want {:?} got {:?}", +// "Vec3.test2", "Color::Green", got); +// // Verify properties of test3 +// let test3 = vec3.test3(); +// let got = test3.a(); +// assert!(got == 5, "bad {}: want {:?} got {:?}", "Test.a", "5", got); +// let got = test3.b(); +// assert!(got == 6, "bad {}: want {:?} got {:?}", "Test.b", "6", got); +// // Verify test type +// let got = monster.test_type(); +// assert!(got == Some(example::AnyType::Monster), "bad {}: want {:?} got {:?}", "TestType", "Monster", got); +// // initialize a Table from a union field +// let got = monster.test(); +// if let Some(example::Any::Monster(monster2)) = got { +// let got = monster2.name(); +// assert!(got == "Fred", "bad {}: want {:?} got {:?}", "Name", "Fred", got); +// } else { +// panic!( "bad {}: want {:?} got {:?}", "Test", "Monster Union", got) +// } +// let got = monster.inventory(); + +// assert!(got.size_hint() == (5, Some(5)), "bad {}: want {:?} got {:?}", +// "Inventory", "Byte Vector of length 5", got); +// use std::ops::Add; +// let got: u8 = got.fold(0, Add::add); +// assert!(got == 10, "bad {}: want {:?} got {:?}", "Inventory Sum", "10", got); +// // Test4 +// let mut got = monster.test4(); +// assert!(got.size_hint() == (2, Some(2)), "bad {}: want {:?} got {:?}", "Test4 vector length", "4", got.size_hint()); +// let test1 = got.next().unwrap(); +// let test2 = got.next().unwrap(); +// assert!(test1.a() == 10, "bad {}: want {:?} got {:?}", "Test4 array test1.a", "10", test1.a()); +// assert!(test1.b() == 20, "bad {}: want {:?} got {:?}", "Test4 array test1.b", "20", test1.b()); +// assert!(test2.a() == 30, "bad {}: want {:?} got {:?}", "Test4 array test2.a", "30", test2.a()); +// assert!(test2.b() == 40, "bad {}: want {:?} got {:?}", "Test4 array test2.b", "40", test2.b()); +// // Test Array of string +// let mut got = monster.testarrayofstring(); +// assert!(got.size_hint() == (2, Some(2)), "bad {}: want {:?} got {:?}", "Test4 string vector length", "2", got.size_hint()); +// let str1 = got.next().unwrap(); +// let str2 = got.next().unwrap(); +// assert!(str1 == "test1", "bad {}: want {:?} got {:?}", "Test string array 1", "test1", str1); +// assert!(str2 == "test2", "bad {}: want {:?} got {:?}", "Test string array 2", "test2", str2); +// // array of tables +// let got = monster.testarrayoftables(); +// assert_eq!(got.size_hint(),(0, Some(0))); +// } - // until benchmark tests are stablized in Rust... - #[test] - fn bench_build() { - use std::time::Instant; - let now = Instant::now(); - for _ in 1..10000 { - build_monster() - } - println!("Building 1000 took {:?}", now.elapsed()); - } -} +// // until benchmark tests are stablized in Rust... +// #[test] +// fn bench_build() { +// use std::time::Instant; +// let now = Instant::now(); +// for _ in 1..10000 { +// build_monster() +// } +// println!("Building 1000 took {:?}", now.elapsed()); +// } +// } diff --git a/rust/src/bin/test/MyGame/Example/Any.rs b/rust/src/bin/test/MyGame/Example/Any.rs deleted file mode 100644 index 24cc67be6f..0000000000 --- a/rust/src/bin/test/MyGame/Example/Any.rs +++ /dev/null @@ -1,61 +0,0 @@ -//! Automatically generated, do not modify. - -use flatbuffers; -use super::*; - -#[derive(PartialEq, Eq, Clone, Debug, Hash)] -#[repr(u8)] -pub enum Any { - NONE = 0, - Monster = 1, - TestSimpleTableWithEnum = 2, -} - -/// A List of all `Any` enum variants. -pub const ANY_LIST: [Any;3] = [Any::NONE,Any::Monster,Any::TestSimpleTableWithEnum,]; - -impl Any { - /// Returns a `str` representation of a `Any` enum. - pub fn name(&self) -> &'static str { - match *self { - Any::NONE => "NONE", - Any::Monster => "Monster", - Any::TestSimpleTableWithEnum => "TestSimpleTableWithEnum", - } - } -} - -impl From for Any { - fn from(value: u8) -> Any { - match value { - 0 => Any::NONE, - 1 => Any::Monster, - 2 => Any::TestSimpleTableWithEnum, - _ => unreachable!("Unable to create a `Any` from value {} ", value), - } - } -} - -#[derive(Debug)] -pub enum AnyUnion<'a> { - None, - Monster(Monster<'a>), - TestSimpleTableWithEnum(TestSimpleTableWithEnum<'a>), -} - -impl<'a> AnyUnion<'a> { - pub fn from_type(table: &'a flatbuffers::Table, t: Any, offset: usize) -> AnyUnion<'a> { - match t { - Any::NONE => { - AnyUnion::None - } - Any::Monster => { - AnyUnion::Monster(table.get_root(offset as u32).into()) - } - Any::TestSimpleTableWithEnum => { - AnyUnion::TestSimpleTableWithEnum(table.get_root(offset as u32).into()) - } - } - } -} - diff --git a/rust/src/bin/test/MyGame/Example/Color.rs b/rust/src/bin/test/MyGame/Example/Color.rs deleted file mode 100644 index d60b7ac5cb..0000000000 --- a/rust/src/bin/test/MyGame/Example/Color.rs +++ /dev/null @@ -1,35 +0,0 @@ -//! Automatically generated, do not modify. - -#[derive(PartialEq, Eq, Clone, Debug, Hash)] -#[repr(i8)] -pub enum Color { - Red = 1, - Green = 2, - Blue = 8, -} - -/// A List of all `Color` enum variants. -pub const COLOR_LIST: [Color;3] = [Color::Red,Color::Green,Color::Blue,]; - -impl Color { - /// Returns a `str` representation of a `Color` enum. - pub fn name(&self) -> &'static str { - match *self { - Color::Red => "Red", - Color::Green => "Green", - Color::Blue => "Blue", - } - } -} - -impl From for Color { - fn from(value: i8) -> Color { - match value { - 1 => Color::Red, - 2 => Color::Green, - 8 => Color::Blue, - _ => unreachable!("Unable to create a `Color` from value {} ", value), - } - } -} - diff --git a/rust/src/bin/test/MyGame/Example/Monster.rs b/rust/src/bin/test/MyGame/Example/Monster.rs deleted file mode 100644 index f89ff78d26..0000000000 --- a/rust/src/bin/test/MyGame/Example/Monster.rs +++ /dev/null @@ -1,534 +0,0 @@ -//! Automatically generated, do not modify. - -use flatbuffers; -use super::*; - -/// an example documentation comment: monster object -#[derive(Debug)] -pub struct Monster<'a> { - table: flatbuffers::Table<'a>, -} - -enum VT { - POS = 4, - MANA = 6, - HP = 8, - NAME = 10, - INVENTORY = 14, - COLOR = 16, - TEST_TYPE = 18, - TEST = 20, - TEST4 = 22, - TESTARRAYOFSTRING = 24, - TESTARRAYOFTABLES = 26, - ENEMY = 28, - TESTNESTEDFLATBUFFER = 30, - TESTEMPTY = 32, - TESTBOOL = 34, - TESTHASHS32_FNV1 = 36, - TESTHASHU32_FNV1 = 38, - TESTHASHS64_FNV1 = 40, - TESTHASHU64_FNV1 = 42, - TESTHASHS32_FNV1A = 44, - TESTHASHU32_FNV1A = 46, - TESTHASHS64_FNV1A = 48, - TESTHASHU64_FNV1A = 50, - TESTARRAYOFBOOLS = 52, - TESTF = 54, - TESTF2 = 56, - TESTF3 = 58, -} - -impl<'a> Monster<'a> { - pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> Monster { - Monster { - table: flatbuffers::Table::from_offset(buf, offset), - } - } - - pub fn pos(&self) -> Option { - let offset = self.table.field_offset(VT::POS as u16); - if offset != 0 { - return Some(self.table.get_struct::(offset)) - }; - None - } - - pub fn mana(&self) -> i16 { - let offset = self.table.field_offset(VT::MANA as u16); - if offset != 0 { - return self.table.get_i16(offset) - } - 150 - } - - pub fn hp(&self) -> i16 { - let offset = self.table.field_offset(VT::HP as u16); - if offset != 0 { - return self.table.get_i16(offset) - } - 100 - } - - pub fn name(&self) -> &str { - let offset = self.table.field_offset(VT::NAME as u16); - if offset != 0 { - return self.table.get_str(offset) - } - "" - } - - pub fn inventory(&self) -> &[u8] { - let offset = self.table.field_offset(VT::INVENTORY as u16); - if offset != 0 { - return self.table.byte_vector(offset); - } - &[] - } - - pub fn color(&self) -> Color { - let offset = self.table.field_offset(VT::COLOR as u16); - if offset != 0 { - return self.table.get_i8(offset).into() - } - 8.into() - } - - pub fn test_type(&self) -> Any { - let offset = self.table.field_offset(VT::TEST_TYPE as u16); - if offset != 0 { - return self.table.get_u8(offset).into() - } - 0.into() - } - - pub fn test(&self) -> AnyUnion { - let offset = self.table.field_offset(VT::TEST as u16); - if offset != 0 { - let t = self.test_type(); - return AnyUnion::from_type(&self.table, t, offset as usize); - } - AnyUnion::None - } - - pub fn test4(&self) -> flatbuffers::Iterator { - let offset = self.table.field_offset(VT::TEST4 as u16); - if offset != 0 { - return self.table.struct_vector(offset) - } - flatbuffers::empty_iterator(&self.table) - } - - pub fn testarrayofstring(&self) -> flatbuffers::Iterator<&str> { - let offset = self.table.field_offset(VT::TESTARRAYOFSTRING as u16); - if offset != 0 { - return self.table.str_vector(offset); - } - flatbuffers::empty_iterator(&self.table) } - - /// an example documentation comment: this will end up in the generated code - /// multiline too - pub fn testarrayoftables(&self) -> flatbuffers::Iterator { - let offset = self.table.field_offset(VT::TESTARRAYOFTABLES as u16); - if offset != 0 { - return self.table.table_vector(offset) - } - flatbuffers::empty_iterator(&self.table) - } - - pub fn enemy(&self) -> Option { - let offset = self.table.field_offset(VT::ENEMY as u16); - if offset != 0 { - return Some(self.table.get_indirect_root(offset).into()) - }; - None - } - - pub fn testnestedflatbuffer(&self) -> &[u8] { - let offset = self.table.field_offset(VT::TESTNESTEDFLATBUFFER as u16); - if offset != 0 { - return self.table.byte_vector(offset); - } - &[] - } - - pub fn testempty(&self) -> Option { - let offset = self.table.field_offset(VT::TESTEMPTY as u16); - if offset != 0 { - return Some(self.table.get_indirect_root(offset).into()) - }; - None - } - - pub fn testbool(&self) -> bool { - let offset = self.table.field_offset(VT::TESTBOOL as u16); - if offset != 0 { - return self.table.get_bool(offset) - } - false - } - - pub fn testhashs32_fnv1(&self) -> i32 { - let offset = self.table.field_offset(VT::TESTHASHS32_FNV1 as u16); - if offset != 0 { - return self.table.get_i32(offset) - } - 0 - } - - pub fn testhashu32_fnv1(&self) -> u32 { - let offset = self.table.field_offset(VT::TESTHASHU32_FNV1 as u16); - if offset != 0 { - return self.table.get_u32(offset) - } - 0 - } - - pub fn testhashs64_fnv1(&self) -> i64 { - let offset = self.table.field_offset(VT::TESTHASHS64_FNV1 as u16); - if offset != 0 { - return self.table.get_i64(offset) - } - 0 - } - - pub fn testhashu64_fnv1(&self) -> u64 { - let offset = self.table.field_offset(VT::TESTHASHU64_FNV1 as u16); - if offset != 0 { - return self.table.get_u64(offset) - } - 0 - } - - pub fn testhashs32_fnv1a(&self) -> i32 { - let offset = self.table.field_offset(VT::TESTHASHS32_FNV1A as u16); - if offset != 0 { - return self.table.get_i32(offset) - } - 0 - } - - pub fn testhashu32_fnv1a(&self) -> u32 { - let offset = self.table.field_offset(VT::TESTHASHU32_FNV1A as u16); - if offset != 0 { - return self.table.get_u32(offset) - } - 0 - } - - pub fn testhashs64_fnv1a(&self) -> i64 { - let offset = self.table.field_offset(VT::TESTHASHS64_FNV1A as u16); - if offset != 0 { - return self.table.get_i64(offset) - } - 0 - } - - pub fn testhashu64_fnv1a(&self) -> u64 { - let offset = self.table.field_offset(VT::TESTHASHU64_FNV1A as u16); - if offset != 0 { - return self.table.get_u64(offset) - } - 0 - } - - pub fn testarrayofbools(&self) -> &[bool] { - let offset = self.table.field_offset(VT::TESTARRAYOFBOOLS as u16); - if offset != 0 { - return self.table.bool_vector(offset); - } - &[] - } - - pub fn testf(&self) -> f32 { - let offset = self.table.field_offset(VT::TESTF as u16); - if offset != 0 { - return self.table.get_f32(offset) - } - 3.14159 - } - - pub fn testf2(&self) -> f32 { - let offset = self.table.field_offset(VT::TESTF2 as u16); - if offset != 0 { - return self.table.get_f32(offset) - } - 3.0 - } - - pub fn testf3(&self) -> f32 { - let offset = self.table.field_offset(VT::TESTF3 as u16); - if offset != 0 { - return self.table.get_f32(offset) - } - 0.0 - } - -} - -impl<'a> From> for Monster<'a> { - fn from(table: flatbuffers::Table) -> Monster { - Monster{ - table: table, - } - } -} - -/// Builder Object for `Monster` tables. -pub struct Builder { - inner: flatbuffers::Builder, -} - -impl Builder { - /// Create a new builder. - pub fn with_capacity(size: usize) -> Self { - Builder { - inner: flatbuffers::Builder::with_capacity(size), - } - } - - /// Initialize a new `Builder` for a `Monster` table. - pub fn start(&mut self) { - self.inner.start_object(28); - } - - /// Finalize the current object and return the offset. - pub fn end(&mut self) -> flatbuffers::UOffsetT { - return self.inner.end_object() - } - - /// Set the value for field `pos`. - pub fn add_pos(&mut self, pos: flatbuffers::UOffsetT) { - self.inner.add_slot_struct(0, pos, 0) - } - - /// Set the value for field `mana`. - pub fn add_mana(&mut self, mana: i16) { - self.inner.add_slot_i16(1, mana, 150) - } - - /// Set the value for field `hp`. - pub fn add_hp(&mut self, hp: i16) { - self.inner.add_slot_i16(2, hp, 100) - } - - /// Set the value for field `name`. - pub fn add_name(&mut self, name: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(3, name, 0) - } - - /// Set the value for field `inventory`. - pub fn add_inventory(&mut self, inventory: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(5, inventory, 0) - } - - /// Initializes bookkeeping for writing a new `inventory` vector. - pub fn start_inventory_vector(&mut self, numElems: usize) { - self.inner.start_vector(1, numElems, 1) - } - - /// Set the value for field `color`. - pub fn add_color(&mut self, color: i8) { - self.inner.add_slot_i8(6, color, 8) - } - - /// Set the value for field `test_type`. - pub fn add_test_type(&mut self, test_type: u8) { - self.inner.add_slot_u8(7, test_type, 0) - } - - /// Set the value for field `test`. - pub fn add_test(&mut self, test: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(8, test, 0) - } - - /// Set the value for field `test4`. - pub fn add_test4(&mut self, test4: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(9, test4, 0) - } - - /// Initializes bookkeeping for writing a new `test4` vector. - pub fn start_test4_vector(&mut self, numElems: usize) { - self.inner.start_vector(4, numElems, 2) - } - - /// Set the value for field `testarrayofstring`. - pub fn add_testarrayofstring(&mut self, testarrayofstring: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(10, testarrayofstring, 0) - } - - /// Initializes bookkeeping for writing a new `testarrayofstring` vector. - pub fn start_testarrayofstring_vector(&mut self, numElems: usize) { - self.inner.start_vector(4, numElems, 4) - } - - /// Set the value for field `testarrayoftables`. - pub fn add_testarrayoftables(&mut self, testarrayoftables: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(11, testarrayoftables, 0) - } - - /// Initializes bookkeeping for writing a new `testarrayoftables` vector. - pub fn start_testarrayoftables_vector(&mut self, numElems: usize) { - self.inner.start_vector(4, numElems, 4) - } - - /// Set the value for field `enemy`. - pub fn add_enemy(&mut self, enemy: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(12, enemy, 0) - } - - /// Set the value for field `testnestedflatbuffer`. - pub fn add_testnestedflatbuffer(&mut self, testnestedflatbuffer: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(13, testnestedflatbuffer, 0) - } - - /// Initializes bookkeeping for writing a new `testnestedflatbuffer` vector. - pub fn start_testnestedflatbuffer_vector(&mut self, numElems: usize) { - self.inner.start_vector(1, numElems, 1) - } - - /// Set the value for field `testempty`. - pub fn add_testempty(&mut self, testempty: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(14, testempty, 0) - } - - /// Set the value for field `testbool`. - pub fn add_testbool(&mut self, testbool: bool) { - self.inner.add_slot_bool(15, testbool, false) - } - - /// Set the value for field `testhashs32_fnv1`. - pub fn add_testhashs32_fnv1(&mut self, testhashs32_fnv1: i32) { - self.inner.add_slot_i32(16, testhashs32_fnv1, 0) - } - - /// Set the value for field `testhashu32_fnv1`. - pub fn add_testhashu32_fnv1(&mut self, testhashu32_fnv1: u32) { - self.inner.add_slot_u32(17, testhashu32_fnv1, 0) - } - - /// Set the value for field `testhashs64_fnv1`. - pub fn add_testhashs64_fnv1(&mut self, testhashs64_fnv1: i64) { - self.inner.add_slot_i64(18, testhashs64_fnv1, 0) - } - - /// Set the value for field `testhashu64_fnv1`. - pub fn add_testhashu64_fnv1(&mut self, testhashu64_fnv1: u64) { - self.inner.add_slot_u64(19, testhashu64_fnv1, 0) - } - - /// Set the value for field `testhashs32_fnv1a`. - pub fn add_testhashs32_fnv1a(&mut self, testhashs32_fnv1a: i32) { - self.inner.add_slot_i32(20, testhashs32_fnv1a, 0) - } - - /// Set the value for field `testhashu32_fnv1a`. - pub fn add_testhashu32_fnv1a(&mut self, testhashu32_fnv1a: u32) { - self.inner.add_slot_u32(21, testhashu32_fnv1a, 0) - } - - /// Set the value for field `testhashs64_fnv1a`. - pub fn add_testhashs64_fnv1a(&mut self, testhashs64_fnv1a: i64) { - self.inner.add_slot_i64(22, testhashs64_fnv1a, 0) - } - - /// Set the value for field `testhashu64_fnv1a`. - pub fn add_testhashu64_fnv1a(&mut self, testhashu64_fnv1a: u64) { - self.inner.add_slot_u64(23, testhashu64_fnv1a, 0) - } - - /// Set the value for field `testarrayofbools`. - pub fn add_testarrayofbools(&mut self, testarrayofbools: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(24, testarrayofbools, 0) - } - - /// Initializes bookkeeping for writing a new `testarrayofbools` vector. - pub fn start_testarrayofbools_vector(&mut self, numElems: usize) { - self.inner.start_vector(1, numElems, 1) - } - - /// Set the value for field `testf`. - pub fn add_testf(&mut self, testf: f32) { - self.inner.add_slot_f32(25, testf, 3.14159) - } - - /// Set the value for field `testf2`. - pub fn add_testf2(&mut self, testf2: f32) { - self.inner.add_slot_f32(26, testf2, 3.0) - } - - /// Set the value for field `testf3`. - pub fn add_testf3(&mut self, testf3: f32) { - self.inner.add_slot_f32(27, testf3, 0.0) - } - - pub fn build_vec3(&mut self , x: f32, y: f32, z: f32, test1: f64, test2: i8, test3_a: i16, test3_b: i8) -> flatbuffers::UOffsetT { - vec3::build_vec3(&mut self.inner, x, y, z, test1, test2, test3_a, test3_b) - } - - pub fn build_test(&mut self , a: i16, b: i8) -> flatbuffers::UOffsetT { - test::build_test(&mut self.inner, a, b) - } - - /// Finish the buffer. - pub fn finish(&mut self, r: flatbuffers::UOffsetT) { - return self.inner.finish(r) - } - - pub fn create_string(&mut self, v: &str) -> flatbuffers::UOffsetT { self.inner.create_string(v) } - pub fn get_bytes(&self) -> &[u8] { self.inner.get_bytes() } - pub fn len(&self) -> usize { self.inner.len() } - pub fn offset(&self) -> usize { self.inner.offset() } - pub fn reset(&mut self) { self.inner.reset() } - pub fn prep(&mut self, s:usize, a: usize) { self.inner.prep(s,a) } - pub fn pad(&mut self, n:usize) { self.inner.pad(n) } - pub fn end_vector(&mut self) -> flatbuffers::UOffsetT { self.inner.end_vector() } - pub fn add_bool(&mut self, v:bool) { self.inner.add_bool(v) } - pub fn add_u8(&mut self, v:u8) { self.inner.add_u8(v) } - pub fn add_i8(&mut self, v:i8) { self.inner.add_i8(v) } - pub fn add_u16(&mut self, v:u16) { self.inner.add_u16(v) } - pub fn add_i16(&mut self, v:i16) { self.inner.add_i16(v) } - pub fn add_u32(&mut self, v:u32) { self.inner.add_u32(v) } - pub fn add_i32(&mut self, v:i32) { self.inner.add_i32(v) } - pub fn add_u64(&mut self, v:u64) { self.inner.add_u64(v) } - pub fn add_i64(&mut self, v:i64) { self.inner.add_i64(v) } - pub fn add_f32(&mut self, v:f32) { self.inner.add_f32(v) } - pub fn add_f64(&mut self, v:f64) { self.inner.add_f64(v) } - pub fn add_uoffset(&mut self, v: flatbuffers::UOffsetT) { self.inner.add_uoffset(v) } - pub fn add_slot_bool(&mut self, o: usize, v: bool, d: bool) { self.inner.add_slot_bool(o,v,d) } - pub fn add_slot_u8(&mut self, o: usize, v: u8, d: u8) { self.inner.add_slot_u8(o,v,d) } - pub fn add_slot_i8(&mut self, o: usize, v: i8, d: i8) { self.inner.add_slot_i8(o,v,d) } - pub fn add_slot_u16(&mut self, o: usize, v: u16, d: u16) { self.inner.add_slot_u16(o,v,d) } - pub fn add_slot_i16(&mut self, o: usize, v: i16, d: i16) { self.inner.add_slot_i16(o,v,d) } - pub fn add_slot_i32(&mut self, o: usize, v: i32, d: i32) { self.inner.add_slot_i32(o,v,d) } - pub fn add_slot_u32(&mut self, o: usize, v: u32, d: u32) { self.inner.add_slot_u32(o,v,d) } - pub fn add_slot_u64(&mut self, o: usize, v: u64, d: u64) { self.inner.add_slot_u64(o,v,d) } - pub fn add_slot_i64(&mut self, o: usize, v: i64, d: i64) { self.inner.add_slot_i64(o,v,d) } - pub fn add_slot_f32(&mut self, o: usize, v: f32, d: f32) { self.inner.add_slot_f32(o,v,d) } - pub fn add_slot_f64(&mut self, o: usize, v: f64, d: f64) { self.inner.add_slot_f64(o,v,d) } - pub fn add_slot_uoffset(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_uoffset(o,v,d) } - pub fn add_slot_struct(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_struct(o,v,d) } -} - -impl Default for Builder { - fn default() -> Builder { - Builder::with_capacity(1024) - } -} - -impl From for Builder { - fn from(b: flatbuffers::Builder) -> Builder { - Builder { - inner: b, - } - } -} - -impl Into for Builder { - fn into(self) -> flatbuffers::Builder { - self.inner - } -} - -impl flatbuffers::ObjectBuilder for Builder {} - diff --git a/rust/src/bin/test/MyGame/Example/Stat.rs b/rust/src/bin/test/MyGame/Example/Stat.rs deleted file mode 100644 index 4bccf31436..0000000000 --- a/rust/src/bin/test/MyGame/Example/Stat.rs +++ /dev/null @@ -1,157 +0,0 @@ -//! Automatically generated, do not modify. - -use flatbuffers; -use super::*; - -#[derive(Debug)] -pub struct Stat<'a> { - table: flatbuffers::Table<'a>, -} - -enum VT { - ID = 4, - VAL = 6, - COUNT = 8, -} - -impl<'a> Stat<'a> { - pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> Stat { - Stat { - table: flatbuffers::Table::from_offset(buf, offset), - } - } - - pub fn id(&self) -> &str { - let offset = self.table.field_offset(VT::ID as u16); - if offset != 0 { - return self.table.get_str(offset) - } - "" - } - - pub fn val(&self) -> i64 { - let offset = self.table.field_offset(VT::VAL as u16); - if offset != 0 { - return self.table.get_i64(offset) - } - 0 - } - - pub fn count(&self) -> u16 { - let offset = self.table.field_offset(VT::COUNT as u16); - if offset != 0 { - return self.table.get_u16(offset) - } - 0 - } - -} - -impl<'a> From> for Stat<'a> { - fn from(table: flatbuffers::Table) -> Stat { - Stat{ - table: table, - } - } -} - -/// Builder Object for `Stat` tables. -pub struct Builder { - inner: flatbuffers::Builder, -} - -impl Builder { - /// Create a new builder. - pub fn with_capacity(size: usize) -> Self { - Builder { - inner: flatbuffers::Builder::with_capacity(size), - } - } - - /// Initialize a new `Builder` for a `Stat` table. - pub fn start(&mut self) { - self.inner.start_object(3); - } - - /// Finalize the current object and return the offset. - pub fn end(&mut self) -> flatbuffers::UOffsetT { - return self.inner.end_object() - } - - /// Set the value for field `id`. - pub fn add_id(&mut self, id: flatbuffers::UOffsetT) { - self.inner.add_slot_uoffset(0, id, 0) - } - - /// Set the value for field `val`. - pub fn add_val(&mut self, val: i64) { - self.inner.add_slot_i64(1, val, 0) - } - - /// Set the value for field `count`. - pub fn add_count(&mut self, count: u16) { - self.inner.add_slot_u16(2, count, 0) - } - - /// Finish the buffer. - pub fn finish(&mut self, r: flatbuffers::UOffsetT) { - return self.inner.finish(r) - } - - pub fn create_string(&mut self, v: &str) -> flatbuffers::UOffsetT { self.inner.create_string(v) } - pub fn get_bytes(&self) -> &[u8] { self.inner.get_bytes() } - pub fn len(&self) -> usize { self.inner.len() } - pub fn offset(&self) -> usize { self.inner.offset() } - pub fn reset(&mut self) { self.inner.reset() } - pub fn prep(&mut self, s:usize, a: usize) { self.inner.prep(s,a) } - pub fn pad(&mut self, n:usize) { self.inner.pad(n) } - pub fn end_vector(&mut self) -> flatbuffers::UOffsetT { self.inner.end_vector() } - pub fn add_bool(&mut self, v:bool) { self.inner.add_bool(v) } - pub fn add_u8(&mut self, v:u8) { self.inner.add_u8(v) } - pub fn add_i8(&mut self, v:i8) { self.inner.add_i8(v) } - pub fn add_u16(&mut self, v:u16) { self.inner.add_u16(v) } - pub fn add_i16(&mut self, v:i16) { self.inner.add_i16(v) } - pub fn add_u32(&mut self, v:u32) { self.inner.add_u32(v) } - pub fn add_i32(&mut self, v:i32) { self.inner.add_i32(v) } - pub fn add_u64(&mut self, v:u64) { self.inner.add_u64(v) } - pub fn add_i64(&mut self, v:i64) { self.inner.add_i64(v) } - pub fn add_f32(&mut self, v:f32) { self.inner.add_f32(v) } - pub fn add_f64(&mut self, v:f64) { self.inner.add_f64(v) } - pub fn add_uoffset(&mut self, v: flatbuffers::UOffsetT) { self.inner.add_uoffset(v) } - pub fn add_slot_bool(&mut self, o: usize, v: bool, d: bool) { self.inner.add_slot_bool(o,v,d) } - pub fn add_slot_u8(&mut self, o: usize, v: u8, d: u8) { self.inner.add_slot_u8(o,v,d) } - pub fn add_slot_i8(&mut self, o: usize, v: i8, d: i8) { self.inner.add_slot_i8(o,v,d) } - pub fn add_slot_u16(&mut self, o: usize, v: u16, d: u16) { self.inner.add_slot_u16(o,v,d) } - pub fn add_slot_i16(&mut self, o: usize, v: i16, d: i16) { self.inner.add_slot_i16(o,v,d) } - pub fn add_slot_i32(&mut self, o: usize, v: i32, d: i32) { self.inner.add_slot_i32(o,v,d) } - pub fn add_slot_u32(&mut self, o: usize, v: u32, d: u32) { self.inner.add_slot_u32(o,v,d) } - pub fn add_slot_u64(&mut self, o: usize, v: u64, d: u64) { self.inner.add_slot_u64(o,v,d) } - pub fn add_slot_i64(&mut self, o: usize, v: i64, d: i64) { self.inner.add_slot_i64(o,v,d) } - pub fn add_slot_f32(&mut self, o: usize, v: f32, d: f32) { self.inner.add_slot_f32(o,v,d) } - pub fn add_slot_f64(&mut self, o: usize, v: f64, d: f64) { self.inner.add_slot_f64(o,v,d) } - pub fn add_slot_uoffset(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_uoffset(o,v,d) } - pub fn add_slot_struct(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_struct(o,v,d) } -} - -impl Default for Builder { - fn default() -> Builder { - Builder::with_capacity(1024) - } -} - -impl From for Builder { - fn from(b: flatbuffers::Builder) -> Builder { - Builder { - inner: b, - } - } -} - -impl Into for Builder { - fn into(self) -> flatbuffers::Builder { - self.inner - } -} - -impl flatbuffers::ObjectBuilder for Builder {} - diff --git a/rust/src/bin/test/MyGame/Example/Test.rs b/rust/src/bin/test/MyGame/Example/Test.rs deleted file mode 100644 index 55f3baf290..0000000000 --- a/rust/src/bin/test/MyGame/Example/Test.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! Automatically generated, do not modify. - -use flatbuffers; -use super::*; - -#[derive(Debug)] -pub struct Test<'a> { - table: flatbuffers::Table<'a>, -} - -enum VT { - A = 0, - B = 2,// Padding1 -} - -impl<'a> Test<'a> { - pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> Test { - Test { - table: flatbuffers::Table::with_pos(buf, offset), - } - } - - pub fn a(&self) -> i16 { - let offset = VT::A as u32; - return self.table.get_i16(offset) - } - - pub fn b(&self) -> i8 { - let offset = VT::B as u32; - return self.table.get_i8(offset) - } - -} - -impl<'a> From> for Test<'a> { - fn from(table: flatbuffers::Table) -> Test { - Test{ - table: table, - } - } -} - -pub fn build_test(builder: &mut flatbuffers::Builder, a: i16, b: i8) -> flatbuffers::UOffsetT { - builder.prep(2, 4); - builder.pad(1); - builder.add_i8(b); - builder.add_i16(a); - builder.offset() as flatbuffers::UOffsetT -} diff --git a/rust/src/bin/test/MyGame/Example/TestSimpleTableWithEnum.rs b/rust/src/bin/test/MyGame/Example/TestSimpleTableWithEnum.rs deleted file mode 100644 index b6ccba8914..0000000000 --- a/rust/src/bin/test/MyGame/Example/TestSimpleTableWithEnum.rs +++ /dev/null @@ -1,129 +0,0 @@ -//! Automatically generated, do not modify. - -use flatbuffers; -use super::*; - -#[derive(Debug)] -pub struct TestSimpleTableWithEnum<'a> { - table: flatbuffers::Table<'a>, -} - -enum VT { - COLOR = 4, -} - -impl<'a> TestSimpleTableWithEnum<'a> { - pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> TestSimpleTableWithEnum { - TestSimpleTableWithEnum { - table: flatbuffers::Table::from_offset(buf, offset), - } - } - - pub fn color(&self) -> Color { - let offset = self.table.field_offset(VT::COLOR as u16); - if offset != 0 { - return self.table.get_i8(offset).into() - } - 2.into() - } - -} - -impl<'a> From> for TestSimpleTableWithEnum<'a> { - fn from(table: flatbuffers::Table) -> TestSimpleTableWithEnum { - TestSimpleTableWithEnum{ - table: table, - } - } -} - -/// Builder Object for `TestSimpleTableWithEnum` tables. -pub struct Builder { - inner: flatbuffers::Builder, -} - -impl Builder { - /// Create a new builder. - pub fn with_capacity(size: usize) -> Self { - Builder { - inner: flatbuffers::Builder::with_capacity(size), - } - } - - /// Initialize a new `Builder` for a `TestSimpleTableWithEnum` table. - pub fn start(&mut self) { - self.inner.start_object(1); - } - - /// Finalize the current object and return the offset. - pub fn end(&mut self) -> flatbuffers::UOffsetT { - return self.inner.end_object() - } - - /// Set the value for field `color`. - pub fn add_color(&mut self, color: i8) { - self.inner.add_slot_i8(0, color, 2) - } - - /// Finish the buffer. - pub fn finish(&mut self, r: flatbuffers::UOffsetT) { - return self.inner.finish(r) - } - - pub fn create_string(&mut self, v: &str) -> flatbuffers::UOffsetT { self.inner.create_string(v) } - pub fn get_bytes(&self) -> &[u8] { self.inner.get_bytes() } - pub fn len(&self) -> usize { self.inner.len() } - pub fn offset(&self) -> usize { self.inner.offset() } - pub fn reset(&mut self) { self.inner.reset() } - pub fn prep(&mut self, s:usize, a: usize) { self.inner.prep(s,a) } - pub fn pad(&mut self, n:usize) { self.inner.pad(n) } - pub fn end_vector(&mut self) -> flatbuffers::UOffsetT { self.inner.end_vector() } - pub fn add_bool(&mut self, v:bool) { self.inner.add_bool(v) } - pub fn add_u8(&mut self, v:u8) { self.inner.add_u8(v) } - pub fn add_i8(&mut self, v:i8) { self.inner.add_i8(v) } - pub fn add_u16(&mut self, v:u16) { self.inner.add_u16(v) } - pub fn add_i16(&mut self, v:i16) { self.inner.add_i16(v) } - pub fn add_u32(&mut self, v:u32) { self.inner.add_u32(v) } - pub fn add_i32(&mut self, v:i32) { self.inner.add_i32(v) } - pub fn add_u64(&mut self, v:u64) { self.inner.add_u64(v) } - pub fn add_i64(&mut self, v:i64) { self.inner.add_i64(v) } - pub fn add_f32(&mut self, v:f32) { self.inner.add_f32(v) } - pub fn add_f64(&mut self, v:f64) { self.inner.add_f64(v) } - pub fn add_uoffset(&mut self, v: flatbuffers::UOffsetT) { self.inner.add_uoffset(v) } - pub fn add_slot_bool(&mut self, o: usize, v: bool, d: bool) { self.inner.add_slot_bool(o,v,d) } - pub fn add_slot_u8(&mut self, o: usize, v: u8, d: u8) { self.inner.add_slot_u8(o,v,d) } - pub fn add_slot_i8(&mut self, o: usize, v: i8, d: i8) { self.inner.add_slot_i8(o,v,d) } - pub fn add_slot_u16(&mut self, o: usize, v: u16, d: u16) { self.inner.add_slot_u16(o,v,d) } - pub fn add_slot_i16(&mut self, o: usize, v: i16, d: i16) { self.inner.add_slot_i16(o,v,d) } - pub fn add_slot_i32(&mut self, o: usize, v: i32, d: i32) { self.inner.add_slot_i32(o,v,d) } - pub fn add_slot_u32(&mut self, o: usize, v: u32, d: u32) { self.inner.add_slot_u32(o,v,d) } - pub fn add_slot_u64(&mut self, o: usize, v: u64, d: u64) { self.inner.add_slot_u64(o,v,d) } - pub fn add_slot_i64(&mut self, o: usize, v: i64, d: i64) { self.inner.add_slot_i64(o,v,d) } - pub fn add_slot_f32(&mut self, o: usize, v: f32, d: f32) { self.inner.add_slot_f32(o,v,d) } - pub fn add_slot_f64(&mut self, o: usize, v: f64, d: f64) { self.inner.add_slot_f64(o,v,d) } - pub fn add_slot_uoffset(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_uoffset(o,v,d) } - pub fn add_slot_struct(&mut self, o: usize, v: flatbuffers::UOffsetT, d: flatbuffers::UOffsetT) { self.inner.add_slot_struct(o,v,d) } -} - -impl Default for Builder { - fn default() -> Builder { - Builder::with_capacity(1024) - } -} - -impl From for Builder { - fn from(b: flatbuffers::Builder) -> Builder { - Builder { - inner: b, - } - } -} - -impl Into for Builder { - fn into(self) -> flatbuffers::Builder { - self.inner - } -} - -impl flatbuffers::ObjectBuilder for Builder {} - diff --git a/rust/src/bin/test/MyGame/Example/Vec3.rs b/rust/src/bin/test/MyGame/Example/Vec3.rs deleted file mode 100644 index f1714a9fdc..0000000000 --- a/rust/src/bin/test/MyGame/Example/Vec3.rs +++ /dev/null @@ -1,82 +0,0 @@ -//! Automatically generated, do not modify. - -use flatbuffers; -use super::*; - -#[derive(Debug)] -pub struct Vec3<'a> { - table: flatbuffers::Table<'a>, -} - -enum VT { - X = 0, - Y = 4, - Z = 8,// Padding4 - TEST1 = 16, - TEST2 = 24,// Padding1 - TEST3 = 26,// Padding2 -} - -impl<'a> Vec3<'a> { - pub fn new(buf: &[u8], offset: flatbuffers::UOffsetT) -> Vec3 { - Vec3 { - table: flatbuffers::Table::with_pos(buf, offset), - } - } - - pub fn x(&self) -> f32 { - let offset = VT::X as u32; - return self.table.get_f32(offset) - } - - pub fn y(&self) -> f32 { - let offset = VT::Y as u32; - return self.table.get_f32(offset) - } - - pub fn z(&self) -> f32 { - let offset = VT::Z as u32; - return self.table.get_f32(offset) - } - - pub fn test1(&self) -> f64 { - let offset = VT::TEST1 as u32; - return self.table.get_f64(offset) - } - - pub fn test2(&self) -> Color { - let offset = VT::TEST2 as u32; - return self.table.get_i8(offset).into() - } - - pub fn test3(&self) -> Test { - let offset = VT::TEST3 as u32; - return self.table.get_struct::(offset) - } - -} - -impl<'a> From> for Vec3<'a> { - fn from(table: flatbuffers::Table) -> Vec3 { - Vec3{ - table: table, - } - } -} - -pub fn build_vec3(builder: &mut flatbuffers::Builder, x: f32, y: f32, z: f32, test1: f64, test2: i8, test3_a: i16, test3_b: i8) -> flatbuffers::UOffsetT { - builder.prep(16, 32); - builder.pad(2); - builder.prep(2, 4); - builder.pad(1); - builder.add_i8(test3_b); - builder.add_i16(test3_a); - builder.pad(1); - builder.add_i8(test2); - builder.add_f64(test1); - builder.pad(4); - builder.add_f32(z); - builder.add_f32(y); - builder.add_f32(x); - builder.offset() as flatbuffers::UOffsetT -} diff --git a/rust/src/bin/test/MyGame/Example/mod.rs b/rust/src/bin/test/MyGame/Example/mod.rs deleted file mode 100644 index 657a1baab1..0000000000 --- a/rust/src/bin/test/MyGame/Example/mod.rs +++ /dev/null @@ -1,18 +0,0 @@ -//! Automatically generated, do not modify -//! -//! Flatbuffer definitions for the Example namespace. -mod color; -mod any; -pub mod test; -pub mod testsimpletablewithenum; -pub mod vec3; -pub mod stat; -pub mod monster; - -pub use self::color::*; -pub use self::any::*; -pub use self::test::{Test, build_test}; -pub use self::testsimpletablewithenum::TestSimpleTableWithEnum; -pub use self::vec3::{Vec3, build_vec3}; -pub use self::stat::Stat; -pub use self::monster::Monster; diff --git a/rust/src/bin/test/MyGame/mod.rs b/rust/src/bin/test/MyGame/mod.rs deleted file mode 100644 index b305cc9d96..0000000000 --- a/rust/src/bin/test/MyGame/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -//! Automatically generated, do not modify -//! -//! Flatbuffer definitions for the MyGame namespace. - -pub mod example; diff --git a/rust/src/builder.rs b/rust/src/builder.rs index b7ca379508..dd24beba2b 100644 --- a/rust/src/builder.rs +++ b/rust/src/builder.rs @@ -3,6 +3,8 @@ //! Builder is a state machine for creating FlatBuffer objects. //! Use a Builder to construct object(s) starting from leaf nodes. use byteorder::{ByteOrder, LittleEndian}; +use std::{io, ops, slice, ptr}; +use std::io::Write; use types::*; @@ -32,6 +34,12 @@ pub struct Builder { space: usize, // Number of elements in the current vector vector_len: usize, + // If false builder will ignore default values and always create a field + // and non-zero vslot. Default is true and will only create an entry + // if value != default. + force_defaults: bool, + // A flag to control the vtable deduplication process. see `write_vtable` + vtable_dedup: bool, } impl Builder { @@ -39,7 +47,7 @@ impl Builder { /// initial capacity of `size`. pub fn with_capacity(size: usize) -> Self { let mut bytes = Vec::with_capacity(size); - unsafe { bytes.set_len(size) }; + bytes.resize(size, 0); Builder { bytes: bytes, min_align: 1, @@ -51,6 +59,8 @@ impl Builder { vtables: Vec::with_capacity(16), space: size, vector_len: 0, + force_defaults: true, + vtable_dedup: true, } } @@ -103,32 +113,24 @@ impl Builder { /// Create a string in the buffer from an already encoded UTF-8 `String`. pub fn create_string(&mut self, value: &str) -> UOffsetT { - let len = value.len(); + // null terminated self.add_u8(0); - self.start_vector(1, len, 1); - self.space -= len; - for (i, c) in value.bytes().enumerate() { - let pos = self.space + i; - self.place_u8(pos, c); - } + self.start_vector(1, value.len(), 1); + self.write(value.as_bytes()).unwrap(); self.end_vector() } /// Create a vector in the buffer from an already encoded /// byte vector. pub fn create_vector(&mut self, value: &[u8]) -> UOffsetT { - let len = value.len(); - self.start_vector(1, len, 0); - self.space -= len; - for (i, c) in value.iter().enumerate() { - let pos = self.space + i; - self.place_u8(pos, *c); - } + self.start_vector(1, value.len(), 1); + self.write(value).unwrap(); self.end_vector() } /// Create a vector of `UOffsetT` in the buffer. /// This function will encode the values to `LittleEndian`. + #[cfg(target_endian = "big")] pub fn create_uoffset_vector(&mut self, value: &[UOffsetT]) -> UOffsetT { let len = value.len(); self.start_vector(UOFFSETT_SIZE, len, 0); @@ -140,6 +142,21 @@ impl Builder { self.end_vector() } + /// Create a vector of `UOffsetT` in the buffer. + /// This function will encode the values to `LittleEndian`. + #[cfg(target_endian = "little")] + pub fn create_uoffset_vector(&mut self, value: &[UOffsetT]) -> UOffsetT { + self.start_vector(1, value.len(), 1); + unsafe { + let ptr = value.as_ptr(); + let ptr = ptr as *const u8; + self.write(slice::from_raw_parts(ptr, value.len() * UOFFSETT_SIZE)) + .unwrap(); + } + self.end_vector() + } + + /// Finalize a table, pointing to the given `root_table`. pub fn finish_table(&mut self, root_table: UOffsetT) -> UOffsetT { self.assert_not_nested(); @@ -157,7 +174,7 @@ impl Builder { let pos = self.pos(); &self.bytes[pos..] } - + /// Returns the current buffer and replaces it with /// a `new_buffer`. /// @@ -170,7 +187,7 @@ impl Builder { new_buffer } - /// Resets the builder. + /// Clears the builder state. /// /// Clears the buffer without resizing. This allows for reuse /// without allocating new memeory. @@ -180,10 +197,8 @@ impl Builder { self.nested = false; self.finished = false; self.vtable_in_use = 0; - unsafe { - self.vtable.set_len(0); - self.vtables.set_len(0); - } + self.vtables.truncate(0); + self.vtable.truncate(0); self.space = self.bytes.capacity(); self.vector_len = 0; } @@ -198,38 +213,30 @@ impl Builder { pub fn offset(&self) -> UOffsetT { (self.bytes.len() - self.space) as UOffsetT } - + /// Returns the offset relative to the beggining /// of the buffer. pub fn pos(&self) -> usize { self.space } - /// prepare to write an element of `size` after `additional_bytes` - /// have been written. - pub fn prep(&mut self, size: usize, additional_bytes: usize) { - if size > self.min_align { - self.min_align = size - } - let align_size = self.offset() as usize + additional_bytes + 1; - let align_size = ((align_size ^ 1)) & (size - 1); - while self.space <= align_size + size + additional_bytes { - self.grow(); - } - self.pad(align_size) + /// Set the vtable default field value check. + /// + /// If true `Builder` will only write values to the table if + /// the value is not equal to the value. If false `Builder` + /// will always write the value to the table. + /// Defaults to true. + pub fn force_defaults(&mut self, defaults: bool) { + self.force_defaults = defaults; } - /// pad places zeros at the current offset. - pub fn pad(&mut self, n: usize) { - use std::ptr; - unsafe { - let mut ptr = self.bytes.as_mut_ptr().offset(self.space as isize); - for _ in 0..n { - self.space -= 1; - ptr = ptr.offset(-1); - ptr::write(ptr, 0); - } - } + /// Set the vtable deduplication process flag. + /// + /// If `true` the `Builder` will check previously written vtables + /// and reuse identical vtables to safe space at the expense of + /// CPU. If `false` this process is skipped. + pub fn vtable_dedup(&mut self, dedup: bool) { + self.vtable_dedup = dedup; } } @@ -405,7 +412,8 @@ impl Builder { /// prepends an UOffsetT, relative to where it will be written. pub fn add_uoffset(&mut self, value: UOffsetT) { self.prep(UOFFSETT_SIZE, 0); - assert!(value <= self.offset() as UOffsetT, "unreachable: off <= boffset();"); + assert!(value <= self.offset() as UOffsetT, + "unreachable: off <= boffset();"); let relative = self.offset() as u32 - value as u32 + UOFFSETT_SIZE as u32; self.put_uoffset(relative); } @@ -419,7 +427,7 @@ impl Builder { /// default `d`, then the slot will be set to zero and no other data /// will be written. pub fn add_slot_bool(&mut self, o: usize, value: bool, d: bool) { - if value != d { + if value != d || !self.force_defaults { self.add_bool(value); self.slot(o) } @@ -429,7 +437,7 @@ impl Builder { /// `x` equals default `d`, then the slot will be set to zero and no other /// data will be written. pub fn add_slot_u8(&mut self, o: usize, value: u8, d: u8) { - if value != d { + if value != d || !self.force_defaults { self.add_u8(value); self.slot(o) } @@ -446,7 +454,7 @@ impl Builder { /// `x` equals default `d`, then the slot will be set to zero and no other /// data will be written. pub fn add_slot_u16(&mut self, o: usize, value: u16, d: u16) { - if value != d { + if value != d || !self.force_defaults { self.add_u16(value); self.slot(o) } @@ -463,7 +471,7 @@ impl Builder { /// `x` equals default `d`, then the slot will be set to zero and no other /// data will be written. pub fn add_slot_u32(&mut self, o: usize, value: u32, d: u32) { - if value != d { + if value != d || !self.force_defaults { self.add_u32(value); self.slot(o) } @@ -480,7 +488,7 @@ impl Builder { /// `x` equals default `d`, then the slot will be set to zero and no other /// data will be written. pub fn add_slot_u64(&mut self, o: usize, value: u64, d: u64) { - if value != d { + if value != d || !self.force_defaults { self.add_u64(value); self.slot(o) } @@ -497,7 +505,7 @@ impl Builder { /// `x` equals default `d`, then the slot will be set to zero and no other /// data will be written. pub fn add_slot_f32(&mut self, o: usize, value: f32, d: f32) { - if value != d { + if value != d || !self.force_defaults { self.add_f32(value); self.slot(o) } @@ -507,7 +515,7 @@ impl Builder { /// `x` equals default `d`, then the slot will be set to zero and no other /// data will be written. pub fn add_slot_f64(&mut self, o: usize, value: f64, d: f64) { - if value != d { + if value != d || !self.force_defaults { self.add_f64(value); self.slot(o) } @@ -519,7 +527,7 @@ impl Builder { /// /// prepends an UOffsetT, relative to where it will be written. pub fn add_slot_uoffset(&mut self, o: usize, value: UOffsetT, d: UOffsetT) { - if value != d { + if value != d || !self.force_defaults { self.add_uoffset(value); self.slot(o) } @@ -529,12 +537,12 @@ impl Builder { /// Structs are stored inline, so nothing additional is being added. /// In generated code, `d` is always 0. pub fn add_slot_struct(&mut self, o: usize, value: UOffsetT, d: UOffsetT) { - if value != d { + if value != d || !self.force_defaults { self.assert_nested(); - assert!(value == self.offset() as u32, "Inline data write outside of object.\ - Write the slot_struct immediatly after \ - writing the struct slot."); - self.slot(o) + assert!(value == self.offset() as u32, + "Inline data write outside of object.Write the slot_struct immediatly after \ + writing the struct slot."); + self.slot(o) } } @@ -544,7 +552,7 @@ impl Builder { use std::ptr; unsafe { let ptr = self.bytes.as_mut_ptr().offset(pos as isize); - ptr::write(ptr,value) + ptr::write(ptr, value) } } @@ -568,8 +576,7 @@ impl Builder { /// Check to assert `finish` has not been called. pub fn assert_not_finished(&self) { - assert!(!self.finished, - "FlatBuffers: root table is not finished."); + assert!(!self.finished, "FlatBuffers: root table is not finished."); } /// Check to assert `start_object` has not been called. @@ -577,7 +584,7 @@ impl Builder { assert!(!self.nested, "FlatBuffers: object serialization must not be nested."); } - + /// Check to assert `start_object` has been called. pub fn assert_nested(&self) { assert!(self.nested, @@ -617,15 +624,42 @@ impl Builder { "FlatBuffers: cannot grow buffer beyond 2 gigabytes."); let new_capacity = old_capacity << 1; let mut nbytes = Vec::with_capacity(new_capacity); - for _ in 0..old_capacity { - nbytes.push(0) + // fill front of buffer with zeroes + if self.bytes.capacity() == 0 { + nbytes.resize(new_capacity, 0); + } else { + nbytes.resize(old_capacity, 0); + // extend the buffer with the old buffer + nbytes.extend_from_slice(&self.bytes); } self.space = new_capacity - self.offset() as usize; - nbytes.extend_from_slice(&self.bytes); - unsafe { nbytes.set_len(new_capacity) }; self.bytes = nbytes; } + /// prepare to write an element of `size` after `additional_bytes` + /// have been written. + pub fn prep(&mut self, size: usize, additional_bytes: usize) { + if size > self.min_align { + self.min_align = size + } + let align_size = self.offset() as usize + additional_bytes + 1; + let align_size = ((align_size ^ 1)) & (size - 1); + while self.space <= align_size + size + additional_bytes { + self.grow(); + } + self.pad(align_size) + } + + /// pad places zeros at the current offset. + pub fn pad(&mut self, n: usize) { + for _ in 0..n { + self.space -= 1; + unsafe { + ptr::write(self.bytes.get_unchecked_mut(self.space), 0); + } + } + } + // WriteVtable serializes the vtable for the current object. // // Before writing out the vtable, this checks pre-existing vtables for @@ -655,24 +689,26 @@ impl Builder { // check for identical vtable let mut existing_vt = 0; let mut this_vt = self.space; - 'outer: for (i, vt_offset) in self.vtables.iter().rev().enumerate() { - let vt_start = self.bytes.len() - *vt_offset as usize; - let vt_len = self.get_u16(vt_start); - if vt_len != self.get_u16(this_vt) { - continue; - } - let vt_end = vt_start + vt_len as usize; - let vt_bytes = &self.bytes[vt_start + VTABLE_METADATA_SIZE..vt_end]; - for (j, chunk) in vt_bytes.chunks(VOFFSETT_SIZE).enumerate() { - let this_start = this_vt + VTABLE_METADATA_SIZE + (j * VOFFSETT_SIZE) as usize; - let this_end = this_start + VOFFSETT_SIZE; - let this_chunk = &self.bytes[this_start..this_end]; - if chunk != this_chunk { - continue 'outer; + if self.vtable_dedup { + 'outer: for (i, vt_offset) in self.vtables.iter().rev().enumerate() { + let vt_start = self.bytes.len() - *vt_offset as usize; + let vt_len = self.get_u16(vt_start); + if vt_len != self.get_u16(this_vt) { + continue; + } + let vt_end = vt_start + vt_len as usize; + let vt_bytes = &self.bytes[vt_start + VTABLE_METADATA_SIZE..vt_end]; + for (j, chunk) in vt_bytes.chunks(VOFFSETT_SIZE).enumerate() { + let this_start = this_vt + VTABLE_METADATA_SIZE + (j * VOFFSETT_SIZE) as usize; + let this_end = this_start + VOFFSETT_SIZE; + let this_chunk = &self.bytes[this_start..this_end]; + if chunk != this_chunk { + continue 'outer; + } } + existing_vt = self.vtables[i] as usize; + break 'outer; } - existing_vt = self.vtables[i] as usize; - break 'outer; } if existing_vt != 0 { @@ -704,6 +740,33 @@ impl Into> for Builder { } } +impl ops::Deref for Builder { + type Target = [u8]; + + fn deref(&self) -> &[u8] { + &self.bytes + } +} + +impl Write for Builder { + fn write(&mut self, bytes: &[u8]) -> io::Result { + let len = bytes.len(); + self.space -= len; + + for i in 0..bytes.len() { + let pos = self.space + i; + unsafe { + ptr::write(self.bytes.get_unchecked_mut(pos), bytes.get_unchecked(i).clone()); + } + } + Ok(len) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + #[cfg(test)] mod test { use super::Builder; @@ -796,11 +859,11 @@ mod test { // test 3: 2xbyte vector b = Builder::with_capacity(0); b.start_vector(1, 2, 1); - check(&b, 14, &[0,0]); // align to 4bytes + check(&b, 14, &[0, 0]); // align to 4bytes b.add_u8(1); - check(&b, 15, &[1,0,0]); + check(&b, 15, &[1, 0, 0]); b.add_u8(2); - check(&b, 16, &[2,1,0,0]); + check(&b, 16, &[2, 1, 0, 0]); b.end_vector(); check(&b, 17, &[2, 0, 0, 0, 2, 1, 0, 0]); // padding @@ -812,17 +875,17 @@ mod test { b.add_u8(i); } b.end_vector(); - // says size is 8 not 11 + // says size is 8 not 11 check(&b, 19, &[8, 0, 0, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]); // test 4: 1xuint16 vector b = Builder::with_capacity(0); b.start_vector(2, 1, 1); - check(&b, 20, &[0,0]); // align to 4bytes + check(&b, 20, &[0, 0]); // align to 4bytes b.add_u16(1); - check(&b, 21, &[1,0,0,0]); + check(&b, 21, &[1, 0, 0, 0]); b.end_vector(); - check(&b, 22, &[1,0,0,0,1,0,0,0]); // padding + check(&b, 22, &[1, 0, 0, 0, 1, 0, 0, 0]); // padding // test 5: 2xuint16 vector b = Builder::with_capacity(0); @@ -831,7 +894,7 @@ mod test { b.add_u16(0xABCD); check(&b, 24, &[0xCD, 0xAB]); b.add_u16(0xDCBA); - check(&b, 25, &[0xBA, 0xDC,0xCD, 0xAB]); + check(&b, 25, &[0xBA, 0xDC, 0xCD, 0xAB]); b.end_vector(); check(&b, 25, &[2, 0, 0, 0, 0xBA, 0xDC, 0xCD, 0xAB]); @@ -840,8 +903,10 @@ mod test { b.create_string("foo"); check(&b, 26, &[3, 0, 0, 0, 102, 111, 111, 0]); // 0-terminated, no pad b.create_string("moop"); - check(&b, 27, &[4, 0, 0, 0, 109, 111, 111, 112, 0, 0, 0, 0, // 0-terminated, 3-byte pad - 3, 0, 0, 0, 102, 111, 111, 0]); + check(&b, + 27, + &[4, 0, 0, 0, 109, 111, 111, 112, 0, 0, 0, 0 /* 0-terminated, 3-byte pad */, + 3, 0, 0, 0, 102, 111, 111, 0]); // test 7: empty vtable b = Builder::with_capacity(0); @@ -856,15 +921,14 @@ mod test { check(&b, 30, &[]); b.add_slot_bool(0, true, false); b.end_object(); - check(&b, 31, &[ - 6, 0, // vtable bytes - 8, 0, // length of object including vtable offset - 7, 0, // start of bool value - 6, 0, 0, 0, // offset for start of vtable (int32) - 0, 0, 0, // padded to 4 bytes - 1, // bool value - ]); - + check(&b, + 31, + &[6, 0 /* vtable bytes */, 8, + 0 /* length of object including vtable offset */, 7, + 0 /* start of bool value */, 6, 0, 0, + 0 /* offset for start of vtable (int32) */, 0, 0, + 0 /* padded to 4 bytes */, 1 /* bool value */]); + // test 9: vtable with one default bool b = Builder::with_capacity(0); @@ -872,26 +936,23 @@ mod test { check(&b, 32, &[]); b.add_slot_bool(0, false, false); b.end_object(); - check(&b, 33, &[ - 6, 0, // vtable bytes - 4, 0, // end of object from here - 0, 0, // entry 1 is zero - 6, 0, 0, 0, // offset for start of vtable (int32) - ]); + check(&b, + 33, + &[6, 0 /* vtable bytes */, 4, 0 /* end of object from here */, 0, + 0 /* entry 1 is zero */, 6, 0, 0, + 0 /* offset for start of vtable (int32) */]); // test 10: vtable with one int16 b = Builder::with_capacity(0); b.start_object(1); b.add_slot_i16(0, 0x789A, 0); b.end_object(); - check(&b, 34, &[ - 6, 0, // vtable bytes - 8, 0, // end of object from here - 6, 0, // offset to value - 6, 0, 0, 0, // offset for start of vtable (int32) - 0, 0, // padding to 4 bytes - 0x9A, 0x78, - ]); + check(&b, + 34, + &[6, 0 /* vtable bytes */, 8, 0 /* end of object from here */, 6, + 0 /* offset to value */, 6, 0, 0, + 0 /* offset for start of vtable (int32) */, 0, + 0 /* padding to 4 bytes */, 0x9A, 0x78]); // test 11: vtable with two int16 b = Builder::with_capacity(0); @@ -899,15 +960,12 @@ mod test { b.add_slot_i16(0, 0x3456, 0); b.add_slot_i16(1, 0x789A, 0); b.end_object(); - check(&b, 35, &[ - 8, 0, // vtable bytes - 8, 0, // end of object from here - 6, 0, // offset to value 0 - 4, 0, // offset to value 1 - 8, 0, 0, 0, // offset for start of vtable (int32) - 0x9A, 0x78, // value 1 - 0x56, 0x34, // value 0 - ]); + check(&b, + 35, + &[8, 0 /* vtable bytes */, 8, 0 /* end of object from here */, 6, + 0 /* offset to value 0 */, 4, 0 /* offset to value 1 */, 8, 0, 0, + 0 /* offset for start of vtable (int32) */, 0x9A, 0x78 /* value 1 */, + 0x56, 0x34 /* value 0 */]); // test 12a: vtable with int16 and bool b = Builder::with_capacity(0); @@ -915,16 +973,12 @@ mod test { b.add_slot_i16(0, 0x3456, 0); b.add_slot_bool(1, true, false); b.end_object(); - check(&b, 36, &[ - 8, 0, // vtable bytes - 8, 0, // end of object from here - 6, 0, // offset to value 0 - 5, 0, // offset to value 1 - 8, 0, 0, 0, // offset for start of vtable (int32) - 0, // padding - 1, // value 1 - 0x56, 0x34, // value 0 - ]); + check(&b, + 36, + &[8, 0 /* vtable bytes */, 8, 0 /* end of object from here */, 6, + 0 /* offset to value 0 */, 5, 0 /* offset to value 1 */, 8, 0, 0, + 0 /* offset for start of vtable (int32) */, 0 /* padding */, + 1 /* value 1 */, 0x56, 0x34 /* value 0 */]); // test 12b: vtable with empty vector b = Builder::with_capacity(0); @@ -933,14 +987,11 @@ mod test { b.start_object(1); b.add_slot_uoffset(0, vecend, 0); b.end_object(); - check(&b, 37, &[ - 6, 0, // vtable bytes - 8, 0, - 4, 0, // offset to vector offset - 6, 0, 0, 0, // offset for start of vtable (int32) - 4, 0, 0, 0, - 0, 0, 0, 0, // length of vector (not in struct) - ]); + check(&b, + 37, + &[6, 0 /* vtable bytes */, 8, 0, 4, 0 /* offset to vector offset */, 6, + 0, 0, 0 /* offset for start of vtable (int32) */, 4, 0, 0, 0, 0, 0, 0, + 0 /* length of vector (not in struct) */]); // test 12c: vtable with empty vector of byte and some scalars b = Builder::with_capacity(0); @@ -950,28 +1001,20 @@ mod test { b.add_slot_i16(0, 55, 0); b.add_slot_uoffset(1, vecend, 0); b.end_object(); - check(&b, 38, &[ - 8, 0, // vtable bytes - 12, 0, - 10, 0, // offset to value 0 - 4, 0, // offset to vector offset - 8, 0, 0, 0, // vtable loc - 8, 0, 0, 0, // value 1 - 0, 0, 55, 0, // value 0 - 0, 0, 0, 0, // length of vector (not in struct) - ]); + check(&b, + 38, + &[8, 0 /* vtable bytes */, 12, 0, 10, 0 /* offset to value 0 */, 4, + 0 /* offset to vector offset */, 8, 0, 0, 0 /* vtable loc */, 8, 0, 0, + 0 /* value 1 */, 0, 0, 55, 0 /* value 0 */, 0, 0, 0, + 0 /* length of vector (not in struct) */]); { let buffer = b.get_bytes(); - assert_eq!(buffer, &[ - 8, 0, // vtable bytes - 12, 0, - 10, 0, // offset to value 0 - 4, 0, // offset to vector offset - 8, 0, 0, 0, // vtable loc - 8, 0, 0, 0, // value 1 - 0, 0, 55, 0, // value 0 - 0, 0, 0, 0, // length of vector (not in struct) - ]); + assert_eq!(buffer, + &[8, 0 /* vtable bytes */, 12, 0, 10, 0 /* offset to value 0 */, + 4, 0 /* offset to vector offset */, 8, 0, 0, + 0 /* vtable loc */, 8, 0, 0, 0 /* value 1 */, 0, 0, 55, + 0 /* value 0 */, 0, 0, 0, + 0 /* length of vector (not in struct) */]); } // test 13: vtable with 1 int16 and 2-vector of int16 @@ -984,24 +1027,20 @@ mod test { b.add_slot_uoffset(1, vecend, 0); b.add_slot_i16(0, 55, 0); b.end_object(); - check(&b, 39, &[ - 8, 0, // vtable bytes - 12, 0, // length of object - 6, 0, // start of value 0 from end of vtable - 8, 0, // start of value 1 from end of buffer - 8, 0, 0, 0, // offset for start of vtable (int32) - 0, 0, // padding - 55, 0, // value 0 - 4, 0, 0, 0, // vector position from here - 2, 0, 0, 0, // length of vector (uint32) - 0x78, 0x56, // vector value 1 - 0x34, 0x12, // vector value 0 - ]); + check(&b, + 39, + &[8, 0 /* vtable bytes */, 12, 0 /* length of object */, 6, + 0 /* start of value 0 from end of vtable */, 8, + 0 /* start of value 1 from end of buffer */, 8, 0, 0, + 0 /* offset for start of vtable (int32) */, 0, 0 /* padding */, 55, + 0 /* value 0 */, 4, 0, 0, 0 /* vector position from here */, 2, 0, 0, + 0 /* length of vector (uint32) */, 0x78, 0x56 /* vector value 1 */, + 0x34, 0x12 /* vector value 0 */]); // test 14: vtable with 1 struct of 1 int8, 1 int16, 1 int32 b = Builder::with_capacity(0); b.start_object(1); - b.prep(4+4+4, 0); + b.prep(4 + 4 + 4, 0); b.add_i8(55); b.pad(3); b.add_i16(0x1234); @@ -1010,21 +1049,17 @@ mod test { let struct_start = b.offset(); b.add_slot_struct(0, struct_start as u32, 0); b.end_object(); - check(&b, 40, &[ - 6, 0, // vtable bytes - 16, 0, // end of object from here - 4, 0, // start of struct from here - 6, 0, 0, 0, // offset for start of vtable (int32) - 0x78, 0x56, 0x34, 0x12, // value 2 - 0, 0, // padding - 0x34, 0x12, // value 1 - 0, 0, 0, // padding - 55, // value 0 - ]); - - // test 15: vtable with 1 vector of 2 struct of 2 int8 + check(&b, + 40, + &[6, 0 /* vtable bytes */, 16, 0 /* end of object from here */, 4, + 0 /* start of struct from here */, 6, 0, 0, + 0 /* offset for start of vtable (int32) */, 0x78, 0x56, 0x34, + 0x12 /* value 2 */, 0, 0 /* padding */, 0x34, 0x12 /* value 1 */, + 0, 0, 0 /* padding */, 55 /* value 0 */]); + + // test 15: vtable with 1 vector of 2 struct of 2 int8 b = Builder::with_capacity(0); - b.start_vector(1*2, 2, 1); + b.start_vector(1 * 2, 2, 1); b.add_i8(33); b.add_i8(44); b.add_i8(55); @@ -1033,19 +1068,13 @@ mod test { b.start_object(1); b.add_slot_uoffset(0, vecend, 0); b.end_object(); - check(&b, 41, &[ - 6, 0, // vtable bytes - 8, 0, - 4, 0, // offset of vector offset - 6, 0, 0, 0, // offset for start of vtable (int32) - 4, 0, 0, 0, // vector start offset - - 2, 0, 0, 0, // vector length - 66, // vector value 1,1 - 55, // vector value 1,0 - 44, // vector value 0,1 - 33, // vector value 0,0 - ]); + check(&b, + 41, + &[6, 0 /* vtable bytes */, 8, 0, 4, 0 /* offset of vector offset */, 6, + 0, 0, 0 /* offset for start of vtable (int32) */, 4, 0, 0, + 0 /* vector start offset */, 2, 0, 0, 0 /* vector length */, + 66 /* vector value 1,1 */, 55 /* vector value 1,0 */, + 44 /* vector value 0,1 */, 33 /* vector value 0,0 */]); // test 16: table with some elements b = Builder::with_capacity(0); @@ -1055,22 +1084,15 @@ mod test { let off = b.end_object(); b.finish_table(off); - check(&b, 42, &[ - 12, 0, 0, 0, // root of table: points to vtable offset - - 8, 0, // vtable bytes - 8, 0, // end of object from here - 7, 0, // start of value 0 - 4, 0, // start of value 1 - - 8, 0, 0, 0, // offset for start of vtable (int32) - - 66, 0, // value 1 - 0, // padding - 33, // value 0 - ]); - - // test 17: one unfinished table and one finished table + check(&b, + 42, + &[12, 0, 0, 0 /* root of table: points to vtable offset */, 8, + 0 /* vtable bytes */, 8, 0 /* end of object from here */, 7, + 0 /* start of value 0 */, 4, 0 /* start of value 1 */, 8, 0, 0, + 0 /* offset for start of vtable (int32) */, 66, 0 /* value 1 */, + 0 /* padding */, 33 /* value 0 */]); + + // test 17: one unfinished table and one finished table b = Builder::with_capacity(0); b.start_object(2); b.add_slot_i8(0, 33, 0); @@ -1085,32 +1107,19 @@ mod test { let obj2 = b.end_object(); b.finish_table(obj2); - check(&b, 43, &[ - 16, 0, 0, 0, // root of table: points to object - 0, 0, // padding - - 10, 0, // vtable bytes - 8, 0, // size of object - 7, 0, // start of value 0 - 6, 0, // start of value 1 - 5, 0, // start of value 2 - 10, 0, 0, 0, // offset for start of vtable (int32) - 0, // padding - 77, // value 2 - 66, // value 1 - 55, // value 0 - - 12, 0, 0, 0, // root of table: points to object - - 8, 0, // vtable bytes - 8, 0, // size of object - 7, 0, // start of value 0 - 6, 0, // start of value 1 - 8, 0, 0, 0, // offset for start of vtable (int32) - 0, 0, // padding - 44, // value 1 - 33, // value 0 - ]); + check(&b, + 43, + &[16, 0, 0, 0 /* root of table: points to object */, 0, 0 /* padding */, + 10, 0 /* vtable bytes */, 8, 0 /* size of object */, 7, + 0 /* start of value 0 */, 6, 0 /* start of value 1 */, 5, + 0 /* start of value 2 */, 10, 0, 0, + 0 /* offset for start of vtable (int32) */, 0 /* padding */, + 77 /* value 2 */, 66 /* value 1 */, 55 /* value 0 */, 12, 0, 0, + 0 /* root of table: points to object */, 8, 0 /* vtable bytes */, 8, + 0 /* size of object */, 7, 0 /* start of value 0 */, 6, + 0 /* start of value 1 */, 8, 0, 0, + 0 /* offset for start of vtable (int32) */, 0, 0 /* padding */, + 44 /* value 1 */, 33 /* value 0 */]); assert!(b.offset() as usize + b.pos() == b.len()); // test 18: a bunch of bools @@ -1127,30 +1136,17 @@ mod test { let off = b.end_object(); b.finish_table(off); - check(&b, 44, &[ - 24, 0, 0, 0, // root of table: points to vtable offset - - 20, 0, // vtable bytes - 12, 0, // size of object - 11, 0, // start of value 0 - 10, 0, // start of value 1 - 9, 0, // start of value 2 - 8, 0, // start of value 3 - 7, 0, // start of value 4 - 6, 0, // start of value 5 - 5, 0, // start of value 6 - 4, 0, // start of value 7 - 20, 0, 0, 0, // vtable offset - - 1, // value 7 - 1, // value 6 - 1, // value 5 - 1, // value 4 - 1, // value 3 - 1, // value 2 - 1, // value 1 - 1, // value 0 - ]); + check(&b, + 44, + &[24, 0, 0, 0 /* root of table: points to vtable offset */, 20, + 0 /* vtable bytes */, 12, 0 /* size of object */, 11, + 0 /* start of value 0 */, 10, 0 /* start of value 1 */, 9, + 0 /* start of value 2 */, 8, 0 /* start of value 3 */, 7, + 0 /* start of value 4 */, 6, 0 /* start of value 5 */, 5, + 0 /* start of value 6 */, 4, 0 /* start of value 7 */, 20, 0, 0, + 0 /* vtable offset */, 1 /* value 7 */, 1 /* value 6 */, + 1 /* value 5 */, 1 /* value 4 */, 1 /* value 3 */, + 1 /* value 2 */, 1 /* value 1 */, 1 /* value 0 */]); // test 19: three bools @@ -1162,23 +1158,14 @@ mod test { let off = b.end_object(); b.finish_table(off); - check(&b, 45, &[ - 16, 0, 0, 0, // root of table: points to vtable offset - - 0, 0, // padding - - 10, 0, // vtable bytes - 8, 0, // size of object - 7, 0, // start of value 0 - 6, 0, // start of value 1 - 5, 0, // start of value 2 - 10, 0, 0, 0, // vtable offset from here - - 0, // padding - 1, // value 2 - 1, // value 1 - 1, // value 0 - ]); + check(&b, + 45, + &[16, 0, 0, 0 /* root of table: points to vtable offset */, 0, + 0 /* padding */, 10, 0 /* vtable bytes */, 8, + 0 /* size of object */, 7, 0 /* start of value 0 */, 6, + 0 /* start of value 1 */, 5, 0 /* start of value 2 */, 10, 0, 0, + 0 /* vtable offset from here */, 0 /* padding */, 1 /* value 2 */, + 1 /* value 1 */, 1 /* value 0 */]); // test 20: some floats b = Builder::with_capacity(0); @@ -1186,103 +1173,86 @@ mod test { b.add_slot_f32(0, 1.0, 0.0); b.end_object(); - check(&b, 46, &[ - 6, 0, // vtable bytes - 8, 0, // size of object - 4, 0, // start of value 0 - 6, 0, 0, 0, // vtable offset - - 0, 0, 128, 63, // value 0 - ]); + check(&b, + 46, + &[6, 0 /* vtable bytes */, 8, 0 /* size of object */, 4, + 0 /* start of value 0 */, 6, 0, 0, 0 /* vtable offset */, 0, 0, 128, + 63 /* value 0 */]); } #[test] fn duplicate_vtable() { let mut b = Builder::with_capacity(0); - - b.start_object(4); - b.add_slot_u8(0, 0, 0); - b.add_slot_u8(1, 11, 0); - b.add_slot_u8(2, 22, 0); - b.add_slot_i16(3, 33, 0); - let obj0 = b.end_object(); - - b.start_object(4); - b.add_slot_u8(0, 0, 0); - b.add_slot_u8(1, 44, 0); - b.add_slot_u8(2, 55, 0); - b.add_slot_i16(3, 66, 0); - let obj1 = b.end_object(); - - b.start_object(4); - b.add_slot_u8(0, 0, 0); - b.add_slot_u8(1, 77, 0); - b.add_slot_u8(2, 88, 0); - b.add_slot_i16(3, 99, 0); - let obj2 = b.end_object(); + + b.start_object(4); + b.add_slot_u8(0, 0, 0); + b.add_slot_u8(1, 11, 0); + b.add_slot_u8(2, 22, 0); + b.add_slot_i16(3, 33, 0); + let obj0 = b.end_object(); + + b.start_object(4); + b.add_slot_u8(0, 0, 0); + b.add_slot_u8(1, 44, 0); + b.add_slot_u8(2, 55, 0); + b.add_slot_i16(3, 66, 0); + let obj1 = b.end_object(); + + b.start_object(4); + b.add_slot_u8(0, 0, 0); + b.add_slot_u8(1, 77, 0); + b.add_slot_u8(2, 88, 0); + b.add_slot_i16(3, 99, 0); + let obj2 = b.end_object(); let got = b.get_bytes(); - let want: &[u8] = &[ - 240, 255, 255, 255, // == -12. offset to dedupped vtable. - 99, 0, - 88, - 77, - 248, 255, 255, 255, // == -8. offset to dedupped vtable. - 66, 0, - 55, - 44, - 12, 0, - 8, 0, - 0, 0, - 7, 0, - 6, 0, - 4, 0, - 12, 0, 0, 0, - 33, 0, - 22, - 11, - ]; - assert!(got == want, "testVtableDeduplication want:\n{} {:?}\nbut got:\n{} {:?}\n", - want.len(), want, got.len(), got); - use std::rc::Rc; + let want: &[u8] = &[240, 255, 255, 255 /* == -12. offset to dedupped vtable. */, 99, + 0, 88, 77, 248, 255, 255, + 255 /* == -8. offset to dedupped vtable. */, 66, 0, 55, 44, 12, + 0, 8, 0, 0, 0, 7, 0, 6, 0, 4, 0, 12, 0, 0, 0, 33, 0, 22, 11]; + assert!(got == want, + "testVtableDeduplication want:\n{} {:?}\nbut got:\n{} {:?}\n", + want.len(), + want, + got.len(), + got); let len = got.len(); - let rc = Rc::new(got.to_vec()); - let table0 = Table::with_pos(rc.clone(), len - obj0 as usize); - let table1 = Table::with_pos(rc.clone(), len - obj1 as usize); - let table2 = Table::with_pos(rc, len - obj2 as usize); - fn test_table(tab: &Table, a: VOffsetT, b: u8, c: u8, d: u8) { - let got = tab.read_voffset_slot(0, 0); + let table0 = Table::get_root(got, len - obj0 as usize); + let table1 = Table::get_root(got, len - obj1 as usize); + let table2 = Table::get_root(got, len - obj2 as usize); + fn test_table(tab: &Table<&[u8]>, a: VOffsetT, b: u8, c: u8, d: u8) { + let got = tab.field_offset(0); if 12 != got { - panic!("failed 0, 0: {}", got) - } - // object size - let got = tab.read_voffset_slot(2, 0); - if 8 != got { - panic!("failed 2, 0: {}", got) - } - // default value - let got = tab.read_voffset_slot(4, 0); - if a != got { - panic!("failed 4, 0: {}", got) - } + panic!("failed 0, 0: {}", got) + } + // object size + let got = tab.field_offset(2); + if 8 != got { + panic!("failed 2, 0: {}", got) + } + // default value + let got = tab.field_offset(4); + if a != got { + panic!("failed 4, 0: {}", got) + } let got = tab.get_slot_u8(6, 0); - if b != got as u8 { - panic!("failed 6, 0: {}", got) - } + if b != got as u8 { + panic!("failed 6, 0: {}", got) + } let val = tab.get_slot_u8(8, 0); - if c != val as u8 { - panic!("failed 8, 0: {}", got) - } - let got = tab.get_slot_u8(10, 0); - if d != got as u8 { - panic!("failed 10, 0: {}", got) - } + if c != val as u8 { + panic!("failed 8, 0: {}", got) + } + let got = tab.get_slot_u8(10, 0); + if d != got as u8 { + panic!("failed 10, 0: {}", got) + } } test_table(&table0, 0, 11, 22, 33); - test_table(&table1, 0, 44, 55, 66); - test_table(&table2, 0, 77, 88, 99); + test_table(&table1, 0, 44, 55, 66); + test_table(&table2, 0, 77, 88, 99); } } diff --git a/rust/src/iter.rs b/rust/src/iter.rs index fd2fc4b2aa..7573bc37f6 100644 --- a/rust/src/iter.rs +++ b/rust/src/iter.rs @@ -1,164 +1,162 @@ -use std::iter; -use std::rc::Rc; use std::marker::PhantomData; use byteorder::{ByteOrder, LittleEndian}; -use table; -use table::{Table,TableObject}; +use types::*; +use table::Table; -/// An iterator over flatbuffer vectors. +/// An iterator over vectors of flatbuffer objects. #[derive(Debug)] -pub struct Iterator<'a, T> { - buffer: Option<&'a Rc>>, - index: usize, - len: usize, - i: usize, - _marker: PhantomData +pub struct Iter<'a, T: 'a> { + buffer: &'a [u8], + start: usize, + end: usize, + _marker: PhantomData<&'a [T]>, } -impl<'a, T> Iterator<'a, T> { +impl<'a, T: VectorType<'a>> Iter<'a, T> { /// Create a new Iterator for type `T` starting at `index` with /// a length of `len` items of size `T`. - pub fn new(buffer: &Rc>, index: usize, len: usize) -> Iterator { - Iterator { - buffer: Some(buffer), - index: index, - len: len, - i: 0, - _marker: PhantomData + pub fn new<'b>(buffer: &'b [u8], index: usize, len: usize) -> Iter<'b, T> { + Iter { + buffer: buffer, + start: index, + end: len * T::inline_size(), + _marker: PhantomData, } } } -impl<'a, T> Default for Iterator<'a, T> { - fn default() -> Iterator<'a, T> { - Iterator { - buffer: None, - index: 0, - len: 0, - i: 0, - _marker: PhantomData +// Its akward to have a default empty iterator but +// it means that the Table module can return +// `Iter` rather than `Option` for +// table vector slots (with defaults). +impl<'a, T> Default for Iter<'a, T> { + fn default() -> Iter<'a, T> { + Iter { + buffer: &[], + start: 0, + end: 0, + _marker: PhantomData, } } } -macro_rules! size_hint { - () => { - fn size_hint(&self) -> (usize, Option) { - (self.len, Some(self.len)) - } - } -} - -impl<'a> iter::Iterator for Iterator<'a, &'a str> { +impl<'a> Iterator for Iter<'a, &'a str> { type Item = &'a str; fn next(&mut self) -> Option<&'a str> { - use std::str; - if self.i < self.len { - self.i += 1; - if self.buffer.unwrap().len() >= self.index + 4 { - let offset = LittleEndian::read_u32(&self.buffer.unwrap()[self.index..]) as usize + self.index; - let start = offset as usize + 4; - let length = table::read_uoffset(self.buffer.unwrap(), offset as usize) as usize; - let s = &self.buffer.unwrap()[start..start+length]; - let res = unsafe { str::from_utf8_unchecked(s) }; - self.index += 4; - return Some(res) - } + if self.start == self.end { + return None; } - None + let ret = Table::<&[u8]>::read_str(&self.buffer[self.start..]); + self.start += UOFFSETT_SIZE; + Some(ret) + } + + fn size_hint(&self) -> (usize, Option) { + let len = (self.end - self.start) / 4; + (len, Some(len)) } - size_hint!(); } -impl<'a, T: TableObject> iter::Iterator for Iterator<'a, T> { - type Item = T; - - fn next(&mut self) -> Option { - if self.i < self.len { - self.i += 1; - if self.buffer.unwrap().len() >= self.index + T::inline_size() { - let table = if T::is_struct() { - Table::with_pos(self.buffer.unwrap().clone(), self.index as usize) - } else { - Table::from_offset(self.buffer.unwrap().clone(), self.index as usize) - }; - let res = table.into(); - self.index += T::inline_size(); - return Some(res) - } +impl<'a> DoubleEndedIterator for Iter<'a, &'a str> { + fn next_back(&mut self) -> Option<&'a str> { + if self.start == self.end { + return None; } - None + self.end -= UOFFSETT_SIZE; + let ret = Table::<&[u8]>::read_str(&self.buffer[self.end..]); + Some(ret) } - size_hint!(); } -impl<'a> iter::Iterator for Iterator<'a, bool> { - type Item = bool; +impl<'a> ExactSizeIterator for Iter<'a, &'a str> {} - fn next(&mut self) -> Option { - if self.i < self.len { - self.i += 1; - if self.buffer.unwrap().len() >= self.index + 1 { - let res = self.buffer.unwrap()[self.index] == 0; - self.index += 1; - return Some(res) - } +impl<'a, T: VectorType<'a>> Iterator for Iter<'a, T> { + type Item = T::Item; + + fn next(&mut self) -> Option { + if self.start == self.end { + return None; } - None + let ret = T::read_next(&self.buffer[self.start..]); + self.start += T::inline_size(); + Some(ret) + } + + fn size_hint(&self) -> (usize, Option) { + let len = (self.end - self.start) / T::inline_size(); + (len, Some(len)) } - size_hint!(); } -macro_rules! little_iterator { - ($ty:ty) => { - impl<'a> iter::Iterator for Iterator<'a, $ty> { - type Item = $ty; +impl<'a, T: VectorType<'a>> DoubleEndedIterator for Iter<'a, T> { + fn next_back(&mut self) -> Option { + if self.start == self.end { + return None; + } + self.end -= T::inline_size(); + let ret = T::read_next(&self.buffer[self.end..]); + Some(ret) + } +} - fn next(&mut self) -> Option<$ty> { - if self.i < self.len { - self.i += 1; - if self.buffer.unwrap().len() >= self.index + 1 { - let res = self.buffer.unwrap()[self.index] as $ty; - self.index += 1; - return Some(res) - } - } - None +impl<'a, T: VectorType<'a>> ExactSizeIterator for Iter<'a, T> {} + +/// A trait for any Flatbuffer type that can occur in a vector. +/// Flatbuffer tables and structs wil need to implemente this trait. +pub trait VectorType<'a> { + /// The type returned by the itertator over this `ScalarVectorType` + type Item; + /// Return the linline length in bytes of the `ScalarVectorType`. + fn inline_size() -> usize; + /// Read one value of `ScalarVectorType` from the front of the + /// buffer. + fn read_next(buffer: &'a [u8]) -> Self::Item; +} + +macro_rules! vector_type { + ($ty:ty, $size:expr, $fun:ident) => { + impl<'a> VectorType<'a> for $ty { + type Item = $ty; + fn inline_size() -> usize { $size } + fn read_next(buffer: &[u8]) -> $ty { + $fun(buffer) } - size_hint!(); } }; - ($ty:ty, $size:expr, $fun:ident) => { - impl<'a> iter::Iterator for Iterator<'a, $ty> { + ($ty:ty, $size:expr, $md:ident::$fun:ident) => { + impl<'a> VectorType<'a> for $ty { type Item = $ty; - - fn next(&mut self) -> Option<$ty> { - if self.i < self.len { - self.i += 1; - if self.buffer.unwrap().len() >= self.index + $size { - let res = LittleEndian::$fun(&self.buffer.unwrap()[self.index..]); - self.index += $size; - return Some(res) - } - } - None + fn inline_size() -> usize { $size } + fn read_next(buffer: &[u8]) -> $ty { + $md::$fun(buffer) } - size_hint!(); } } } -little_iterator!(u8); -little_iterator!(i8); -little_iterator!(u16, 2, read_u16); -little_iterator!(i16, 2, read_i16); -little_iterator!(u32, 4, read_u32); -little_iterator!(i32, 4, read_i32); -little_iterator!(u64, 8, read_u64); -little_iterator!(i64, 8, read_i64); -little_iterator!(f32, 4, read_f32); -little_iterator!(f64, 8, read_f64); +vector_type!(bool, 1, read_bool); +vector_type!(u8, 1, read_u8); +vector_type!(i8, 1, read_i8); +vector_type!(u16, 2, LittleEndian::read_u16); +vector_type!(i16, 2, LittleEndian::read_i16); +vector_type!(u32, 4, LittleEndian::read_u32); +vector_type!(i32, 4, LittleEndian::read_i32); +vector_type!(u64, 8, LittleEndian::read_u64); +vector_type!(i64, 8, LittleEndian::read_i64); +vector_type!(f32, 4, LittleEndian::read_f32); +vector_type!(f64, 8, LittleEndian::read_f64); + +fn read_bool(buffer: &[u8]) -> bool { + buffer[0] == 1 +} + +fn read_u8(buffer: &[u8]) -> u8 { + buffer[0] +} +fn read_i8(buffer: &[u8]) -> i8 { + buffer[0] as i8 +} diff --git a/rust/src/lib.rs b/rust/src/lib.rs index a744595981..149c1d36a5 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -9,7 +9,7 @@ #![deny(unused_qualifications, missing_debug_implementations, trivial_casts, missing_copy_implementations, unused_import_braces, missing_docs)] - +#![feature(trace_macros)] extern crate byteorder; mod builder; @@ -17,11 +17,8 @@ mod types; mod table; mod iter; -#[macro_use] -pub mod macros; - pub use self::builder::Builder; -pub use self::types::{UOffsetT, VOffsetT, SOffsetT}; +pub use self::types::*; pub use self::table::*; pub use self::iter::*; diff --git a/rust/src/macros.rs b/rust/src/macros.rs index f274b7dd4d..f05460d5cf 100644 --- a/rust/src/macros.rs +++ b/rust/src/macros.rs @@ -44,7 +44,7 @@ macro_rules! table_get_fn { } }; (($name:ident, vector, $ty:ty, $slot:expr)) => { - pub fn $name(&self) -> flatbuffers::Iterator<$ty> { + pub fn $name<'a>(&self) -> flatbuffers::Iter<'a, $ty> { table_fn!(vector, self, $slot, $ty) } }; @@ -75,7 +75,7 @@ macro_rules! table_get_fn { #[macro_export] macro_rules! struct_get_fn { (($name:ident, get_struct, $ty:ty, $slot:expr)) => { - pub fn $name(&self) -> $ty { + pub fn $name(&self) -> $ty { struct_fn!(get_struct, self, $slot, $ty) } }; @@ -96,16 +96,16 @@ macro_rules! struct_get_fn { macro_rules! basic_struct_def { ($name:ident) => { #[derive(Debug)] - pub struct $name($crate::Table); + pub struct $name>($crate::Table); - impl $name { - pub fn new(table: $crate::Table) -> $name { + impl> $name { + pub fn new(table: $crate::Table) -> $name { $name ( table ) } } - impl From<$crate::Table> for $name { - fn from(table: $crate::Table) -> $name { + impl> From<$crate::Table> for $name { + fn from(table: $crate::Table) -> $name { $name(table) } } @@ -115,14 +115,13 @@ macro_rules! basic_struct_def { #[macro_export] macro_rules! table_object_trait { ($name:ident, $indirect:expr, $inline_size:expr) => { - impl $crate::TableObject for $name { - fn is_struct() -> bool { - $indirect - } - + impl> $crate::VectorType for $name { fn inline_size() -> usize { $inline_size } + fn read_next(buffer: &[u8]) -> $name { + $crate::Table::get_indirect_root(buffer, 0).into(); + } } } } @@ -132,7 +131,7 @@ macro_rules! table_object { ($name:ident, $inline_size:expr, [ $( $f:tt ),* ]) => { basic_struct_def!{$name} - impl $name { + impl $name { $( table_get_fn!{$f} )* } table_object_trait!{ $name, false, $inline_size } @@ -144,7 +143,7 @@ macro_rules! struct_object { ($name:ident, $inline_size:expr, [ $( $f:tt ),* ]) => { basic_struct_def!{$name} - impl $name { + impl $name { $( struct_get_fn!{$f} )* } table_object_trait!{ $name, true, $inline_size } @@ -187,7 +186,7 @@ macro_rules! union { } impl $name { - pub fn new(table: $crate::Table, utype: Option<$type_name>) -> Option<$name> { + pub fn new(table: $crate::Table, utype: Option<$type_name>) -> Option<$name> { match utype { $( Some($type_name::$e_name) => Some( $name::$e_name( table.into() ) ), )* _ => None diff --git a/rust/src/new_macros.rs b/rust/src/new_macros.rs new file mode 100644 index 0000000000..ad621604b3 --- /dev/null +++ b/rust/src/new_macros.rs @@ -0,0 +1,285 @@ +//! Macro for defining flatbuffer Tables, Structs, Enums and Unions. +//! +//! The `flatbuffers_object!` macro is used to create the necessary +//! biolerplate for using flatbuffers. The recommended use is to +//! generate these macros using the `flatc --rust` command. + +//! # Example Enums +//! +//! +use types::*; + +#[macro_export] +macro_rules! flatbuffers_object { + // Table slot accessor functions + (@table_accessor $i:ident [$ty:ty] $slot:expr,) => { + ($i.0).get_slot_vector::<$ty>($slot) + }; + (@table_accessor $i:ident &str $slot:expr,) => { + ($i.0).get_slot_str($slot) + }; + // enum + (@table_accessor $i:ident $ty:ident($si:ident) $slot:expr, $default:expr) => { + let v = flatbuffers_object!(@table_accessor $i $si $slot, $default); + $ty::from(v) + }; + // Union + (@table_accessor $i:ident Union($ty:ident = $fi:ident) $slot:expr, $default:expr) => { + let ty = $i.$fi(); + let table = ($i.0).get_slot_table($slot) + $ty::new(table, ty) + }; + (@table_accessor $i:ident u8 $slot:expr, $default:expr) => { + ($i.0).get_slot_u8($slot, $default) + }; + (@table_accessor $i:ident i8 $slot:expr, $default:expr) => { + ($i.0).get_slot_i8($slot, $default) + }; + (@table_accessor $i:ident u16 $slot:expr, $default:expr) => { + ($i.0).get_slot_u16($slot, $default) + }; + (@table_accessor $i:ident i16 $slot:expr, $default:expr) => { + ($i.0).get_slot_i16($slot, $default) + }; + (@table_accessor $i:ident u32 $slot:expr, $default:expr) => { + ($i.0).get_slot_u32($slot, $default) + }; + (@table_accessor $i:ident i32 $slot:expr, $default:expr) => { + ($i.0).get_slot_i32($slot, $default) + }; + (@table_accessor $i:ident u64 $slot:expr, $default:expr) => { + ($i.0).get_slot_u64($slot, $default) + }; + (@table_accessor $i:ident i64 $slot:expr, $default:expr) => { + ($i.0).get_slot_i64($slot, $default) + }; + (@table_accessor $i:ident f32 $slot:expr, $default:expr) => { + ($i.0).get_slot_f32($slot, $default) + }; + (@table_accessor $i:ident f64 $slot:expr, $default:expr) => { + ($i.0).get_slot_f64($slot, $default) + }; + (@table_accessor $i:ident bool $slot:expr, $default:expr) => { + ($i.0).get_slot_bool($slot, $default) + }; + (@table_accessor $i:ident $ty:ident $slot:expr,) => { + ($i.0).get_slot_struct($slot) + }; + // Struct slot accessor functions + (@table_accessor $i:ident &str $slot:expr,) => { + ($i.0).get_str($slot) + }; + (@struct_accessor $i:ident u8 $slot:expr) => { + ($i.0).get_u8($slot) + }; + (@struct_accessor $i:ident i8) $slot:expr => { + ($i.0).get_i8($slot) + }; + (@struct_accessor $i:ident u16 $slot:expr) => { + ($i.0).get_u16($slot) + }; + (@struct_accessor $i:ident i16 $slot:expr) => { + ($i.0).get_i16($slot) + }; + (@struct_accessor $i:ident u32 $slot:expr) => { + ($i.0).get_u32($slot) + }; + (@struct_accessor $i:ident i32 $slot:expr) => { + ($i.0).get_i32($slot) + }; + (@struct_accessor $i:ident u64 $slot:expr) => { + ($i.0).get_u64($slot) + }; + (@struct_accessor $i:ident i64 $slot:expr) => { + ($i.0).get_i64($slot) + }; + (@struct_accessor $i:ident f32 $slot:expr) => { + ($i.0).get_f32($slot) + }; + (@struct_accessor $i:ident f64 $slot:expr) => { + ($i.0).get_f64($slot) + }; + (@struct_accessor $i:ident bool $slot:expr) => { + ($i.0).get_bool($slot) + }; + (@struct_accessor $i:ident $ty:tt $slot:expr,) => { + ($i.0).get_struct($slot) + }; + // enum + (@struct_accessor $i:ident $ty:ident($si:ident) $slot:expr, $default:expr) => { + let v = flatbuffers_object!(@table_accessor $i $si $slot, $default); + $ty::from(v) + }; + // For each @field build + // 1. table accessor functions, + // 2. builder trait definition, + // 3. builder functions + // and then recurse until no more fields. + // (@field { field { } }, ($($table:tt)*), ($($traits:tt)*), ($($builder:tt)*)) + // => { + // flatbuffers_object!{@field ($($table:tt)*), ($($traits:tt)*), ($($builder:tt)*)} + // }; + (@table_fun { }) => {}; + (@table_fun { field => }) => {}; + (@table_fun { field => { name = $name:ident, + typeOf = $ret_ty:ty, + slot = $slot:expr + $(, default = $default:expr)* + $(, comment = $comment:expr)*} + $(, field => $body:tt)* $(,)*}) => { + $( #[doc = $comment] )* + fn $name(&self) -> $ret_ty { + flatbuffers_object!(@table_accessor self $ret_ty $slot, $($default)*) + } + flatbuffers_object!(@table_fun { field => $($body)* }); + }; + (@struct_fun { }) => {}; + (@struct_fun { field => }) => {}; + (@struct_fun { field => { name = $name:ident, + typeOf = $ret_ty:ty, + slot = $slot:expr + $(, default = $default:expr)* + $(, comment = $comment:expr)*} + $(, field => $body:tt)* $(,)*}) => { + $( #[doc = $comment] )* + fn $name(&self) -> $ret_ty { + flatbuffers_object!(@struct_accessor self $ret_ty $slot) + } + flatbuffers_object!(@struct_fun { field => $($body)* }); + }; + (@from_table $name:ident) => { + impl> From<$crate::Table> for $name { + fn from(table: $crate::Table) -> $name { + $name(table) + } + } + } + (@vector_type $name:ident $size:expr) => { + impl> VectorType for $name { + fn inline_size() -> usize { + $size + } + + fn read_next(buffer: &[u8]) -> $name { + Table::get_indirect_root(buffer, 0).into(); + } + } + }; + // Table + ($name:ident => + $body:tt ) => { + + #[derive(Debug, Clone, PartialEq, Eq)] + pub struct $name>($crate::Table); + + impl> $name { + flatbuffers_object!(@table_fun $body); + } + + flatbuffers_object!(@from_table $name); + + flatbuffers_object!(@vector_type $name UOFFSETT_SIZE); + + }; + // Struct + ($name:ident => + fixed_size = $inline_size:expr, + $body:tt ) => { + + #[derive(Debug, Clone, PartialEq, Eq)] + pub struct $name>($crate::Table); + + impl> $name { + flatbuffers_object!(@struct_fun $body); + } + + flatbuffers_object!(@from_table $name); + + flatbuffers_object!(@vector_type $name $inline_size); + }; + // Simple Enum + ($name:ident => Enum {$( ($e_name:ident = $value:expr) ),+ } + as $repr:ty) => { + #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] + #[repr($repr)] + pub enum $name { + $( $e_name = $value ),+ + } + + impl $name { + pub fn from(value: $repr) -> Option<$name> { + match value { + $( $value => Some($name::$e_name) ),+, + _ => None + } + } + } + }; + // Union + ($name:ident => $ty:ident {$( ($e_name:ident = $value:expr) ),+ } + as $repr:ty) => { + #[derive(Debug)] + pub enum $name { + None, + $( $e_name( $ty ) ),+ + } + + impl $name { + pub fn new(table: $crate::Table, utype: Option<$type_name>) -> Option<$name> { + match utype { + $( Some($type_name::$e_name) => Some( $name::$e_name( table.into() ) ), )* + _ => None + } + } + } + + flatbuffers_object!($ty => Enum {$( ($e_name = $value) ),+ } as $repr); + } +} + +// use table::Table; + +// pub struct Vec3; + +// impl<'a> From> for Vec3 { +// fn from(table: Table) -> Vec3 { +// Vec3 +// } +// } + +// /// an example documentation comment: monster object +// flatbuffers_object!{Monster => +// { field => { name = pos, +// typeOf = Vec3, +// slot = 4, +// comment = "///Testing all my ways are dead\ntestomg"}, +// field => { name = mana, +// typeOf = i16, +// slot = 6, +// default = 150, +// comment = "///Testing all my ways are dead\ntestomg", +// comment = "///Testing all my ways are dead\ntestomg"}, +// field => { name = color, +// typeOf = Color(i8), +// slot = 6, +// default = 8, +// comment = "///Testing all my ways are dead\ntestomg", +// comment = "///Testing all my ways are dead\ntestomg"}, +// field => { name = test_type, +// typeOf = AnyType(u8), +// slot = 8, +// default = 0, +// comment = "///Testing all my ways are dead\ntestomg", +// comment = "///Testing all my ways are dead\ntestomg"}, +// field => { name = test, +// typeOf = Union(Any = test_type), +// slot = 10, +// default = 0, +// comment = "///Testing all my ways are dead\ntestomg", +// comment = "///Testing all my ways are dead\ntestomg"}, +// } +// } + +// flatbuffers_object!{Color => Enum{ Red = 1, Blue = 2} as i8} + +// flatbuffers_object!{Any => AnyType{ } as u8} diff --git a/rust/src/table.rs b/rust/src/table.rs index aa441520b6..298cd496e8 100644 --- a/rust/src/table.rs +++ b/rust/src/table.rs @@ -1,26 +1,17 @@ -use std::rc::Rc; +use std::{ops, str}; use byteorder::{ByteOrder, LittleEndian}; use types::*; -use iter::Iterator; - -/// A trait for Structs and Tables to implement. -pub trait TableObject: From
{ - /// Table Objects require indirection. Structs do not. - fn is_struct() -> bool; - /// The size of the object in the vector. - fn inline_size() -> usize; -} - +use iter::{Iter, VectorType}; -/// Table provides functions to read Flatbuffer data. +/// Table provides functions to read Flatbuffer data. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct Table { - buffer: Rc>, +pub struct Table> { + inner: T, pos: usize, } -impl Table { +impl> Table { /// Create a table using from a slice using data starting at `pos`. /// First `UOffsetT` should indicate the offset from the root /// of the table to the begining of the object. @@ -34,17 +25,17 @@ impl Table { /// 7, 0, // start of value 0 /// 6, 0, // start of value 1 /// 5, 0, // start of value 2 - /// 10, 0, 0, 0, // start of object..ie. vtable offset + /// 10, 0, 0, 0, // start of object..ie. vtable offset /// 0, // padding /// 77, // value 2 /// 66, // value 1 /// 55, // value 0 /// ``` - pub fn from_offset(buffer: Rc>, pos: usize) -> Table { - let n = read_uoffset(&buffer, pos); - Table { - buffer: buffer, - pos: n as usize + pos + pub fn get_indirect_root(buffer: T, pos: usize) -> Table { + let offset = Table::::read_uoffset(&buffer.as_ref()[pos..]) as usize; + Table { + inner: buffer, + pos: offset + pos, } } @@ -67,53 +58,40 @@ impl Table { /// 66, // value 1 /// 55, // value 0 /// ``` - pub fn with_pos(buffer: Rc>, pos: usize) -> Table { + pub fn get_root(buffer: T, pos: usize) -> Table { Table { - buffer: buffer, - pos: pos + inner: buffer, + pos: pos, } } - /// Return an object table at offset. - /// See `from_offset`. - pub fn get_root(&self, offset: UOffsetT) -> Table { - Table::from_offset(self.buffer.clone(), self.pos + offset as usize) - } - - /// Return an object table at offset specified by offset. - pub fn get_indirect_root(&self, offset: UOffsetT) -> Table { - let actual_offset = self.pos as u32 + offset + self.get_u32(offset); - Table::with_pos(self.buffer.clone(), actual_offset as usize) - } - - // Returns a slice of table including the vtable. // - // First element of root table is Offset to vtable used + // First element of root table is the vtable offset // and is by default a negative direction. #[inline(always)] fn vtable(&self) -> &[u8] { - let vt_offset = read_soffset(&self.buffer, self.pos); + let vt_offset = Table::::read_soffset(&self[self.pos..]); let vtable = (self.pos as i32 - vt_offset) as usize; - &self.buffer[vtable..] + &self.as_bytes()[vtable..] } - + /// Returns the field offset or 0 if the field was not present. - pub fn field_offset(&self, field: VOffsetT) -> UOffsetT { + pub fn field_offset(&self, field: VOffsetT) -> VOffsetT { let vtable = self.vtable(); let vt_size = LittleEndian::read_u16(vtable); if field < vt_size { - return LittleEndian::read_u16(&vtable[field as usize..]) as u32 + return LittleEndian::read_u16(&vtable[field as usize..]); } 0 } /// Returns the `bool` value of the field at the offset written in the - /// vtable `slot`. + /// vtable `slot`. pub fn get_slot_bool(&self, slot: VOffsetT, default: bool) -> bool { let offset = self.field_offset(slot); if offset != 0 { - return self.get_bool(offset) + return self.get_bool(offset); } default } @@ -123,7 +101,7 @@ impl Table { pub fn get_slot_u8(&self, slot: VOffsetT, default: u8) -> u8 { let offset = self.field_offset(slot); if offset != 0 { - return self.get_u8(offset) + return self.get_u8(offset); } default } @@ -133,7 +111,7 @@ impl Table { pub fn get_slot_i8(&self, slot: VOffsetT, default: i8) -> i8 { let offset = self.field_offset(slot); if offset != 0 { - return self.get_i8(offset) + return self.get_i8(offset); } default } @@ -143,7 +121,7 @@ impl Table { pub fn get_slot_u16(&self, slot: VOffsetT, default: u16) -> u16 { let offset = self.field_offset(slot); if offset != 0 { - return self.get_u16(offset) + return self.get_u16(offset); } default } @@ -153,7 +131,7 @@ impl Table { pub fn get_slot_i16(&self, slot: VOffsetT, default: i16) -> i16 { let offset = self.field_offset(slot); if offset != 0 { - return self.get_i16(offset) + return self.get_i16(offset); } default } @@ -163,7 +141,7 @@ impl Table { pub fn get_slot_u32(&self, slot: VOffsetT, default: u32) -> u32 { let offset = self.field_offset(slot); if offset != 0 { - return self.get_u32(offset) + return self.get_u32(offset); } default } @@ -173,7 +151,7 @@ impl Table { pub fn get_slot_i32(&self, slot: VOffsetT, default: i32) -> i32 { let offset = self.field_offset(slot); if offset != 0 { - return self.get_i32(offset) + return self.get_i32(offset); } default } @@ -183,7 +161,7 @@ impl Table { pub fn get_slot_u64(&self, slot: VOffsetT, default: u64) -> u64 { let offset = self.field_offset(slot); if offset != 0 { - return self.get_u64(offset) + return self.get_u64(offset); } default } @@ -193,7 +171,7 @@ impl Table { pub fn get_slot_i64(&self, slot: VOffsetT, default: i64) -> i64 { let offset = self.field_offset(slot); if offset != 0 { - return self.get_i64(offset) + return self.get_i64(offset); } default } @@ -203,7 +181,7 @@ impl Table { pub fn get_slot_f32(&self, slot: VOffsetT, default: f32) -> f32 { let offset = self.field_offset(slot); if offset != 0 { - return self.get_f32(offset) + return self.get_f32(offset); } default } @@ -213,7 +191,7 @@ impl Table { pub fn get_slot_f64(&self, slot: VOffsetT, default: f64) -> f64 { let offset = self.field_offset(slot); if offset != 0 { - return self.get_f64(offset) + return self.get_f64(offset); } default } @@ -223,124 +201,146 @@ impl Table { pub fn get_slot_str(&self, slot: VOffsetT) -> &str { let offset = self.field_offset(slot); if offset != 0 { - return self.get_str(offset) + return self.get_str(offset); } "" } /// Returns the struct `T` value of the field at the offset written in the /// vtable `slot`. - pub fn get_slot_struct>(&self, slot: VOffsetT) -> Option { + pub fn get_slot_struct<'a, O>(&'a self, slot: VOffsetT) -> Option + where O: From> + AsRef<[u8]> + { let offset = self.field_offset(slot); if offset != 0 { - return Some(self.get_struct(offset)) + return Some(self.get_struct(offset)); } None } - /// Returns the unsigned byte vector value of the field at the offset written in the + /// Returns the a `Table` value of the field at the offset written in the /// vtable `slot`. - pub fn get_slot_vector(&self, slot: VOffsetT) -> Iterator { + pub fn get_slot_table(&self, slot: VOffsetT) -> Option> { let offset = self.field_offset(slot); if offset != 0 { - return self.get_vector::(offset) + return Some(self.get_table(offset)); + } + None + } + + + /// Returns the vector value of the field at the offset + /// written in the vtable `slot`. + pub fn get_slot_vector<'a, V>(&'a self, slot: VOffsetT) -> Iter + where V: VectorType<'a> + { + let offset = self.field_offset(slot); + if offset != 0 { + return self.get_vector::(offset); } Default::default() } - /// ByteVector gets an unsigned byte slice from data stored inside + /// Returns byte slice from data stored inside /// the flatbuffer. - pub fn get_vector(&self, offset: UOffsetT) -> Iterator { + pub fn get_vector<'a, V>(&'a self, offset: VOffsetT) -> Iter + where V: VectorType<'a> + { let mut offset = offset as usize + self.pos; - offset += read_uoffset(&*self.buffer, offset) as usize; - let start = offset + UOFFSETT_SIZE; - let length = read_uoffset(&*self.buffer, offset) as usize; - Iterator::new(&self.buffer, start, length) + let length = Table::::read_uoffset(&self[offset..]) as usize; + offset += length; + let start = offset + UOFFSETT_SIZE; + Iter::new(&self.as_bytes(), start, length) } /// Returns a value of `bool` at `offset`. - pub fn get_bool(&self, offset: UOffsetT) -> bool { + pub fn get_bool(&self, offset: VOffsetT) -> bool { let pos = self.pos as usize; - self.buffer[pos + offset as usize] == 1 + self.as_bytes()[pos + offset as usize] == 1 } /// Returns a value of `u8` at `offset`. - pub fn get_u8(&self, offset: UOffsetT) -> u8 { + pub fn get_u8(&self, offset: VOffsetT) -> u8 { let pos = self.pos as usize; - self.buffer[pos + offset as usize] + self.as_bytes()[pos + offset as usize] } /// Returns a value of `i8` at `offset`. - pub fn get_i8(&self, offset: UOffsetT) -> i8 { + pub fn get_i8(&self, offset: VOffsetT) -> i8 { let pos = self.pos as usize; - self.buffer[pos + offset as usize] as i8 + self.as_bytes()[pos + offset as usize] as i8 } /// Returns a value of `u16` at `offset`. - pub fn get_u16(&self, offset: UOffsetT) -> u16 { + pub fn get_u16(&self, offset: VOffsetT) -> u16 { let pos = self.pos as usize; - LittleEndian::read_u16(&self.buffer[pos + offset as usize..]) + LittleEndian::read_u16(&self[pos + offset as usize..]) } /// Returns a value of `i16` at `offset`. - pub fn get_i16(&self, offset: UOffsetT) -> i16 { + pub fn get_i16(&self, offset: VOffsetT) -> i16 { let pos = self.pos as usize; - LittleEndian::read_i16(&self.buffer[pos + offset as usize..]) + LittleEndian::read_i16(&self[pos + offset as usize..]) } /// Returns a value of `u32` at `offset`. - pub fn get_u32(&self, offset: UOffsetT) -> u32 { + pub fn get_u32(&self, offset: VOffsetT) -> u32 { let pos = self.pos as usize; - LittleEndian::read_u32(&self.buffer[pos + offset as usize..]) + LittleEndian::read_u32(&self[pos + offset as usize..]) } /// Returns a value of `i32` at `offset`. - pub fn get_i32(&self, offset: UOffsetT) -> i32 { + pub fn get_i32(&self, offset: VOffsetT) -> i32 { let pos = self.pos as usize; - LittleEndian::read_i32(&self.buffer[pos + offset as usize..]) + LittleEndian::read_i32(&self[pos + offset as usize..]) } /// Returns a value of `u64` at `offset`. - pub fn get_u64(&self, offset: UOffsetT) -> u64 { + pub fn get_u64(&self, offset: VOffsetT) -> u64 { let pos = self.pos as usize; - LittleEndian::read_u64(&self.buffer[pos + offset as usize..]) + LittleEndian::read_u64(&self[pos + offset as usize..]) } /// Returns a value of `i64` at `offset`. - pub fn get_i64(&self, offset: UOffsetT) -> i64 { + pub fn get_i64(&self, offset: VOffsetT) -> i64 { let pos = self.pos as usize; - LittleEndian::read_i64(&self.buffer[pos + offset as usize..]) + LittleEndian::read_i64(&self[pos + offset as usize..]) } /// Returns a value of `f32` at `offset`. - pub fn get_f32(&self, offset: UOffsetT) -> f32 { + pub fn get_f32(&self, offset: VOffsetT) -> f32 { let pos = self.pos as usize; - LittleEndian::read_f32(&self.buffer[pos + offset as usize..]) + LittleEndian::read_f32(&self[pos + offset as usize..]) } /// Returns a value of `f64` at `offset`. - pub fn get_f64(&self, offset: UOffsetT) -> f64 { + pub fn get_f64(&self, offset: VOffsetT) -> f64 { let pos = self.pos as usize; - LittleEndian::read_f64(&self.buffer[pos + offset as usize..]) + LittleEndian::read_f64(&self[pos + offset as usize..]) } /// Returns a value of `&str` at `offset`. - pub fn get_str(&self, offset: UOffsetT) -> &str { - use std::str; - let mut offset = offset + self.pos as UOffsetT; - offset += read_uoffset(&*self.buffer, offset as usize); - let start = offset as usize + 4 as usize; - let length = read_uoffset(&*self.buffer, offset as usize) as usize; - let s = &self.buffer[start..start+length]; - unsafe { str::from_utf8_unchecked(s) } + pub fn get_str(&self, offset: VOffsetT) -> &str { + let offset = offset as usize + self.pos; + Table::::read_str(&self[offset..]) + } + + /// Retrieve a struct table from offset. Offset should point to the + /// first usable byte of data i.e. the Vtable offset or start + /// of struct + pub fn get_struct<'a, O>(&'a self, offset: VOffsetT) -> O + where O: From> + { + let table = self.get_table(offset); + table.into() } - /// Retrieve a struct table from offset. Offset should point to then - /// first usable byte of data i.e. the Vtable offset. - pub fn get_struct>(&self, offset: UOffsetT) -> T { - let pos = self.pos as UOffsetT + offset; - let table = Table::with_pos(self.buffer.clone(), pos as usize); - table.into() + /// Retrieve a `Table` from offset. Offset should point to the + /// first usable byte of data i.e. the Vtable offset or start + /// of struct + pub fn get_table(&self, offset: VOffsetT) -> Table<&[u8]> { + let pos = self.pos as usize + offset as usize; + Table::get_root(self.inner.as_ref(), pos as usize) } /// Accesor function for the tables position in the buffer. @@ -350,49 +350,75 @@ impl Table { } /// Reads an `UOffsetT` at exact position. - pub fn read_uoffset(&self, offset: UOffsetT) -> UOffsetT { - read_uoffset(&*self.buffer, offset as usize) + pub fn get_uoffset(&self, pos: usize) -> UOffsetT { + Table::::read_uoffset(&self[pos..]) } /// Reads an `VOffsetT` at exact position. - pub fn read_voffset(&self, offset: UOffsetT) -> VOffsetT { - read_voffset(&*self.buffer, offset as usize) + pub fn get_voffset(&self, pos: usize) -> VOffsetT { + Table::::read_voffset(&self[pos..]) } - /// Retrieves the `VOffsetT` in the vtable `slot`. - /// If the vtable value is zero, the default value `d` will be returned. - pub fn read_voffset_slot(&self, slot: VOffsetT, d: VOffsetT) -> VOffsetT { - let offset = self.field_offset(slot); - if offset != 0 { - return offset as VOffsetT - } - d + /// Read a Signed offset value at given pos. + pub fn get_soffset(&self, pos: usize) -> SOffsetT { + Table::::read_soffset(&self[pos..]) } - /// Get a reference to the raw buffer + /// Get a reference to the raw buffer. #[inline] - pub fn get_bytes(&self) -> &[u8] { - &*self.buffer + pub fn as_bytes(&self) -> &[u8] { + self.inner.as_ref() + } + + /// Return the backing buffer. + pub fn into_inner(self) -> T { + self.inner } -} -/// Read a Unsigned offset value at given offset -pub fn read_uoffset(buf: &[u8], offset: usize) -> UOffsetT { - LittleEndian::read_u32(&buf[offset as usize..]) + /// Read a string starting at the beginning of the buffer. + pub fn read_str(buffer: &[u8]) -> &str { + let offset = Table::::read_uoffset(buffer) as usize; + let start = offset + UOFFSETT_SIZE; + let length = Table::::read_uoffset(&buffer[offset..]) as usize; + let s = &buffer[start..start + length]; + unsafe { str::from_utf8_unchecked(s) } + } + + /// Read a `UOffsetT` starting at the beginning of the buffer. + pub fn read_uoffset(buffer: &[u8]) -> UOffsetT { + LittleEndian::read_u32(buffer) + } + + /// Read a `VOffsetT` starting at the beginning of the buffer. + pub fn read_voffset(buffer: &[u8]) -> VOffsetT { + LittleEndian::read_u16(buffer) + } + + /// Read a `SOffsetT` starting at the beginning of the buffer. + pub fn read_soffset(buffer: &[u8]) -> SOffsetT { + LittleEndian::read_i32(buffer) + } } -/// Read a Signed offset value at given offset -pub fn read_soffset(buf: &[u8], offset: usize) -> SOffsetT { - LittleEndian::read_i32(&buf[offset as usize..]) +impl From> for Table> { + fn from(buf: Vec) -> Table> { + Table { + inner: buf, + pos: 0, + } + } } -/// Read a Signed offset value at given offset -pub fn read_voffset(buf: &[u8], offset: usize) -> VOffsetT { - LittleEndian::read_u16(&buf[offset as usize..]) +impl> ops::Deref for Table { + type Target = [u8]; + + fn deref(&self) -> &[u8] { + self.inner.as_ref() + } } -impl From>> for Table { - fn from(buf: Rc>,) -> Table { - Table::from_offset(buf, 0) +impl ops::DerefMut for Table> { + fn deref_mut<'a>(&'a mut self) -> &'a mut [u8] { + &mut self.inner } } diff --git a/samples/rust/Cargo.toml b/samples/rust/Cargo.toml new file mode 100644 index 0000000000..0a88c980c8 --- /dev/null +++ b/samples/rust/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "rust" +version = "0.1.0" +authors = ["Joseph Dunne "] + +[dependencies] +flatbuffers = "*" diff --git a/samples/rust/src/main.rs b/samples/rust/src/main.rs new file mode 100644 index 0000000000..e7a11a969c --- /dev/null +++ b/samples/rust/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/src/idl_gen_rust.cpp b/src/idl_gen_rust.cpp index b300da58b9..f9bce63e0f 100644 --- a/src/idl_gen_rust.cpp +++ b/src/idl_gen_rust.cpp @@ -17,6 +17,7 @@ // independent from idl_parser, since this code is not needed for most clients #include +#include #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" @@ -36,6 +37,9 @@ static std::string TypeName(const FieldDef &field); // Hardcode spaces per indentation. const std::string Indent = " "; +const std::string TwoIndent = Indent + Indent; +const std::string ThreeIndent = Indent + Indent + Indent; + // Format a module name from struct/enum definitions. static std::string ModName(std::string &def_name) { @@ -71,13 +75,14 @@ static void TableStructDefinition(const StructDef &struct_def, std::string *code_ptr) { std::string &code = *code_ptr; if (!struct_def.fixed) { - code += "table_object!{" + struct_def.name; - code += ", 4"; //mmmm assuming type.base_type is UOFFSET + code += "flatbuffers_object!{Table => " + struct_def.name; } else { - code += "struct_object!{" + struct_def.name; - code += ", " + NumToString(struct_def.bytesize); + code += "flatbuffers_object!{Struct => " + struct_def.name; + code += " ( size:"; + code += NumToString(struct_def.bytesize) + ","; + code += " align: " + NumToString(struct_def.minalign) + ")"; } - code += ", ["; + code += " ["; bool first = true; for (auto it = struct_def.fields.vec.begin(); it != struct_def.fields.vec.end(); @@ -90,76 +95,106 @@ static void TableStructDefinition(const StructDef &struct_def, } else { code += ", \n"; } + code += " field => { "; //GenComment(field.doc_comment, code_ptr, nullptr, ""); if ( (IsScalar(field.value.type.base_type)) && !(field.value.type.enum_def)) { - code += Indent + "("; - code += field.name + ","; - code += "get_" + TypeName(field); - code += ", " + TypeName(field); - code += ", " + NumToString(field.value.offset); - code += ", " + MapConstant(field); - code += ")"; + code += "name = "; + code += field.name + ",\n"; + code += ThreeIndent +"typeOf = " + TypeName(field); + code += ",\n"; + code += ThreeIndent + "slot = " + NumToString(field.value.offset); + code += ",\n"; + code += ThreeIndent + "default = " + MapConstant(field); + if (field.padding) { + code += ",\n"; + code += ThreeIndent + "padding = " + NumToString(field.padding); + } + code += " }"; continue; } if ( (IsScalar(field.value.type.base_type)) && (field.value.type.enum_def) ) { - code += Indent + "("; - code += field.name + ","; - code += "simple_enum,"; - code += "get_" + TypeName(field); - code += ", " + TypeName(field); + code += "name = " + field.name; + code += ",\n"; + code += ThreeIndent +"typeOf = enum"; if (field.value.type.enum_def->is_union) { - code += ", " + field.value.type.enum_def->name; + code += " " + field.value.type.enum_def->name; code += "Type"; } else { - code += ", " + field.value.type.enum_def->name; + code += " " + field.value.type.enum_def->name; + } + code += " " + TypeName(field); + code += ",\n"; + code += ThreeIndent + "slot = " + NumToString(field.value.offset); + code += ",\n"; + code += ThreeIndent + "default = " + MapConstant(field); + if (field.padding) { + code += ",\n"; + code += ThreeIndent + "padding = " + NumToString(field.padding); } - code += ", " + NumToString(field.value.offset); - code += ", " + MapConstant(field); - code += ")"; + code += " }"; continue; } switch (field.value.type.base_type) { case BASE_TYPE_STRUCT: { - code += Indent + "("; - code += field.name + ","; - code += "get_struct"; - code += ", " + TypeName(field); - code += ", " + NumToString(field.value.offset); - code += ")"; + code += "name = "; + code += field.name + ",\n"; + code += ThreeIndent +"typeOf = "; + code += TypeName(field); + code += ",\n"; + code += ThreeIndent + "slot = " + NumToString(field.value.offset); + if (field.padding) { + code += ",\n"; + code += ThreeIndent + "padding = " + NumToString(field.padding); + } + code += " }"; break; } case BASE_TYPE_STRING: { - code += Indent + "("; - code += field.name + ","; - code += "get_str"; - code += ", " + TypeName(field); - code += ", " + NumToString(field.value.offset); - code += ", " + MapConstant(field); - code += ")"; + code += "name = "; + code += field.name + ",\n"; + code += ThreeIndent + "typeOf = string"; + code += ",\n"; + code += ThreeIndent + "slot = " + NumToString(field.value.offset); + code += ",\n"; + code += ThreeIndent + "default = " + MapConstant(field); + if (field.padding) { + code += ",\n"; + code += ThreeIndent + "padding = " + NumToString(field.padding); + } + code += " }"; break; } case BASE_TYPE_VECTOR: { - code += Indent + "("; - code += field.name + ","; - code += "vector"; - code += ", " + TypeName(field); - code += ", " + NumToString(field.value.offset); - code += ")"; - break; + code += "name = "; + code += field.name + ",\n"; + code += ThreeIndent +"typeOf = "; + code += TypeName(field); + code += ",\n"; + code += ThreeIndent + "slot = "; + code += NumToString(field.value.offset); + if (field.padding) { + code += ",\n"; + code += ThreeIndent + "padding = " + NumToString(field.padding); + } + code += " }"; break; } case BASE_TYPE_UNION: - code += Indent + "("; - code += field.name + ","; - code += "union,"; - code += field.name + "_type"; - code += ", " + TypeName(field); - code += ", " + field.value.type.enum_def->name; - code += ", " + NumToString(field.value.offset); - code += ", " + MapConstant(field); - code += ")"; + code += "name = "; + code += field.name + ",\n"; + code += ThreeIndent +"typeOf = union "; + code += TypeName(field); + code += ",\n"; + code += ThreeIndent + "slot = " + NumToString(field.value.offset); + code += ",\n"; + code += ThreeIndent + "default = " + MapConstant(field); + if (field.padding) { + code += ",\n"; + code += ThreeIndent + "padding = " + NumToString(field.padding); + } + code += " }"; break; default: assert(0); @@ -439,8 +474,7 @@ static void GenTableBuilders(const StructDef &struct_def, static void GenStruct(const StructDef &struct_def, std::string *code_ptr) { if (struct_def.generated) return; - GenComment(struct_def.doc_comment, code_ptr, nullptr); - + GenComment(struct_def.doc_comment, code_ptr, nullptr); TableStructDefinition(struct_def, code_ptr); if (struct_def.fixed) { @@ -458,38 +492,30 @@ static void GenEnum(const EnumDef &enum_def, std::string *code_ptr) { std::string &code = *code_ptr; GenComment(enum_def.doc_comment, code_ptr, nullptr); if (enum_def.is_union) { - code += "union!{" + enum_def.name +","; - code += enum_def.name + "Type,"; + code += "flatbuffers_object!{Union =>" + enum_def.name; } else { - code += "simple_enum!{" + enum_def.name +","; + code += "flatbuffers_object!{Enum =>" + enum_def.name; } - code += GenTypeGet(enum_def.underlying_type); - code += ", ["; + code += "{ "; bool first = true; for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); ++it) { auto &ev = **it; //GenComment(ev.doc_comment, code_ptr, nullptr, Indent.c_str()); - if (ev.name.compare("NONE") == 0) { - continue; - } + // if (ev.name.compare("NONE") == 0) { + // continue; + // } if (first) { - code += "\n"; first = false; } else { - code += ", \n"; - } - if (enum_def.is_union) { - code += Indent + "(" + ev.name +", "+NumToString(ev.value); - code += ", " + ev.name; - code += ")"; - } - else { - code += Indent + "(" + ev.name +", "+NumToString(ev.value) +")"; + code += ", "; } + code += ev.name + " = "+ NumToString(ev.value); } - code += "]}\n\n"; + code += "} as "; + code += GenTypeGet(enum_def.underlying_type); + code += "}\n\n"; } @@ -598,12 +624,12 @@ static std::string GenTypeBasic(const Type &type) { static std::string GenTypePointer(const Type &type) { switch (type.base_type) { - case BASE_TYPE_STRING: - return "&str"; case BASE_TYPE_VECTOR: - return GenTypeGet(type.VectorType()); + return "[" + GenTypeGet(type.VectorType()) + "]"; case BASE_TYPE_STRUCT: return type.struct_def->name; + case BASE_TYPE_STRING: + return "string"; case BASE_TYPE_UNION: // fall through default: @@ -618,13 +644,14 @@ static std::string GenTypeGet(const Type &type) { } static std::string TypeName(const FieldDef &field) { - return GenTypeGet(field.value.type); + std::string ty = GenTypeGet(field.value.type); + ty.erase(remove( ty.begin(), ty.end(), '\"' ), ty.end()); + return ty; } // Create a struct with a builder and the struct's arguments. static void GenStructBuilder(const StructDef &struct_def, std::string *code_ptr) { - BeginBuilderTraitArgs(struct_def, code_ptr); StructBuilderArgs(struct_def, "", code_ptr); EndBuilderTraitArgs(struct_def, code_ptr); diff --git a/tests/MyGame/Example/Any.cs b/tests/MyGame/Example/Any.cs deleted file mode 100644 index a05a91851a..0000000000 --- a/tests/MyGame/Example/Any.cs +++ /dev/null @@ -1,14 +0,0 @@ -// automatically generated, do not modify - -namespace MyGame.Example -{ - -public enum Any : byte -{ - NONE = 0, - Monster = 1, - TestSimpleTableWithEnum = 2, -}; - - -} diff --git a/tests/MyGame/Example/Any.java b/tests/MyGame/Example/Any.java deleted file mode 100644 index cdc3ec5672..0000000000 --- a/tests/MyGame/Example/Any.java +++ /dev/null @@ -1,15 +0,0 @@ -// automatically generated, do not modify - -package MyGame.Example; - -public final class Any { - private Any() { } - public static final byte NONE = 0; - public static final byte Monster = 1; - public static final byte TestSimpleTableWithEnum = 2; - - private static final String[] names = { "NONE", "Monster", "TestSimpleTableWithEnum", }; - - public static String name(int e) { return names[e]; } -}; - diff --git a/tests/MyGame/Example/Any.php b/tests/MyGame/Example/Any.php deleted file mode 100644 index d35bfd6396..0000000000 --- a/tests/MyGame/Example/Any.php +++ /dev/null @@ -1,25 +0,0 @@ -Any{ NONE = 0, Monster = 1, TestSimpleTableWithEnum = 2 as u8} diff --git a/tests/MyGame/Example/Color.cs b/tests/MyGame/Example/Color.cs deleted file mode 100644 index 7843733e38..0000000000 --- a/tests/MyGame/Example/Color.cs +++ /dev/null @@ -1,14 +0,0 @@ -// automatically generated, do not modify - -namespace MyGame.Example -{ - -public enum Color : sbyte -{ - Red = 1, - Green = 2, - Blue = 8, -}; - - -} diff --git a/tests/MyGame/Example/Color.java b/tests/MyGame/Example/Color.java deleted file mode 100644 index 822d2bbfe6..0000000000 --- a/tests/MyGame/Example/Color.java +++ /dev/null @@ -1,15 +0,0 @@ -// automatically generated, do not modify - -package MyGame.Example; - -public final class Color { - private Color() { } - public static final byte Red = 1; - public static final byte Green = 2; - public static final byte Blue = 8; - - private static final String[] names = { "Red", "Green", "", "", "", "", "", "Blue", }; - - public static String name(int e) { return names[e - Red]; } -}; - diff --git a/tests/MyGame/Example/Color.php b/tests/MyGame/Example/Color.php deleted file mode 100644 index 9de0e68f99..0000000000 --- a/tests/MyGame/Example/Color.php +++ /dev/null @@ -1,25 +0,0 @@ -Color{ Red = 1, Green = 2, Blue = 8 as i8} diff --git a/tests/MyGame/Example/Monster.cs b/tests/MyGame/Example/Monster.cs deleted file mode 100644 index abe95ec844..0000000000 --- a/tests/MyGame/Example/Monster.cs +++ /dev/null @@ -1,130 +0,0 @@ -// automatically generated, do not modify - -namespace MyGame.Example -{ - -using System; -using FlatBuffers; - -/// an example documentation comment: monster object -public sealed class Monster : Table { - public static Monster GetRootAsMonster(ByteBuffer _bb) { return GetRootAsMonster(_bb, new Monster()); } - public static Monster GetRootAsMonster(ByteBuffer _bb, Monster obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } - public static bool MonsterBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "MONS"); } - public Monster __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } - - public Vec3 Pos { get { return GetPos(new Vec3()); } } - public Vec3 GetPos(Vec3 obj) { int o = __offset(4); return o != 0 ? obj.__init(o + bb_pos, bb) : null; } - public short Mana { get { int o = __offset(6); return o != 0 ? bb.GetShort(o + bb_pos) : (short)150; } } - public bool MutateMana(short mana) { int o = __offset(6); if (o != 0) { bb.PutShort(o + bb_pos, mana); return true; } else { return false; } } - public short Hp { get { int o = __offset(8); return o != 0 ? bb.GetShort(o + bb_pos) : (short)100; } } - public bool MutateHp(short hp) { int o = __offset(8); if (o != 0) { bb.PutShort(o + bb_pos, hp); return true; } else { return false; } } - public string Name { get { int o = __offset(10); return o != 0 ? __string(o + bb_pos) : null; } } - public ArraySegment? GetNameBytes() { return __vector_as_arraysegment(10); } - public byte GetInventory(int j) { int o = __offset(14); return o != 0 ? bb.Get(__vector(o) + j * 1) : (byte)0; } - public int InventoryLength { get { int o = __offset(14); return o != 0 ? __vector_len(o) : 0; } } - public ArraySegment? GetInventoryBytes() { return __vector_as_arraysegment(14); } - public bool MutateInventory(int j, byte inventory) { int o = __offset(14); if (o != 0) { bb.Put(__vector(o) + j * 1, inventory); return true; } else { return false; } } - public Color Color { get { int o = __offset(16); return o != 0 ? (Color)bb.GetSbyte(o + bb_pos) : Color.Blue; } } - public bool MutateColor(Color color) { int o = __offset(16); if (o != 0) { bb.PutSbyte(o + bb_pos, (sbyte)color); return true; } else { return false; } } - public Any TestType { get { int o = __offset(18); return o != 0 ? (Any)bb.Get(o + bb_pos) : Any.NONE; } } - public bool MutateTestType(Any test_type) { int o = __offset(18); if (o != 0) { bb.Put(o + bb_pos, (byte)test_type); return true; } else { return false; } } - public TTable GetTest(TTable obj) where TTable : Table { int o = __offset(20); return o != 0 ? __union(obj, o) : null; } - public Test GetTest4(int j) { return GetTest4(new Test(), j); } - public Test GetTest4(Test obj, int j) { int o = __offset(22); return o != 0 ? obj.__init(__vector(o) + j * 4, bb) : null; } - public int Test4Length { get { int o = __offset(22); return o != 0 ? __vector_len(o) : 0; } } - public string GetTestarrayofstring(int j) { int o = __offset(24); return o != 0 ? __string(__vector(o) + j * 4) : null; } - public int TestarrayofstringLength { get { int o = __offset(24); return o != 0 ? __vector_len(o) : 0; } } - /// an example documentation comment: this will end up in the generated code - /// multiline too - public Monster GetTestarrayoftables(int j) { return GetTestarrayoftables(new Monster(), j); } - public Monster GetTestarrayoftables(Monster obj, int j) { int o = __offset(26); return o != 0 ? obj.__init(__indirect(__vector(o) + j * 4), bb) : null; } - public int TestarrayoftablesLength { get { int o = __offset(26); return o != 0 ? __vector_len(o) : 0; } } - public Monster Enemy { get { return GetEnemy(new Monster()); } } - public Monster GetEnemy(Monster obj) { int o = __offset(28); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; } - public byte GetTestnestedflatbuffer(int j) { int o = __offset(30); return o != 0 ? bb.Get(__vector(o) + j * 1) : (byte)0; } - public int TestnestedflatbufferLength { get { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; } } - public ArraySegment? GetTestnestedflatbufferBytes() { return __vector_as_arraysegment(30); } - public Monster TestnestedflatbufferAsMonster() { return GetTestnestedflatbufferAsMonster(new Monster()); } - public Monster GetTestnestedflatbufferAsMonster(Monster obj) { int o = __offset(30); return o != 0 ? obj.__init(__indirect(__vector(o)), bb) : null; } - public bool MutateTestnestedflatbuffer(int j, byte testnestedflatbuffer) { int o = __offset(30); if (o != 0) { bb.Put(__vector(o) + j * 1, testnestedflatbuffer); return true; } else { return false; } } - public Stat Testempty { get { return GetTestempty(new Stat()); } } - public Stat GetTestempty(Stat obj) { int o = __offset(32); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; } - public bool Testbool { get { int o = __offset(34); return o != 0 ? 0!=bb.Get(o + bb_pos) : (bool)false; } } - public bool MutateTestbool(bool testbool) { int o = __offset(34); if (o != 0) { bb.Put(o + bb_pos, (byte)(testbool ? 1 : 0)); return true; } else { return false; } } - public int Testhashs32Fnv1 { get { int o = __offset(36); return o != 0 ? bb.GetInt(o + bb_pos) : (int)0; } } - public bool MutateTesthashs32Fnv1(int testhashs32_fnv1) { int o = __offset(36); if (o != 0) { bb.PutInt(o + bb_pos, testhashs32_fnv1); return true; } else { return false; } } - public uint Testhashu32Fnv1 { get { int o = __offset(38); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } - public bool MutateTesthashu32Fnv1(uint testhashu32_fnv1) { int o = __offset(38); if (o != 0) { bb.PutUint(o + bb_pos, testhashu32_fnv1); return true; } else { return false; } } - public long Testhashs64Fnv1 { get { int o = __offset(40); return o != 0 ? bb.GetLong(o + bb_pos) : (long)0; } } - public bool MutateTesthashs64Fnv1(long testhashs64_fnv1) { int o = __offset(40); if (o != 0) { bb.PutLong(o + bb_pos, testhashs64_fnv1); return true; } else { return false; } } - public ulong Testhashu64Fnv1 { get { int o = __offset(42); return o != 0 ? bb.GetUlong(o + bb_pos) : (ulong)0; } } - public bool MutateTesthashu64Fnv1(ulong testhashu64_fnv1) { int o = __offset(42); if (o != 0) { bb.PutUlong(o + bb_pos, testhashu64_fnv1); return true; } else { return false; } } - public int Testhashs32Fnv1a { get { int o = __offset(44); return o != 0 ? bb.GetInt(o + bb_pos) : (int)0; } } - public bool MutateTesthashs32Fnv1a(int testhashs32_fnv1a) { int o = __offset(44); if (o != 0) { bb.PutInt(o + bb_pos, testhashs32_fnv1a); return true; } else { return false; } } - public uint Testhashu32Fnv1a { get { int o = __offset(46); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } } - public bool MutateTesthashu32Fnv1a(uint testhashu32_fnv1a) { int o = __offset(46); if (o != 0) { bb.PutUint(o + bb_pos, testhashu32_fnv1a); return true; } else { return false; } } - public long Testhashs64Fnv1a { get { int o = __offset(48); return o != 0 ? bb.GetLong(o + bb_pos) : (long)0; } } - public bool MutateTesthashs64Fnv1a(long testhashs64_fnv1a) { int o = __offset(48); if (o != 0) { bb.PutLong(o + bb_pos, testhashs64_fnv1a); return true; } else { return false; } } - public ulong Testhashu64Fnv1a { get { int o = __offset(50); return o != 0 ? bb.GetUlong(o + bb_pos) : (ulong)0; } } - public bool MutateTesthashu64Fnv1a(ulong testhashu64_fnv1a) { int o = __offset(50); if (o != 0) { bb.PutUlong(o + bb_pos, testhashu64_fnv1a); return true; } else { return false; } } - public bool GetTestarrayofbools(int j) { int o = __offset(52); return o != 0 ? 0!=bb.Get(__vector(o) + j * 1) : false; } - public int TestarrayofboolsLength { get { int o = __offset(52); return o != 0 ? __vector_len(o) : 0; } } - public ArraySegment? GetTestarrayofboolsBytes() { return __vector_as_arraysegment(52); } - public bool MutateTestarrayofbools(int j, bool testarrayofbools) { int o = __offset(52); if (o != 0) { bb.Put(__vector(o) + j * 1, (byte)(testarrayofbools ? 1 : 0)); return true; } else { return false; } } - public float Testf { get { int o = __offset(54); return o != 0 ? bb.GetFloat(o + bb_pos) : (float)3.14159f; } } - public bool MutateTestf(float testf) { int o = __offset(54); if (o != 0) { bb.PutFloat(o + bb_pos, testf); return true; } else { return false; } } - public float Testf2 { get { int o = __offset(56); return o != 0 ? bb.GetFloat(o + bb_pos) : (float)3.0f; } } - public bool MutateTestf2(float testf2) { int o = __offset(56); if (o != 0) { bb.PutFloat(o + bb_pos, testf2); return true; } else { return false; } } - public float Testf3 { get { int o = __offset(58); return o != 0 ? bb.GetFloat(o + bb_pos) : (float)0.0f; } } - public bool MutateTestf3(float testf3) { int o = __offset(58); if (o != 0) { bb.PutFloat(o + bb_pos, testf3); return true; } else { return false; } } - - public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(28); } - public static void AddPos(FlatBufferBuilder builder, Offset posOffset) { builder.AddStruct(0, posOffset.Value, 0); } - public static void AddMana(FlatBufferBuilder builder, short mana) { builder.AddShort(1, mana, 150); } - public static void AddHp(FlatBufferBuilder builder, short hp) { builder.AddShort(2, hp, 100); } - public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(3, nameOffset.Value, 0); } - public static void AddInventory(FlatBufferBuilder builder, VectorOffset inventoryOffset) { builder.AddOffset(5, inventoryOffset.Value, 0); } - public static VectorOffset CreateInventoryVector(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddByte(data[i]); return builder.EndVector(); } - public static void StartInventoryVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } - public static void AddColor(FlatBufferBuilder builder, Color color) { builder.AddSbyte(6, (sbyte)color, 8); } - public static void AddTestType(FlatBufferBuilder builder, Any testType) { builder.AddByte(7, (byte)testType, 0); } - public static void AddTest(FlatBufferBuilder builder, int testOffset) { builder.AddOffset(8, testOffset, 0); } - public static void AddTest4(FlatBufferBuilder builder, VectorOffset test4Offset) { builder.AddOffset(9, test4Offset.Value, 0); } - public static void StartTest4Vector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 2); } - public static void AddTestarrayofstring(FlatBufferBuilder builder, VectorOffset testarrayofstringOffset) { builder.AddOffset(10, testarrayofstringOffset.Value, 0); } - public static VectorOffset CreateTestarrayofstringVector(FlatBufferBuilder builder, StringOffset[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); } - public static void StartTestarrayofstringVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } - public static void AddTestarrayoftables(FlatBufferBuilder builder, VectorOffset testarrayoftablesOffset) { builder.AddOffset(11, testarrayoftablesOffset.Value, 0); } - public static VectorOffset CreateTestarrayoftablesVector(FlatBufferBuilder builder, Offset[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); } - public static void StartTestarrayoftablesVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); } - public static void AddEnemy(FlatBufferBuilder builder, Offset enemyOffset) { builder.AddOffset(12, enemyOffset.Value, 0); } - public static void AddTestnestedflatbuffer(FlatBufferBuilder builder, VectorOffset testnestedflatbufferOffset) { builder.AddOffset(13, testnestedflatbufferOffset.Value, 0); } - public static VectorOffset CreateTestnestedflatbufferVector(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddByte(data[i]); return builder.EndVector(); } - public static void StartTestnestedflatbufferVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } - public static void AddTestempty(FlatBufferBuilder builder, Offset testemptyOffset) { builder.AddOffset(14, testemptyOffset.Value, 0); } - public static void AddTestbool(FlatBufferBuilder builder, bool testbool) { builder.AddBool(15, testbool, false); } - public static void AddTesthashs32Fnv1(FlatBufferBuilder builder, int testhashs32Fnv1) { builder.AddInt(16, testhashs32Fnv1, 0); } - public static void AddTesthashu32Fnv1(FlatBufferBuilder builder, uint testhashu32Fnv1) { builder.AddUint(17, testhashu32Fnv1, 0); } - public static void AddTesthashs64Fnv1(FlatBufferBuilder builder, long testhashs64Fnv1) { builder.AddLong(18, testhashs64Fnv1, 0); } - public static void AddTesthashu64Fnv1(FlatBufferBuilder builder, ulong testhashu64Fnv1) { builder.AddUlong(19, testhashu64Fnv1, 0); } - public static void AddTesthashs32Fnv1a(FlatBufferBuilder builder, int testhashs32Fnv1a) { builder.AddInt(20, testhashs32Fnv1a, 0); } - public static void AddTesthashu32Fnv1a(FlatBufferBuilder builder, uint testhashu32Fnv1a) { builder.AddUint(21, testhashu32Fnv1a, 0); } - public static void AddTesthashs64Fnv1a(FlatBufferBuilder builder, long testhashs64Fnv1a) { builder.AddLong(22, testhashs64Fnv1a, 0); } - public static void AddTesthashu64Fnv1a(FlatBufferBuilder builder, ulong testhashu64Fnv1a) { builder.AddUlong(23, testhashu64Fnv1a, 0); } - public static void AddTestarrayofbools(FlatBufferBuilder builder, VectorOffset testarrayofboolsOffset) { builder.AddOffset(24, testarrayofboolsOffset.Value, 0); } - public static VectorOffset CreateTestarrayofboolsVector(FlatBufferBuilder builder, bool[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddBool(data[i]); return builder.EndVector(); } - public static void StartTestarrayofboolsVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); } - public static void AddTestf(FlatBufferBuilder builder, float testf) { builder.AddFloat(25, testf, 3.14159f); } - public static void AddTestf2(FlatBufferBuilder builder, float testf2) { builder.AddFloat(26, testf2, 3.0f); } - public static void AddTestf3(FlatBufferBuilder builder, float testf3) { builder.AddFloat(27, testf3, 0.0f); } - public static Offset EndMonster(FlatBufferBuilder builder) { - int o = builder.EndObject(); - builder.Required(o, 10); // name - return new Offset(o); - } - public static void FinishMonsterBuffer(FlatBufferBuilder builder, Offset offset) { builder.Finish(offset.Value, "MONS"); } -}; - - -} diff --git a/tests/MyGame/Example/Monster.java b/tests/MyGame/Example/Monster.java deleted file mode 100644 index 69c975436f..0000000000 --- a/tests/MyGame/Example/Monster.java +++ /dev/null @@ -1,134 +0,0 @@ -// automatically generated, do not modify - -package MyGame.Example; - -import java.nio.*; -import java.lang.*; -import java.util.*; -import com.google.flatbuffers.*; - -@SuppressWarnings("unused") -/** - * an example documentation comment: monster object - */ -public final class Monster extends Table { - public static Monster getRootAsMonster(ByteBuffer _bb) { return getRootAsMonster(_bb, new Monster()); } - public static Monster getRootAsMonster(ByteBuffer _bb, Monster obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public static boolean MonsterBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "MONS"); } - public Monster __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } - - public Vec3 pos() { return pos(new Vec3()); } - public Vec3 pos(Vec3 obj) { int o = __offset(4); return o != 0 ? obj.__init(o + bb_pos, bb) : null; } - public short mana() { int o = __offset(6); return o != 0 ? bb.getShort(o + bb_pos) : 150; } - public boolean mutateMana(short mana) { int o = __offset(6); if (o != 0) { bb.putShort(o + bb_pos, mana); return true; } else { return false; } } - public short hp() { int o = __offset(8); return o != 0 ? bb.getShort(o + bb_pos) : 100; } - public boolean mutateHp(short hp) { int o = __offset(8); if (o != 0) { bb.putShort(o + bb_pos, hp); return true; } else { return false; } } - public String name() { int o = __offset(10); return o != 0 ? __string(o + bb_pos) : null; } - public ByteBuffer nameAsByteBuffer() { return __vector_as_bytebuffer(10, 1); } - public int inventory(int j) { int o = __offset(14); return o != 0 ? bb.get(__vector(o) + j * 1) & 0xFF : 0; } - public int inventoryLength() { int o = __offset(14); return o != 0 ? __vector_len(o) : 0; } - public ByteBuffer inventoryAsByteBuffer() { return __vector_as_bytebuffer(14, 1); } - public boolean mutateInventory(int j, int inventory) { int o = __offset(14); if (o != 0) { bb.put(__vector(o) + j * 1, (byte)inventory); return true; } else { return false; } } - public byte color() { int o = __offset(16); return o != 0 ? bb.get(o + bb_pos) : 8; } - public boolean mutateColor(byte color) { int o = __offset(16); if (o != 0) { bb.put(o + bb_pos, color); return true; } else { return false; } } - public byte testType() { int o = __offset(18); return o != 0 ? bb.get(o + bb_pos) : 0; } - public boolean mutateTestType(byte test_type) { int o = __offset(18); if (o != 0) { bb.put(o + bb_pos, test_type); return true; } else { return false; } } - public Table test(Table obj) { int o = __offset(20); return o != 0 ? __union(obj, o) : null; } - public Test test4(int j) { return test4(new Test(), j); } - public Test test4(Test obj, int j) { int o = __offset(22); return o != 0 ? obj.__init(__vector(o) + j * 4, bb) : null; } - public int test4Length() { int o = __offset(22); return o != 0 ? __vector_len(o) : 0; } - public String testarrayofstring(int j) { int o = __offset(24); return o != 0 ? __string(__vector(o) + j * 4) : null; } - public int testarrayofstringLength() { int o = __offset(24); return o != 0 ? __vector_len(o) : 0; } - /** - * an example documentation comment: this will end up in the generated code - * multiline too - */ - public Monster testarrayoftables(int j) { return testarrayoftables(new Monster(), j); } - public Monster testarrayoftables(Monster obj, int j) { int o = __offset(26); return o != 0 ? obj.__init(__indirect(__vector(o) + j * 4), bb) : null; } - public int testarrayoftablesLength() { int o = __offset(26); return o != 0 ? __vector_len(o) : 0; } - public Monster enemy() { return enemy(new Monster()); } - public Monster enemy(Monster obj) { int o = __offset(28); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; } - public int testnestedflatbuffer(int j) { int o = __offset(30); return o != 0 ? bb.get(__vector(o) + j * 1) & 0xFF : 0; } - public int testnestedflatbufferLength() { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; } - public ByteBuffer testnestedflatbufferAsByteBuffer() { return __vector_as_bytebuffer(30, 1); } - public Monster testnestedflatbufferAsMonster() { return testnestedflatbufferAsMonster(new Monster()); } - public Monster testnestedflatbufferAsMonster(Monster obj) { int o = __offset(30); return o != 0 ? obj.__init(__indirect(__vector(o)), bb) : null; } - public boolean mutateTestnestedflatbuffer(int j, int testnestedflatbuffer) { int o = __offset(30); if (o != 0) { bb.put(__vector(o) + j * 1, (byte)testnestedflatbuffer); return true; } else { return false; } } - public Stat testempty() { return testempty(new Stat()); } - public Stat testempty(Stat obj) { int o = __offset(32); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; } - public boolean testbool() { int o = __offset(34); return o != 0 ? 0!=bb.get(o + bb_pos) : false; } - public boolean mutateTestbool(boolean testbool) { int o = __offset(34); if (o != 0) { bb.put(o + bb_pos, (byte)(testbool ? 1 : 0)); return true; } else { return false; } } - public int testhashs32Fnv1() { int o = __offset(36); return o != 0 ? bb.getInt(o + bb_pos) : 0; } - public boolean mutateTesthashs32Fnv1(int testhashs32_fnv1) { int o = __offset(36); if (o != 0) { bb.putInt(o + bb_pos, testhashs32_fnv1); return true; } else { return false; } } - public long testhashu32Fnv1() { int o = __offset(38); return o != 0 ? (long)bb.getInt(o + bb_pos) & 0xFFFFFFFFL : 0; } - public boolean mutateTesthashu32Fnv1(long testhashu32_fnv1) { int o = __offset(38); if (o != 0) { bb.putInt(o + bb_pos, (int)testhashu32_fnv1); return true; } else { return false; } } - public long testhashs64Fnv1() { int o = __offset(40); return o != 0 ? bb.getLong(o + bb_pos) : 0; } - public boolean mutateTesthashs64Fnv1(long testhashs64_fnv1) { int o = __offset(40); if (o != 0) { bb.putLong(o + bb_pos, testhashs64_fnv1); return true; } else { return false; } } - public long testhashu64Fnv1() { int o = __offset(42); return o != 0 ? bb.getLong(o + bb_pos) : 0; } - public boolean mutateTesthashu64Fnv1(long testhashu64_fnv1) { int o = __offset(42); if (o != 0) { bb.putLong(o + bb_pos, testhashu64_fnv1); return true; } else { return false; } } - public int testhashs32Fnv1a() { int o = __offset(44); return o != 0 ? bb.getInt(o + bb_pos) : 0; } - public boolean mutateTesthashs32Fnv1a(int testhashs32_fnv1a) { int o = __offset(44); if (o != 0) { bb.putInt(o + bb_pos, testhashs32_fnv1a); return true; } else { return false; } } - public long testhashu32Fnv1a() { int o = __offset(46); return o != 0 ? (long)bb.getInt(o + bb_pos) & 0xFFFFFFFFL : 0; } - public boolean mutateTesthashu32Fnv1a(long testhashu32_fnv1a) { int o = __offset(46); if (o != 0) { bb.putInt(o + bb_pos, (int)testhashu32_fnv1a); return true; } else { return false; } } - public long testhashs64Fnv1a() { int o = __offset(48); return o != 0 ? bb.getLong(o + bb_pos) : 0; } - public boolean mutateTesthashs64Fnv1a(long testhashs64_fnv1a) { int o = __offset(48); if (o != 0) { bb.putLong(o + bb_pos, testhashs64_fnv1a); return true; } else { return false; } } - public long testhashu64Fnv1a() { int o = __offset(50); return o != 0 ? bb.getLong(o + bb_pos) : 0; } - public boolean mutateTesthashu64Fnv1a(long testhashu64_fnv1a) { int o = __offset(50); if (o != 0) { bb.putLong(o + bb_pos, testhashu64_fnv1a); return true; } else { return false; } } - public boolean testarrayofbools(int j) { int o = __offset(52); return o != 0 ? 0!=bb.get(__vector(o) + j * 1) : false; } - public int testarrayofboolsLength() { int o = __offset(52); return o != 0 ? __vector_len(o) : 0; } - public ByteBuffer testarrayofboolsAsByteBuffer() { return __vector_as_bytebuffer(52, 1); } - public boolean mutateTestarrayofbools(int j, boolean testarrayofbools) { int o = __offset(52); if (o != 0) { bb.put(__vector(o) + j * 1, (byte)(testarrayofbools ? 1 : 0)); return true; } else { return false; } } - public float testf() { int o = __offset(54); return o != 0 ? bb.getFloat(o + bb_pos) : 3.14159f; } - public boolean mutateTestf(float testf) { int o = __offset(54); if (o != 0) { bb.putFloat(o + bb_pos, testf); return true; } else { return false; } } - public float testf2() { int o = __offset(56); return o != 0 ? bb.getFloat(o + bb_pos) : 3.0f; } - public boolean mutateTestf2(float testf2) { int o = __offset(56); if (o != 0) { bb.putFloat(o + bb_pos, testf2); return true; } else { return false; } } - public float testf3() { int o = __offset(58); return o != 0 ? bb.getFloat(o + bb_pos) : 0.0f; } - public boolean mutateTestf3(float testf3) { int o = __offset(58); if (o != 0) { bb.putFloat(o + bb_pos, testf3); return true; } else { return false; } } - - public static void startMonster(FlatBufferBuilder builder) { builder.startObject(28); } - public static void addPos(FlatBufferBuilder builder, int posOffset) { builder.addStruct(0, posOffset, 0); } - public static void addMana(FlatBufferBuilder builder, short mana) { builder.addShort(1, mana, 150); } - public static void addHp(FlatBufferBuilder builder, short hp) { builder.addShort(2, hp, 100); } - public static void addName(FlatBufferBuilder builder, int nameOffset) { builder.addOffset(3, nameOffset, 0); } - public static void addInventory(FlatBufferBuilder builder, int inventoryOffset) { builder.addOffset(5, inventoryOffset, 0); } - public static int createInventoryVector(FlatBufferBuilder builder, byte[] data) { builder.startVector(1, data.length, 1); for (int i = data.length - 1; i >= 0; i--) builder.addByte(data[i]); return builder.endVector(); } - public static void startInventoryVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems, 1); } - public static void addColor(FlatBufferBuilder builder, byte color) { builder.addByte(6, color, 8); } - public static void addTestType(FlatBufferBuilder builder, byte testType) { builder.addByte(7, testType, 0); } - public static void addTest(FlatBufferBuilder builder, int testOffset) { builder.addOffset(8, testOffset, 0); } - public static void addTest4(FlatBufferBuilder builder, int test4Offset) { builder.addOffset(9, test4Offset, 0); } - public static void startTest4Vector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 2); } - public static void addTestarrayofstring(FlatBufferBuilder builder, int testarrayofstringOffset) { builder.addOffset(10, testarrayofstringOffset, 0); } - public static int createTestarrayofstringVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } - public static void startTestarrayofstringVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addTestarrayoftables(FlatBufferBuilder builder, int testarrayoftablesOffset) { builder.addOffset(11, testarrayoftablesOffset, 0); } - public static int createTestarrayoftablesVector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); } - public static void startTestarrayoftablesVector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); } - public static void addEnemy(FlatBufferBuilder builder, int enemyOffset) { builder.addOffset(12, enemyOffset, 0); } - public static void addTestnestedflatbuffer(FlatBufferBuilder builder, int testnestedflatbufferOffset) { builder.addOffset(13, testnestedflatbufferOffset, 0); } - public static int createTestnestedflatbufferVector(FlatBufferBuilder builder, byte[] data) { builder.startVector(1, data.length, 1); for (int i = data.length - 1; i >= 0; i--) builder.addByte(data[i]); return builder.endVector(); } - public static void startTestnestedflatbufferVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems, 1); } - public static void addTestempty(FlatBufferBuilder builder, int testemptyOffset) { builder.addOffset(14, testemptyOffset, 0); } - public static void addTestbool(FlatBufferBuilder builder, boolean testbool) { builder.addBoolean(15, testbool, false); } - public static void addTesthashs32Fnv1(FlatBufferBuilder builder, int testhashs32Fnv1) { builder.addInt(16, testhashs32Fnv1, 0); } - public static void addTesthashu32Fnv1(FlatBufferBuilder builder, long testhashu32Fnv1) { builder.addInt(17, (int)testhashu32Fnv1, 0); } - public static void addTesthashs64Fnv1(FlatBufferBuilder builder, long testhashs64Fnv1) { builder.addLong(18, testhashs64Fnv1, 0); } - public static void addTesthashu64Fnv1(FlatBufferBuilder builder, long testhashu64Fnv1) { builder.addLong(19, testhashu64Fnv1, 0); } - public static void addTesthashs32Fnv1a(FlatBufferBuilder builder, int testhashs32Fnv1a) { builder.addInt(20, testhashs32Fnv1a, 0); } - public static void addTesthashu32Fnv1a(FlatBufferBuilder builder, long testhashu32Fnv1a) { builder.addInt(21, (int)testhashu32Fnv1a, 0); } - public static void addTesthashs64Fnv1a(FlatBufferBuilder builder, long testhashs64Fnv1a) { builder.addLong(22, testhashs64Fnv1a, 0); } - public static void addTesthashu64Fnv1a(FlatBufferBuilder builder, long testhashu64Fnv1a) { builder.addLong(23, testhashu64Fnv1a, 0); } - public static void addTestarrayofbools(FlatBufferBuilder builder, int testarrayofboolsOffset) { builder.addOffset(24, testarrayofboolsOffset, 0); } - public static int createTestarrayofboolsVector(FlatBufferBuilder builder, boolean[] data) { builder.startVector(1, data.length, 1); for (int i = data.length - 1; i >= 0; i--) builder.addBoolean(data[i]); return builder.endVector(); } - public static void startTestarrayofboolsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems, 1); } - public static void addTestf(FlatBufferBuilder builder, float testf) { builder.addFloat(25, testf, 3.14159f); } - public static void addTestf2(FlatBufferBuilder builder, float testf2) { builder.addFloat(26, testf2, 3.0f); } - public static void addTestf3(FlatBufferBuilder builder, float testf3) { builder.addFloat(27, testf3, 0.0f); } - public static int endMonster(FlatBufferBuilder builder) { - int o = builder.endObject(); - builder.required(o, 10); // name - return o; - } - public static void finishMonsterBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset, "MONS"); } -}; - diff --git a/tests/MyGame/Example/Monster.php b/tests/MyGame/Example/Monster.php deleted file mode 100644 index 879b76247d..0000000000 --- a/tests/MyGame/Example/Monster.php +++ /dev/null @@ -1,835 +0,0 @@ -init($bb->getInt($bb->getPosition()) + $bb->getPosition(), $bb)); - } - - public static function MonsterIdentifier() - { - return "MONS"; - } - - public static function MonsterBufferHasIdentifier(ByteBuffer $buf) - { - return self::__has_identifier($buf, self::MonsterIdentifier()); - } - - public static function MonsterExtension() - { - return "mon"; - } - - /** - * @param int $_i offset - * @param ByteBuffer $_bb - * @return Monster - **/ - public function init($_i, ByteBuffer $_bb) - { - $this->bb_pos = $_i; - $this->bb = $_bb; - return $this; - } - - public function getPos() - { - $obj = new Vec3(); - $o = $this->__offset(4); - return $o != 0 ? $obj->init($o + $this->bb_pos, $this->bb) : 0; - } - - /** - * @return short - */ - public function getMana() - { - $o = $this->__offset(6); - return $o != 0 ? $this->bb->getShort($o + $this->bb_pos) : 150; - } - - /** - * @return short - */ - public function getHp() - { - $o = $this->__offset(8); - return $o != 0 ? $this->bb->getShort($o + $this->bb_pos) : 100; - } - - public function getName() - { - $o = $this->__offset(10); - return $o != 0 ? $this->__string($o + $this->bb_pos) : null; - } - - /** - * @param int offset - * @return byte - */ - public function getInventory($j) - { - $o = $this->__offset(14); - return $o != 0 ? $this->bb->getByte($this->__vector($o) + $j * 1) : 0; - } - - /** - * @return int - */ - public function getInventoryLength() - { - $o = $this->__offset(14); - return $o != 0 ? $this->__vector_len($o) : 0; - } - - /** - * @return string - */ - public function getInventoryBytes() - { - return $this->__vector_as_bytes(14); - } - - /** - * @return sbyte - */ - public function getColor() - { - $o = $this->__offset(16); - return $o != 0 ? $this->bb->getSbyte($o + $this->bb_pos) : \MyGame\Example\Color::Blue; - } - - /** - * @return byte - */ - public function getTestType() - { - $o = $this->__offset(18); - return $o != 0 ? $this->bb->getByte($o + $this->bb_pos) : \MyGame\Example\Any::NONE; - } - - /** - * @returnint - */ - public function getTest($obj) - { - $o = $this->__offset(20); - return $o != 0 ? $this->__union($obj, $o) : null; - } - - /** - * @returnVectorOffset - */ - public function getTest4($j) - { - $o = $this->__offset(22); - $obj = new Test(); - return $o != 0 ? $obj->init($this->__vector($o) + $j *4, $this->bb) : null; - } - - /** - * @return int - */ - public function getTest4Length() - { - $o = $this->__offset(22); - return $o != 0 ? $this->__vector_len($o) : 0; - } - - /** - * @param int offset - * @return string - */ - public function getTestarrayofstring($j) - { - $o = $this->__offset(24); - return $o != 0 ? $this->__string($this->__vector($o) + $j * 4) : 0; - } - - /** - * @return int - */ - public function getTestarrayofstringLength() - { - $o = $this->__offset(24); - return $o != 0 ? $this->__vector_len($o) : 0; - } - -/// an example documentation comment: this will end up in the generated code -/// multiline too - /** - * @returnVectorOffset - */ - public function getTestarrayoftables($j) - { - $o = $this->__offset(26); - $obj = new Monster(); - return $o != 0 ? $obj->init($this->__indirect($this->__vector($o) + $j * 4), $this->bb) : null; - } - - /** - * @return int - */ - public function getTestarrayoftablesLength() - { - $o = $this->__offset(26); - return $o != 0 ? $this->__vector_len($o) : 0; - } - - public function getEnemy() - { - $obj = new Monster(); - $o = $this->__offset(28); - return $o != 0 ? $obj->init($this->__indirect($o + $this->bb_pos), $this->bb) : 0; - } - - /** - * @param int offset - * @return byte - */ - public function getTestnestedflatbuffer($j) - { - $o = $this->__offset(30); - return $o != 0 ? $this->bb->getByte($this->__vector($o) + $j * 1) : 0; - } - - /** - * @return int - */ - public function getTestnestedflatbufferLength() - { - $o = $this->__offset(30); - return $o != 0 ? $this->__vector_len($o) : 0; - } - - /** - * @return string - */ - public function getTestnestedflatbufferBytes() - { - return $this->__vector_as_bytes(30); - } - - public function getTestempty() - { - $obj = new Stat(); - $o = $this->__offset(32); - return $o != 0 ? $obj->init($this->__indirect($o + $this->bb_pos), $this->bb) : 0; - } - - /** - * @return bool - */ - public function getTestbool() - { - $o = $this->__offset(34); - return $o != 0 ? $this->bb->getBool($o + $this->bb_pos) : false; - } - - /** - * @return int - */ - public function getTesthashs32Fnv1() - { - $o = $this->__offset(36); - return $o != 0 ? $this->bb->getInt($o + $this->bb_pos) : 0; - } - - /** - * @return uint - */ - public function getTesthashu32Fnv1() - { - $o = $this->__offset(38); - return $o != 0 ? $this->bb->getUint($o + $this->bb_pos) : 0; - } - - /** - * @return long - */ - public function getTesthashs64Fnv1() - { - $o = $this->__offset(40); - return $o != 0 ? $this->bb->getLong($o + $this->bb_pos) : 0; - } - - /** - * @return ulong - */ - public function getTesthashu64Fnv1() - { - $o = $this->__offset(42); - return $o != 0 ? $this->bb->getUlong($o + $this->bb_pos) : 0; - } - - /** - * @return int - */ - public function getTesthashs32Fnv1a() - { - $o = $this->__offset(44); - return $o != 0 ? $this->bb->getInt($o + $this->bb_pos) : 0; - } - - /** - * @return uint - */ - public function getTesthashu32Fnv1a() - { - $o = $this->__offset(46); - return $o != 0 ? $this->bb->getUint($o + $this->bb_pos) : 0; - } - - /** - * @return long - */ - public function getTesthashs64Fnv1a() - { - $o = $this->__offset(48); - return $o != 0 ? $this->bb->getLong($o + $this->bb_pos) : 0; - } - - /** - * @return ulong - */ - public function getTesthashu64Fnv1a() - { - $o = $this->__offset(50); - return $o != 0 ? $this->bb->getUlong($o + $this->bb_pos) : 0; - } - - /** - * @param int offset - * @return bool - */ - public function getTestarrayofbools($j) - { - $o = $this->__offset(52); - return $o != 0 ? $this->bb->getBool($this->__vector($o) + $j * 1) : 0; - } - - /** - * @return int - */ - public function getTestarrayofboolsLength() - { - $o = $this->__offset(52); - return $o != 0 ? $this->__vector_len($o) : 0; - } - - /** - * @return float - */ - public function getTestf() - { - $o = $this->__offset(54); - return $o != 0 ? $this->bb->getFloat($o + $this->bb_pos) : 3.14159; - } - - /** - * @return float - */ - public function getTestf2() - { - $o = $this->__offset(56); - return $o != 0 ? $this->bb->getFloat($o + $this->bb_pos) : 3.0; - } - - /** - * @return float - */ - public function getTestf3() - { - $o = $this->__offset(58); - return $o != 0 ? $this->bb->getFloat($o + $this->bb_pos) : 0.0; - } - - /** - * @param FlatBufferBuilder $builder - * @return void - */ - public static function startMonster(FlatBufferBuilder $builder) - { - $builder->StartObject(28); - } - - /** - * @param FlatBufferBuilder $builder - * @return Monster - */ - public static function createMonster(FlatBufferBuilder $builder, $pos, $mana, $hp, $name, $inventory, $color, $test_type, $test, $test4, $testarrayofstring, $testarrayoftables, $enemy, $testnestedflatbuffer, $testempty, $testbool, $testhashs32_fnv1, $testhashu32_fnv1, $testhashs64_fnv1, $testhashu64_fnv1, $testhashs32_fnv1a, $testhashu32_fnv1a, $testhashs64_fnv1a, $testhashu64_fnv1a, $testarrayofbools, $testf, $testf2, $testf3) - { - $builder->startObject(28); - self::addPos($builder, $pos); - self::addMana($builder, $mana); - self::addHp($builder, $hp); - self::addName($builder, $name); - self::addInventory($builder, $inventory); - self::addColor($builder, $color); - self::addTestType($builder, $test_type); - self::addTest($builder, $test); - self::addTest4($builder, $test4); - self::addTestarrayofstring($builder, $testarrayofstring); - self::addTestarrayoftables($builder, $testarrayoftables); - self::addEnemy($builder, $enemy); - self::addTestnestedflatbuffer($builder, $testnestedflatbuffer); - self::addTestempty($builder, $testempty); - self::addTestbool($builder, $testbool); - self::addTesthashs32Fnv1($builder, $testhashs32_fnv1); - self::addTesthashu32Fnv1($builder, $testhashu32_fnv1); - self::addTesthashs64Fnv1($builder, $testhashs64_fnv1); - self::addTesthashu64Fnv1($builder, $testhashu64_fnv1); - self::addTesthashs32Fnv1a($builder, $testhashs32_fnv1a); - self::addTesthashu32Fnv1a($builder, $testhashu32_fnv1a); - self::addTesthashs64Fnv1a($builder, $testhashs64_fnv1a); - self::addTesthashu64Fnv1a($builder, $testhashu64_fnv1a); - self::addTestarrayofbools($builder, $testarrayofbools); - self::addTestf($builder, $testf); - self::addTestf2($builder, $testf2); - self::addTestf3($builder, $testf3); - $o = $builder->endObject(); - $builder->required($o, 10); // name - return $o; - } - - /** - * @param FlatBufferBuilder $builder - * @param int - * @return void - */ - public static function addPos(FlatBufferBuilder $builder, $pos) - { - $builder->addStructX(0, $pos, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param short - * @return void - */ - public static function addMana(FlatBufferBuilder $builder, $mana) - { - $builder->addShortX(1, $mana, 150); - } - - /** - * @param FlatBufferBuilder $builder - * @param short - * @return void - */ - public static function addHp(FlatBufferBuilder $builder, $hp) - { - $builder->addShortX(2, $hp, 100); - } - - /** - * @param FlatBufferBuilder $builder - * @param StringOffset - * @return void - */ - public static function addName(FlatBufferBuilder $builder, $name) - { - $builder->addOffsetX(3, $name, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param VectorOffset - * @return void - */ - public static function addInventory(FlatBufferBuilder $builder, $inventory) - { - $builder->addOffsetX(5, $inventory, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param array offset array - * @return int vector offset - */ - public static function createInventoryVector(FlatBufferBuilder $builder, array $data) - { - $builder->startVector(1, count($data), 1); - for ($i = count($data) - 1; $i >= 0; $i--) { - $builder->addByte($data[$i]); - } - return $builder->endVector(); - } - - /** - * @param FlatBufferBuilder $builder - * @param int $numElems - * @return void - */ - public static function startInventoryVector(FlatBufferBuilder $builder, $numElems) - { - $builder->startVector(1, $numElems, 1); - } - - /** - * @param FlatBufferBuilder $builder - * @param sbyte - * @return void - */ - public static function addColor(FlatBufferBuilder $builder, $color) - { - $builder->addSbyteX(6, $color, 8); - } - - /** - * @param FlatBufferBuilder $builder - * @param byte - * @return void - */ - public static function addTestType(FlatBufferBuilder $builder, $testType) - { - $builder->addByteX(7, $testType, 0); - } - - public static function addTest(FlatBufferBuilder $builder, $offset) - { - $builder->addOffsetX(8, $offset, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param VectorOffset - * @return void - */ - public static function addTest4(FlatBufferBuilder $builder, $test4) - { - $builder->addOffsetX(9, $test4, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param array offset array - * @return int vector offset - */ - public static function createTest4Vector(FlatBufferBuilder $builder, array $data) - { - $builder->startVector(4, count($data), 2); - for ($i = count($data) - 1; $i >= 0; $i--) { - $builder->addOffset($data[$i]); - } - return $builder->endVector(); - } - - /** - * @param FlatBufferBuilder $builder - * @param int $numElems - * @return void - */ - public static function startTest4Vector(FlatBufferBuilder $builder, $numElems) - { - $builder->startVector(4, $numElems, 2); - } - - /** - * @param FlatBufferBuilder $builder - * @param VectorOffset - * @return void - */ - public static function addTestarrayofstring(FlatBufferBuilder $builder, $testarrayofstring) - { - $builder->addOffsetX(10, $testarrayofstring, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param array offset array - * @return int vector offset - */ - public static function createTestarrayofstringVector(FlatBufferBuilder $builder, array $data) - { - $builder->startVector(4, count($data), 4); - for ($i = count($data) - 1; $i >= 0; $i--) { - $builder->addOffset($data[$i]); - } - return $builder->endVector(); - } - - /** - * @param FlatBufferBuilder $builder - * @param int $numElems - * @return void - */ - public static function startTestarrayofstringVector(FlatBufferBuilder $builder, $numElems) - { - $builder->startVector(4, $numElems, 4); - } - - /** - * @param FlatBufferBuilder $builder - * @param VectorOffset - * @return void - */ - public static function addTestarrayoftables(FlatBufferBuilder $builder, $testarrayoftables) - { - $builder->addOffsetX(11, $testarrayoftables, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param array offset array - * @return int vector offset - */ - public static function createTestarrayoftablesVector(FlatBufferBuilder $builder, array $data) - { - $builder->startVector(4, count($data), 4); - for ($i = count($data) - 1; $i >= 0; $i--) { - $builder->addOffset($data[$i]); - } - return $builder->endVector(); - } - - /** - * @param FlatBufferBuilder $builder - * @param int $numElems - * @return void - */ - public static function startTestarrayoftablesVector(FlatBufferBuilder $builder, $numElems) - { - $builder->startVector(4, $numElems, 4); - } - - /** - * @param FlatBufferBuilder $builder - * @param int - * @return void - */ - public static function addEnemy(FlatBufferBuilder $builder, $enemy) - { - $builder->addOffsetX(12, $enemy, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param VectorOffset - * @return void - */ - public static function addTestnestedflatbuffer(FlatBufferBuilder $builder, $testnestedflatbuffer) - { - $builder->addOffsetX(13, $testnestedflatbuffer, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param array offset array - * @return int vector offset - */ - public static function createTestnestedflatbufferVector(FlatBufferBuilder $builder, array $data) - { - $builder->startVector(1, count($data), 1); - for ($i = count($data) - 1; $i >= 0; $i--) { - $builder->addByte($data[$i]); - } - return $builder->endVector(); - } - - /** - * @param FlatBufferBuilder $builder - * @param int $numElems - * @return void - */ - public static function startTestnestedflatbufferVector(FlatBufferBuilder $builder, $numElems) - { - $builder->startVector(1, $numElems, 1); - } - - /** - * @param FlatBufferBuilder $builder - * @param int - * @return void - */ - public static function addTestempty(FlatBufferBuilder $builder, $testempty) - { - $builder->addOffsetX(14, $testempty, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param bool - * @return void - */ - public static function addTestbool(FlatBufferBuilder $builder, $testbool) - { - $builder->addBoolX(15, $testbool, false); - } - - /** - * @param FlatBufferBuilder $builder - * @param int - * @return void - */ - public static function addTesthashs32Fnv1(FlatBufferBuilder $builder, $testhashs32Fnv1) - { - $builder->addIntX(16, $testhashs32Fnv1, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param uint - * @return void - */ - public static function addTesthashu32Fnv1(FlatBufferBuilder $builder, $testhashu32Fnv1) - { - $builder->addUintX(17, $testhashu32Fnv1, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param long - * @return void - */ - public static function addTesthashs64Fnv1(FlatBufferBuilder $builder, $testhashs64Fnv1) - { - $builder->addLongX(18, $testhashs64Fnv1, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param ulong - * @return void - */ - public static function addTesthashu64Fnv1(FlatBufferBuilder $builder, $testhashu64Fnv1) - { - $builder->addUlongX(19, $testhashu64Fnv1, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param int - * @return void - */ - public static function addTesthashs32Fnv1a(FlatBufferBuilder $builder, $testhashs32Fnv1a) - { - $builder->addIntX(20, $testhashs32Fnv1a, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param uint - * @return void - */ - public static function addTesthashu32Fnv1a(FlatBufferBuilder $builder, $testhashu32Fnv1a) - { - $builder->addUintX(21, $testhashu32Fnv1a, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param long - * @return void - */ - public static function addTesthashs64Fnv1a(FlatBufferBuilder $builder, $testhashs64Fnv1a) - { - $builder->addLongX(22, $testhashs64Fnv1a, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param ulong - * @return void - */ - public static function addTesthashu64Fnv1a(FlatBufferBuilder $builder, $testhashu64Fnv1a) - { - $builder->addUlongX(23, $testhashu64Fnv1a, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param VectorOffset - * @return void - */ - public static function addTestarrayofbools(FlatBufferBuilder $builder, $testarrayofbools) - { - $builder->addOffsetX(24, $testarrayofbools, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param array offset array - * @return int vector offset - */ - public static function createTestarrayofboolsVector(FlatBufferBuilder $builder, array $data) - { - $builder->startVector(1, count($data), 1); - for ($i = count($data) - 1; $i >= 0; $i--) { - $builder->addBool($data[$i]); - } - return $builder->endVector(); - } - - /** - * @param FlatBufferBuilder $builder - * @param int $numElems - * @return void - */ - public static function startTestarrayofboolsVector(FlatBufferBuilder $builder, $numElems) - { - $builder->startVector(1, $numElems, 1); - } - - /** - * @param FlatBufferBuilder $builder - * @param float - * @return void - */ - public static function addTestf(FlatBufferBuilder $builder, $testf) - { - $builder->addFloatX(25, $testf, 3.14159); - } - - /** - * @param FlatBufferBuilder $builder - * @param float - * @return void - */ - public static function addTestf2(FlatBufferBuilder $builder, $testf2) - { - $builder->addFloatX(26, $testf2, 3.0); - } - - /** - * @param FlatBufferBuilder $builder - * @param float - * @return void - */ - public static function addTestf3(FlatBufferBuilder $builder, $testf3) - { - $builder->addFloatX(27, $testf3, 0.0); - } - - /** - * @param FlatBufferBuilder $builder - * @return int table offset - */ - public static function endMonster(FlatBufferBuilder $builder) - { - $o = $builder->endObject(); - $builder->required($o, 10); // name - return $o; - } - - public static function finishMonsterBuffer(FlatBufferBuilder $builder, $offset) - { - $builder->finish($offset, "MONS"); - } -} diff --git a/tests/MyGame/Example/Monster.py b/tests/MyGame/Example/Monster.py deleted file mode 100644 index 42b79939bb..0000000000 --- a/tests/MyGame/Example/Monster.py +++ /dev/null @@ -1,320 +0,0 @@ -# automatically generated, do not modify - -# namespace: Example - -import flatbuffers - -# /// an example documentation comment: monster object -class Monster(object): - __slots__ = ['_tab'] - - @classmethod - def GetRootAsMonster(cls, buf, offset): - n = flatbuffers.encode.Get(flatbuffers.packer.uoffset, buf, offset) - x = Monster() - x.Init(buf, n + offset) - return x - - - # Monster - def Init(self, buf, pos): - self._tab = flatbuffers.table.Table(buf, pos) - - # Monster - def Pos(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) - if o != 0: - x = o + self._tab.Pos - from .Vec3 import Vec3 - obj = Vec3() - obj.Init(self._tab.Bytes, x) - return obj - return None - - # Monster - def Mana(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Int16Flags, o + self._tab.Pos) - return 150 - - # Monster - def Hp(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Int16Flags, o + self._tab.Pos) - return 100 - - # Monster - def Name(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(10)) - if o != 0: - return self._tab.String(o + self._tab.Pos) - return "" - - # Monster - def Inventory(self, j): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14)) - if o != 0: - a = self._tab.Vector(o) - return self._tab.Get(flatbuffers.number_types.Uint8Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1)) - return 0 - - # Monster - def InventoryLength(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(14)) - if o != 0: - return self._tab.VectorLen(o) - return 0 - - # Monster - def Color(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(16)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos) - return 8 - - # Monster - def TestType(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(18)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Uint8Flags, o + self._tab.Pos) - return 0 - - # Monster - def Test(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(20)) - if o != 0: - from flatbuffers.table import Table - obj = Table(bytearray(), 0) - self._tab.Union(obj, o) - return obj - return None - - # Monster - def Test4(self, j): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22)) - if o != 0: - x = self._tab.Vector(o) - x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4 - from .Test import Test - obj = Test() - obj.Init(self._tab.Bytes, x) - return obj - return None - - # Monster - def Test4Length(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(22)) - if o != 0: - return self._tab.VectorLen(o) - return 0 - - # Monster - def Testarrayofstring(self, j): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(24)) - if o != 0: - a = self._tab.Vector(o) - return self._tab.String(a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 4)) - return "" - - # Monster - def TestarrayofstringLength(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(24)) - if o != 0: - return self._tab.VectorLen(o) - return 0 - -# /// an example documentation comment: this will end up in the generated code -# /// multiline too - # Monster - def Testarrayoftables(self, j): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(26)) - if o != 0: - x = self._tab.Vector(o) - x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 4 - x = self._tab.Indirect(x) - from .Monster import Monster - obj = Monster() - obj.Init(self._tab.Bytes, x) - return obj - return None - - # Monster - def TestarrayoftablesLength(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(26)) - if o != 0: - return self._tab.VectorLen(o) - return 0 - - # Monster - def Enemy(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(28)) - if o != 0: - x = self._tab.Indirect(o + self._tab.Pos) - from .Monster import Monster - obj = Monster() - obj.Init(self._tab.Bytes, x) - return obj - return None - - # Monster - def Testnestedflatbuffer(self, j): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(30)) - if o != 0: - a = self._tab.Vector(o) - return self._tab.Get(flatbuffers.number_types.Uint8Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1)) - return 0 - - # Monster - def TestnestedflatbufferLength(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(30)) - if o != 0: - return self._tab.VectorLen(o) - return 0 - - # Monster - def Testempty(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(32)) - if o != 0: - x = self._tab.Indirect(o + self._tab.Pos) - from .Stat import Stat - obj = Stat() - obj.Init(self._tab.Bytes, x) - return obj - return None - - # Monster - def Testbool(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(34)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.BoolFlags, o + self._tab.Pos) - return 0 - - # Monster - def Testhashs32Fnv1(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(36)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos) - return 0 - - # Monster - def Testhashu32Fnv1(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(38)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos) - return 0 - - # Monster - def Testhashs64Fnv1(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(40)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos) - return 0 - - # Monster - def Testhashu64Fnv1(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(42)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Uint64Flags, o + self._tab.Pos) - return 0 - - # Monster - def Testhashs32Fnv1a(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(44)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Int32Flags, o + self._tab.Pos) - return 0 - - # Monster - def Testhashu32Fnv1a(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(46)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Uint32Flags, o + self._tab.Pos) - return 0 - - # Monster - def Testhashs64Fnv1a(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(48)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos) - return 0 - - # Monster - def Testhashu64Fnv1a(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(50)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Uint64Flags, o + self._tab.Pos) - return 0 - - # Monster - def Testarrayofbools(self, j): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(52)) - if o != 0: - a = self._tab.Vector(o) - return self._tab.Get(flatbuffers.number_types.BoolFlags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1)) - return 0 - - # Monster - def TestarrayofboolsLength(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(52)) - if o != 0: - return self._tab.VectorLen(o) - return 0 - - # Monster - def Testf(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(54)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) - return 3.14159 - - # Monster - def Testf2(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(56)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) - return 3.0 - - # Monster - def Testf3(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(58)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Float32Flags, o + self._tab.Pos) - return 0.0 - -def MonsterStart(builder): builder.StartObject(28) -def MonsterAddPos(builder, pos): builder.PrependStructSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(pos), 0) -def MonsterAddMana(builder, mana): builder.PrependInt16Slot(1, mana, 150) -def MonsterAddHp(builder, hp): builder.PrependInt16Slot(2, hp, 100) -def MonsterAddName(builder, name): builder.PrependUOffsetTRelativeSlot(3, flatbuffers.number_types.UOffsetTFlags.py_type(name), 0) -def MonsterAddInventory(builder, inventory): builder.PrependUOffsetTRelativeSlot(5, flatbuffers.number_types.UOffsetTFlags.py_type(inventory), 0) -def MonsterStartInventoryVector(builder, numElems): return builder.StartVector(1, numElems, 1) -def MonsterAddColor(builder, color): builder.PrependInt8Slot(6, color, 8) -def MonsterAddTestType(builder, testType): builder.PrependUint8Slot(7, testType, 0) -def MonsterAddTest(builder, test): builder.PrependUOffsetTRelativeSlot(8, flatbuffers.number_types.UOffsetTFlags.py_type(test), 0) -def MonsterAddTest4(builder, test4): builder.PrependUOffsetTRelativeSlot(9, flatbuffers.number_types.UOffsetTFlags.py_type(test4), 0) -def MonsterStartTest4Vector(builder, numElems): return builder.StartVector(4, numElems, 2) -def MonsterAddTestarrayofstring(builder, testarrayofstring): builder.PrependUOffsetTRelativeSlot(10, flatbuffers.number_types.UOffsetTFlags.py_type(testarrayofstring), 0) -def MonsterStartTestarrayofstringVector(builder, numElems): return builder.StartVector(4, numElems, 4) -def MonsterAddTestarrayoftables(builder, testarrayoftables): builder.PrependUOffsetTRelativeSlot(11, flatbuffers.number_types.UOffsetTFlags.py_type(testarrayoftables), 0) -def MonsterStartTestarrayoftablesVector(builder, numElems): return builder.StartVector(4, numElems, 4) -def MonsterAddEnemy(builder, enemy): builder.PrependUOffsetTRelativeSlot(12, flatbuffers.number_types.UOffsetTFlags.py_type(enemy), 0) -def MonsterAddTestnestedflatbuffer(builder, testnestedflatbuffer): builder.PrependUOffsetTRelativeSlot(13, flatbuffers.number_types.UOffsetTFlags.py_type(testnestedflatbuffer), 0) -def MonsterStartTestnestedflatbufferVector(builder, numElems): return builder.StartVector(1, numElems, 1) -def MonsterAddTestempty(builder, testempty): builder.PrependUOffsetTRelativeSlot(14, flatbuffers.number_types.UOffsetTFlags.py_type(testempty), 0) -def MonsterAddTestbool(builder, testbool): builder.PrependBoolSlot(15, testbool, 0) -def MonsterAddTesthashs32Fnv1(builder, testhashs32Fnv1): builder.PrependInt32Slot(16, testhashs32Fnv1, 0) -def MonsterAddTesthashu32Fnv1(builder, testhashu32Fnv1): builder.PrependUint32Slot(17, testhashu32Fnv1, 0) -def MonsterAddTesthashs64Fnv1(builder, testhashs64Fnv1): builder.PrependInt64Slot(18, testhashs64Fnv1, 0) -def MonsterAddTesthashu64Fnv1(builder, testhashu64Fnv1): builder.PrependUint64Slot(19, testhashu64Fnv1, 0) -def MonsterAddTesthashs32Fnv1a(builder, testhashs32Fnv1a): builder.PrependInt32Slot(20, testhashs32Fnv1a, 0) -def MonsterAddTesthashu32Fnv1a(builder, testhashu32Fnv1a): builder.PrependUint32Slot(21, testhashu32Fnv1a, 0) -def MonsterAddTesthashs64Fnv1a(builder, testhashs64Fnv1a): builder.PrependInt64Slot(22, testhashs64Fnv1a, 0) -def MonsterAddTesthashu64Fnv1a(builder, testhashu64Fnv1a): builder.PrependUint64Slot(23, testhashu64Fnv1a, 0) -def MonsterAddTestarrayofbools(builder, testarrayofbools): builder.PrependUOffsetTRelativeSlot(24, flatbuffers.number_types.UOffsetTFlags.py_type(testarrayofbools), 0) -def MonsterStartTestarrayofboolsVector(builder, numElems): return builder.StartVector(1, numElems, 1) -def MonsterAddTestf(builder, testf): builder.PrependFloat32Slot(25, testf, 3.14159) -def MonsterAddTestf2(builder, testf2): builder.PrependFloat32Slot(26, testf2, 3.0) -def MonsterAddTestf3(builder, testf3): builder.PrependFloat32Slot(27, testf3, 0.0) -def MonsterEnd(builder): return builder.EndObject() diff --git a/tests/MyGame/Example/Monster.rs b/tests/MyGame/Example/Monster.rs index 81b810a30a..3d77c5c937 100644 --- a/tests/MyGame/Example/Monster.rs +++ b/tests/MyGame/Example/Monster.rs @@ -4,34 +4,106 @@ use flatbuffers; use super::*; /// an example documentation comment: monster object -table_object!{Monster, 4, [ - (pos,get_struct, Vec3, 4), - (mana,get_i16, i16, 6, 150), - (hp,get_i16, i16, 8, 100), - (name,get_str, &str, 10, 0), - (inventory,vector, u8, 14), - (color,simple_enum,get_i8, i8, Color, 16, 8), - (test_type,simple_enum,get_u8, u8, AnyType, 18, 0), - (test,union,test_type, Any, Any, 20, 0), - (test4,vector, Test, 22), - (testarrayofstring,vector, &str, 24), - (testarrayoftables,vector, Monster, 26), - (enemy,get_struct, Monster, 28), - (testnestedflatbuffer,vector, u8, 30), - (testempty,get_struct, Stat, 32), - (testbool,get_bool, bool, 34, false), - (testhashs32_fnv1,get_i32, i32, 36, 0), - (testhashu32_fnv1,get_u32, u32, 38, 0), - (testhashs64_fnv1,get_i64, i64, 40, 0), - (testhashu64_fnv1,get_u64, u64, 42, 0), - (testhashs32_fnv1a,get_i32, i32, 44, 0), - (testhashu32_fnv1a,get_u32, u32, 46, 0), - (testhashs64_fnv1a,get_i64, i64, 48, 0), - (testhashu64_fnv1a,get_u64, u64, 50, 0), - (testarrayofbools,vector, bool, 52), - (testf,get_f32, f32, 54, 3.14159), - (testf2,get_f32, f32, 56, 3.0), - (testf3,get_f32, f32, 58, 0.0)]} +flatbuffers_object!{Table => Monster [ + field => { name = pos, + typeOf = Vec3, + slot = 4 }, + field => { name = mana, + typeOf = i16, + slot = 6, + default = 150 }, + field => { name = hp, + typeOf = i16, + slot = 8, + default = 100 }, + field => { name = name, + typeOf = string, + slot = 10, + default = 0 }, + field => { name = inventory, + typeOf = [u8], + slot = 14 }, + field => { name = color, + typeOf = enum Color i8, + slot = 16, + default = 8 }, + field => { name = test_type, + typeOf = enum AnyType u8, + slot = 18, + default = 0 }, + field => { name = test, + typeOf = union Any, + slot = 20, + default = 0 }, + field => { name = test4, + typeOf = [Test], + slot = 22 }, + field => { name = testarrayofstring, + typeOf = [string], + slot = 24 }, + field => { name = testarrayoftables, + typeOf = [Monster], + slot = 26 }, + field => { name = enemy, + typeOf = Monster, + slot = 28 }, + field => { name = testnestedflatbuffer, + typeOf = [u8], + slot = 30 }, + field => { name = testempty, + typeOf = Stat, + slot = 32 }, + field => { name = testbool, + typeOf = bool, + slot = 34, + default = false }, + field => { name = testhashs32_fnv1, + typeOf = i32, + slot = 36, + default = 0 }, + field => { name = testhashu32_fnv1, + typeOf = u32, + slot = 38, + default = 0 }, + field => { name = testhashs64_fnv1, + typeOf = i64, + slot = 40, + default = 0 }, + field => { name = testhashu64_fnv1, + typeOf = u64, + slot = 42, + default = 0 }, + field => { name = testhashs32_fnv1a, + typeOf = i32, + slot = 44, + default = 0 }, + field => { name = testhashu32_fnv1a, + typeOf = u32, + slot = 46, + default = 0 }, + field => { name = testhashs64_fnv1a, + typeOf = i64, + slot = 48, + default = 0 }, + field => { name = testhashu64_fnv1a, + typeOf = u64, + slot = 50, + default = 0 }, + field => { name = testarrayofbools, + typeOf = [bool], + slot = 52 }, + field => { name = testf, + typeOf = f32, + slot = 54, + default = 3.14159 }, + field => { name = testf2, + typeOf = f32, + slot = 56, + default = 3.0 }, + field => { name = testf3, + typeOf = f32, + slot = 58, + default = 0.0 }]} /// Builder Trait for `Monster` tables. pub trait MonsterBuilder { diff --git a/tests/MyGame/Example/Stat.cs b/tests/MyGame/Example/Stat.cs deleted file mode 100644 index 2b3f5375f8..0000000000 --- a/tests/MyGame/Example/Stat.cs +++ /dev/null @@ -1,43 +0,0 @@ -// automatically generated, do not modify - -namespace MyGame.Example -{ - -using System; -using FlatBuffers; - -public sealed class Stat : Table { - public static Stat GetRootAsStat(ByteBuffer _bb) { return GetRootAsStat(_bb, new Stat()); } - public static Stat GetRootAsStat(ByteBuffer _bb, Stat obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } - public Stat __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } - - public string Id { get { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; } } - public ArraySegment? GetIdBytes() { return __vector_as_arraysegment(4); } - public long Val { get { int o = __offset(6); return o != 0 ? bb.GetLong(o + bb_pos) : (long)0; } } - public bool MutateVal(long val) { int o = __offset(6); if (o != 0) { bb.PutLong(o + bb_pos, val); return true; } else { return false; } } - public ushort Count { get { int o = __offset(8); return o != 0 ? bb.GetUshort(o + bb_pos) : (ushort)0; } } - public bool MutateCount(ushort count) { int o = __offset(8); if (o != 0) { bb.PutUshort(o + bb_pos, count); return true; } else { return false; } } - - public static Offset CreateStat(FlatBufferBuilder builder, - StringOffset idOffset = default(StringOffset), - long val = 0, - ushort count = 0) { - builder.StartObject(3); - Stat.AddVal(builder, val); - Stat.AddId(builder, idOffset); - Stat.AddCount(builder, count); - return Stat.EndStat(builder); - } - - public static void StartStat(FlatBufferBuilder builder) { builder.StartObject(3); } - public static void AddId(FlatBufferBuilder builder, StringOffset idOffset) { builder.AddOffset(0, idOffset.Value, 0); } - public static void AddVal(FlatBufferBuilder builder, long val) { builder.AddLong(1, val, 0); } - public static void AddCount(FlatBufferBuilder builder, ushort count) { builder.AddUshort(2, count, 0); } - public static Offset EndStat(FlatBufferBuilder builder) { - int o = builder.EndObject(); - return new Offset(o); - } -}; - - -} diff --git a/tests/MyGame/Example/Stat.java b/tests/MyGame/Example/Stat.java deleted file mode 100644 index dd3716330a..0000000000 --- a/tests/MyGame/Example/Stat.java +++ /dev/null @@ -1,43 +0,0 @@ -// automatically generated, do not modify - -package MyGame.Example; - -import java.nio.*; -import java.lang.*; -import java.util.*; -import com.google.flatbuffers.*; - -@SuppressWarnings("unused") -public final class Stat extends Table { - public static Stat getRootAsStat(ByteBuffer _bb) { return getRootAsStat(_bb, new Stat()); } - public static Stat getRootAsStat(ByteBuffer _bb, Stat obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public Stat __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } - - public String id() { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; } - public ByteBuffer idAsByteBuffer() { return __vector_as_bytebuffer(4, 1); } - public long val() { int o = __offset(6); return o != 0 ? bb.getLong(o + bb_pos) : 0; } - public boolean mutateVal(long val) { int o = __offset(6); if (o != 0) { bb.putLong(o + bb_pos, val); return true; } else { return false; } } - public int count() { int o = __offset(8); return o != 0 ? bb.getShort(o + bb_pos) & 0xFFFF : 0; } - public boolean mutateCount(int count) { int o = __offset(8); if (o != 0) { bb.putShort(o + bb_pos, (short)count); return true; } else { return false; } } - - public static int createStat(FlatBufferBuilder builder, - int idOffset, - long val, - int count) { - builder.startObject(3); - Stat.addVal(builder, val); - Stat.addId(builder, idOffset); - Stat.addCount(builder, count); - return Stat.endStat(builder); - } - - public static void startStat(FlatBufferBuilder builder) { builder.startObject(3); } - public static void addId(FlatBufferBuilder builder, int idOffset) { builder.addOffset(0, idOffset, 0); } - public static void addVal(FlatBufferBuilder builder, long val) { builder.addLong(1, val, 0); } - public static void addCount(FlatBufferBuilder builder, int count) { builder.addShort(2, (short)count, 0); } - public static int endStat(FlatBufferBuilder builder) { - int o = builder.endObject(); - return o; - } -}; - diff --git a/tests/MyGame/Example/Stat.php b/tests/MyGame/Example/Stat.php deleted file mode 100644 index c959ac7bb1..0000000000 --- a/tests/MyGame/Example/Stat.php +++ /dev/null @@ -1,136 +0,0 @@ -init($bb->getInt($bb->getPosition()) + $bb->getPosition(), $bb)); - } - - public static function StatIdentifier() - { - return "MONS"; - } - - public static function StatBufferHasIdentifier(ByteBuffer $buf) - { - return self::__has_identifier($buf, self::StatIdentifier()); - } - - public static function StatExtension() - { - return "mon"; - } - - /** - * @param int $_i offset - * @param ByteBuffer $_bb - * @return Stat - **/ - public function init($_i, ByteBuffer $_bb) - { - $this->bb_pos = $_i; - $this->bb = $_bb; - return $this; - } - - public function getId() - { - $o = $this->__offset(4); - return $o != 0 ? $this->__string($o + $this->bb_pos) : null; - } - - /** - * @return long - */ - public function getVal() - { - $o = $this->__offset(6); - return $o != 0 ? $this->bb->getLong($o + $this->bb_pos) : 0; - } - - /** - * @return ushort - */ - public function getCount() - { - $o = $this->__offset(8); - return $o != 0 ? $this->bb->getUshort($o + $this->bb_pos) : 0; - } - - /** - * @param FlatBufferBuilder $builder - * @return void - */ - public static function startStat(FlatBufferBuilder $builder) - { - $builder->StartObject(3); - } - - /** - * @param FlatBufferBuilder $builder - * @return Stat - */ - public static function createStat(FlatBufferBuilder $builder, $id, $val, $count) - { - $builder->startObject(3); - self::addId($builder, $id); - self::addVal($builder, $val); - self::addCount($builder, $count); - $o = $builder->endObject(); - return $o; - } - - /** - * @param FlatBufferBuilder $builder - * @param StringOffset - * @return void - */ - public static function addId(FlatBufferBuilder $builder, $id) - { - $builder->addOffsetX(0, $id, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param long - * @return void - */ - public static function addVal(FlatBufferBuilder $builder, $val) - { - $builder->addLongX(1, $val, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @param ushort - * @return void - */ - public static function addCount(FlatBufferBuilder $builder, $count) - { - $builder->addUshortX(2, $count, 0); - } - - /** - * @param FlatBufferBuilder $builder - * @return int table offset - */ - public static function endStat(FlatBufferBuilder $builder) - { - $o = $builder->endObject(); - return $o; - } -} diff --git a/tests/MyGame/Example/Stat.py b/tests/MyGame/Example/Stat.py deleted file mode 100644 index 23bef0db62..0000000000 --- a/tests/MyGame/Example/Stat.py +++ /dev/null @@ -1,39 +0,0 @@ -# automatically generated, do not modify - -# namespace: Example - -import flatbuffers - -class Stat(object): - __slots__ = ['_tab'] - - # Stat - def Init(self, buf, pos): - self._tab = flatbuffers.table.Table(buf, pos) - - # Stat - def Id(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) - if o != 0: - return self._tab.String(o + self._tab.Pos) - return "" - - # Stat - def Val(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Int64Flags, o + self._tab.Pos) - return 0 - - # Stat - def Count(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(8)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Uint16Flags, o + self._tab.Pos) - return 0 - -def StatStart(builder): builder.StartObject(3) -def StatAddId(builder, id): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(id), 0) -def StatAddVal(builder, val): builder.PrependInt64Slot(1, val, 0) -def StatAddCount(builder, count): builder.PrependUint16Slot(2, count, 0) -def StatEnd(builder): return builder.EndObject() diff --git a/tests/MyGame/Example/Stat.rs b/tests/MyGame/Example/Stat.rs index a68dd0ed04..a03e80aaac 100644 --- a/tests/MyGame/Example/Stat.rs +++ b/tests/MyGame/Example/Stat.rs @@ -3,10 +3,19 @@ use flatbuffers; use super::*; -table_object!{Stat, 4, [ - (id,get_str, &str, 4, 0), - (val,get_i64, i64, 6, 0), - (count,get_u16, u16, 8, 0)]} +flatbuffers_object!{Table => Stat [ + field => { name = id, + typeOf = string, + slot = 4, + default = 0 }, + field => { name = val, + typeOf = i64, + slot = 6, + default = 0 }, + field => { name = count, + typeOf = u16, + slot = 8, + default = 0 }]} /// Builder Trait for `Stat` tables. pub trait StatBuilder { diff --git a/tests/MyGame/Example/Test.cs b/tests/MyGame/Example/Test.cs deleted file mode 100644 index 5bd2e58dd2..0000000000 --- a/tests/MyGame/Example/Test.cs +++ /dev/null @@ -1,27 +0,0 @@ -// automatically generated, do not modify - -namespace MyGame.Example -{ - -using System; -using FlatBuffers; - -public sealed class Test : Struct { - public Test __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } - - public short A { get { return bb.GetShort(bb_pos + 0); } } - public void MutateA(short a) { bb.PutShort(bb_pos + 0, a); } - public sbyte B { get { return bb.GetSbyte(bb_pos + 2); } } - public void MutateB(sbyte b) { bb.PutSbyte(bb_pos + 2, b); } - - public static Offset CreateTest(FlatBufferBuilder builder, short A, sbyte B) { - builder.Prep(2, 4); - builder.Pad(1); - builder.PutSbyte(B); - builder.PutShort(A); - return new Offset(builder.Offset); - } -}; - - -} diff --git a/tests/MyGame/Example/Test.java b/tests/MyGame/Example/Test.java deleted file mode 100644 index ffd7394f64..0000000000 --- a/tests/MyGame/Example/Test.java +++ /dev/null @@ -1,27 +0,0 @@ -// automatically generated, do not modify - -package MyGame.Example; - -import java.nio.*; -import java.lang.*; -import java.util.*; -import com.google.flatbuffers.*; - -@SuppressWarnings("unused") -public final class Test extends Struct { - public Test __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } - - public short a() { return bb.getShort(bb_pos + 0); } - public void mutateA(short a) { bb.putShort(bb_pos + 0, a); } - public byte b() { return bb.get(bb_pos + 2); } - public void mutateB(byte b) { bb.put(bb_pos + 2, b); } - - public static int createTest(FlatBufferBuilder builder, short a, byte b) { - builder.prep(2, 4); - builder.pad(1); - builder.putByte(b); - builder.putShort(a); - return builder.offset(); - } -}; - diff --git a/tests/MyGame/Example/Test.php b/tests/MyGame/Example/Test.php deleted file mode 100644 index acc838a334..0000000000 --- a/tests/MyGame/Example/Test.php +++ /dev/null @@ -1,53 +0,0 @@ -bb_pos = $_i; - $this->bb = $_bb; - return $this; - } - - /** - * @return short - */ - public function GetA() - { - return $this->bb->getShort($this->bb_pos + 0); - } - - /** - * @return sbyte - */ - public function GetB() - { - return $this->bb->getSbyte($this->bb_pos + 2); - } - - - /** - * @return int offset - */ - public static function createTest(FlatBufferBuilder $builder, $a, $b) - { - $builder->prep(2, 4); - $builder->pad(1); - $builder->putSbyte($b); - $builder->putShort($a); - return $builder->offset(); - } -} diff --git a/tests/MyGame/Example/Test.py b/tests/MyGame/Example/Test.py deleted file mode 100644 index 4c4912a619..0000000000 --- a/tests/MyGame/Example/Test.py +++ /dev/null @@ -1,24 +0,0 @@ -# automatically generated, do not modify - -# namespace: Example - -import flatbuffers - -class Test(object): - __slots__ = ['_tab'] - - # Test - def Init(self, buf, pos): - self._tab = flatbuffers.table.Table(buf, pos) - - # Test - def A(self): return self._tab.Get(flatbuffers.number_types.Int16Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(0)) - # Test - def B(self): return self._tab.Get(flatbuffers.number_types.Int8Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(2)) - -def CreateTest(builder, a, b): - builder.Prep(2, 4) - builder.Pad(1) - builder.PrependInt8(b) - builder.PrependInt16(a) - return builder.Offset() diff --git a/tests/MyGame/Example/Test.rs b/tests/MyGame/Example/Test.rs index 8cf0fa5c3f..e4130cb1fc 100644 --- a/tests/MyGame/Example/Test.rs +++ b/tests/MyGame/Example/Test.rs @@ -3,9 +3,16 @@ use flatbuffers; use super::*; -struct_object!{Test, 4, [ - (a,get_i16, i16, 0, 0), - (b,get_i8, i8, 2, 0)]} +flatbuffers_object!{Struct => Test ( size:4, align: 2) [ + field => { name = a, + typeOf = i16, + slot = 0, + default = 0 }, + field => { name = b, + typeOf = i8, + slot = 2, + default = 0, + padding = 1 }]} pub trait TestBuilder { fn build_test(&mut self, a: i16, b: i8) -> flatbuffers::UOffsetT; diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.cs b/tests/MyGame/Example/TestSimpleTableWithEnum.cs deleted file mode 100644 index c1bf571f84..0000000000 --- a/tests/MyGame/Example/TestSimpleTableWithEnum.cs +++ /dev/null @@ -1,33 +0,0 @@ -// automatically generated, do not modify - -namespace MyGame.Example -{ - -using System; -using FlatBuffers; - -public partial class TestSimpleTableWithEnum : Table { - public static TestSimpleTableWithEnum GetRootAsTestSimpleTableWithEnum(ByteBuffer _bb) { return GetRootAsTestSimpleTableWithEnum(_bb, new TestSimpleTableWithEnum()); } - public static TestSimpleTableWithEnum GetRootAsTestSimpleTableWithEnum(ByteBuffer _bb, TestSimpleTableWithEnum obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } - public TestSimpleTableWithEnum __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } - - public Color Color { get { int o = __offset(4); return o != 0 ? (Color)bb.GetSbyte(o + bb_pos) : Color.Green; } } - public bool MutateColor(Color color) { int o = __offset(4); if (o != 0) { bb.PutSbyte(o + bb_pos, (sbyte)color); return true; } else { return false; } } - - public static Offset CreateTestSimpleTableWithEnum(FlatBufferBuilder builder, - Color color = Color.Green) { - builder.StartObject(1); - TestSimpleTableWithEnum.AddColor(builder, color); - return TestSimpleTableWithEnum.EndTestSimpleTableWithEnum(builder); - } - - public static void StartTestSimpleTableWithEnum(FlatBufferBuilder builder) { builder.StartObject(1); } - public static void AddColor(FlatBufferBuilder builder, Color color) { builder.AddSbyte(0, (sbyte)color, 2); } - public static Offset EndTestSimpleTableWithEnum(FlatBufferBuilder builder) { - int o = builder.EndObject(); - return new Offset(o); - } -}; - - -} diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.java b/tests/MyGame/Example/TestSimpleTableWithEnum.java deleted file mode 100644 index 3000cab47f..0000000000 --- a/tests/MyGame/Example/TestSimpleTableWithEnum.java +++ /dev/null @@ -1,33 +0,0 @@ -// automatically generated, do not modify - -package MyGame.Example; - -import java.nio.*; -import java.lang.*; -import java.util.*; -import com.google.flatbuffers.*; - -@SuppressWarnings("unused") -public final class TestSimpleTableWithEnum extends Table { - public static TestSimpleTableWithEnum getRootAsTestSimpleTableWithEnum(ByteBuffer _bb) { return getRootAsTestSimpleTableWithEnum(_bb, new TestSimpleTableWithEnum()); } - public static TestSimpleTableWithEnum getRootAsTestSimpleTableWithEnum(ByteBuffer _bb, TestSimpleTableWithEnum obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } - public TestSimpleTableWithEnum __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } - - public byte color() { int o = __offset(4); return o != 0 ? bb.get(o + bb_pos) : 2; } - public boolean mutateColor(byte color) { int o = __offset(4); if (o != 0) { bb.put(o + bb_pos, color); return true; } else { return false; } } - - public static int createTestSimpleTableWithEnum(FlatBufferBuilder builder, - byte color) { - builder.startObject(1); - TestSimpleTableWithEnum.addColor(builder, color); - return TestSimpleTableWithEnum.endTestSimpleTableWithEnum(builder); - } - - public static void startTestSimpleTableWithEnum(FlatBufferBuilder builder) { builder.startObject(1); } - public static void addColor(FlatBufferBuilder builder, byte color) { builder.addByte(0, color, 2); } - public static int endTestSimpleTableWithEnum(FlatBufferBuilder builder) { - int o = builder.endObject(); - return o; - } -}; - diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.php b/tests/MyGame/Example/TestSimpleTableWithEnum.php deleted file mode 100644 index 6181461e59..0000000000 --- a/tests/MyGame/Example/TestSimpleTableWithEnum.php +++ /dev/null @@ -1,99 +0,0 @@ -init($bb->getInt($bb->getPosition()) + $bb->getPosition(), $bb)); - } - - public static function TestSimpleTableWithEnumIdentifier() - { - return "MONS"; - } - - public static function TestSimpleTableWithEnumBufferHasIdentifier(ByteBuffer $buf) - { - return self::__has_identifier($buf, self::TestSimpleTableWithEnumIdentifier()); - } - - public static function TestSimpleTableWithEnumExtension() - { - return "mon"; - } - - /** - * @param int $_i offset - * @param ByteBuffer $_bb - * @return TestSimpleTableWithEnum - **/ - public function init($_i, ByteBuffer $_bb) - { - $this->bb_pos = $_i; - $this->bb = $_bb; - return $this; - } - - /** - * @return sbyte - */ - public function getColor() - { - $o = $this->__offset(4); - return $o != 0 ? $this->bb->getSbyte($o + $this->bb_pos) : \MyGame\Example\Color::Green; - } - - /** - * @param FlatBufferBuilder $builder - * @return void - */ - public static function startTestSimpleTableWithEnum(FlatBufferBuilder $builder) - { - $builder->StartObject(1); - } - - /** - * @param FlatBufferBuilder $builder - * @return TestSimpleTableWithEnum - */ - public static function createTestSimpleTableWithEnum(FlatBufferBuilder $builder, $color) - { - $builder->startObject(1); - self::addColor($builder, $color); - $o = $builder->endObject(); - return $o; - } - - /** - * @param FlatBufferBuilder $builder - * @param sbyte - * @return void - */ - public static function addColor(FlatBufferBuilder $builder, $color) - { - $builder->addSbyteX(0, $color, 2); - } - - /** - * @param FlatBufferBuilder $builder - * @return int table offset - */ - public static function endTestSimpleTableWithEnum(FlatBufferBuilder $builder) - { - $o = $builder->endObject(); - return $o; - } -} diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.py b/tests/MyGame/Example/TestSimpleTableWithEnum.py deleted file mode 100644 index 7085995be7..0000000000 --- a/tests/MyGame/Example/TestSimpleTableWithEnum.py +++ /dev/null @@ -1,23 +0,0 @@ -# automatically generated, do not modify - -# namespace: Example - -import flatbuffers - -class TestSimpleTableWithEnum(object): - __slots__ = ['_tab'] - - # TestSimpleTableWithEnum - def Init(self, buf, pos): - self._tab = flatbuffers.table.Table(buf, pos) - - # TestSimpleTableWithEnum - def Color(self): - o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) - if o != 0: - return self._tab.Get(flatbuffers.number_types.Int8Flags, o + self._tab.Pos) - return 2 - -def TestSimpleTableWithEnumStart(builder): builder.StartObject(1) -def TestSimpleTableWithEnumAddColor(builder, color): builder.PrependInt8Slot(0, color, 2) -def TestSimpleTableWithEnumEnd(builder): return builder.EndObject() diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.rs b/tests/MyGame/Example/TestSimpleTableWithEnum.rs index 6a2248446d..0e1ea8bfa8 100644 --- a/tests/MyGame/Example/TestSimpleTableWithEnum.rs +++ b/tests/MyGame/Example/TestSimpleTableWithEnum.rs @@ -3,8 +3,11 @@ use flatbuffers; use super::*; -table_object!{TestSimpleTableWithEnum, 4, [ - (color,simple_enum,get_i8, i8, Color, 4, 2)]} +flatbuffers_object!{Table => TestSimpleTableWithEnum [ + field => { name = color, + typeOf = enum Color i8, + slot = 4, + default = 2 }]} /// Builder Trait for `TestSimpleTableWithEnum` tables. pub trait TestSimpleTableWithEnumBuilder { diff --git a/tests/MyGame/Example/Vec3.cs b/tests/MyGame/Example/Vec3.cs deleted file mode 100644 index e5fa2f674e..0000000000 --- a/tests/MyGame/Example/Vec3.cs +++ /dev/null @@ -1,44 +0,0 @@ -// automatically generated, do not modify - -namespace MyGame.Example -{ - -using System; -using FlatBuffers; - -public sealed class Vec3 : Struct { - public Vec3 __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } - - public float X { get { return bb.GetFloat(bb_pos + 0); } } - public void MutateX(float x) { bb.PutFloat(bb_pos + 0, x); } - public float Y { get { return bb.GetFloat(bb_pos + 4); } } - public void MutateY(float y) { bb.PutFloat(bb_pos + 4, y); } - public float Z { get { return bb.GetFloat(bb_pos + 8); } } - public void MutateZ(float z) { bb.PutFloat(bb_pos + 8, z); } - public double Test1 { get { return bb.GetDouble(bb_pos + 16); } } - public void MutateTest1(double test1) { bb.PutDouble(bb_pos + 16, test1); } - public Color Test2 { get { return (Color)bb.GetSbyte(bb_pos + 24); } } - public void MutateTest2(Color test2) { bb.PutSbyte(bb_pos + 24, (sbyte)test2); } - public Test Test3 { get { return GetTest3(new Test()); } } - public Test GetTest3(Test obj) { return obj.__init(bb_pos + 26, bb); } - - public static Offset CreateVec3(FlatBufferBuilder builder, float X, float Y, float Z, double Test1, Color Test2, short test3_A, sbyte test3_B) { - builder.Prep(16, 32); - builder.Pad(2); - builder.Prep(2, 4); - builder.Pad(1); - builder.PutSbyte(test3_B); - builder.PutShort(test3_A); - builder.Pad(1); - builder.PutSbyte((sbyte)Test2); - builder.PutDouble(Test1); - builder.Pad(4); - builder.PutFloat(Z); - builder.PutFloat(Y); - builder.PutFloat(X); - return new Offset(builder.Offset); - } -}; - - -} diff --git a/tests/MyGame/Example/Vec3.java b/tests/MyGame/Example/Vec3.java deleted file mode 100644 index 86edb6dc5b..0000000000 --- a/tests/MyGame/Example/Vec3.java +++ /dev/null @@ -1,44 +0,0 @@ -// automatically generated, do not modify - -package MyGame.Example; - -import java.nio.*; -import java.lang.*; -import java.util.*; -import com.google.flatbuffers.*; - -@SuppressWarnings("unused") -public final class Vec3 extends Struct { - public Vec3 __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } - - public float x() { return bb.getFloat(bb_pos + 0); } - public void mutateX(float x) { bb.putFloat(bb_pos + 0, x); } - public float y() { return bb.getFloat(bb_pos + 4); } - public void mutateY(float y) { bb.putFloat(bb_pos + 4, y); } - public float z() { return bb.getFloat(bb_pos + 8); } - public void mutateZ(float z) { bb.putFloat(bb_pos + 8, z); } - public double test1() { return bb.getDouble(bb_pos + 16); } - public void mutateTest1(double test1) { bb.putDouble(bb_pos + 16, test1); } - public byte test2() { return bb.get(bb_pos + 24); } - public void mutateTest2(byte test2) { bb.put(bb_pos + 24, test2); } - public Test test3() { return test3(new Test()); } - public Test test3(Test obj) { return obj.__init(bb_pos + 26, bb); } - - public static int createVec3(FlatBufferBuilder builder, float x, float y, float z, double test1, byte test2, short test3_a, byte test3_b) { - builder.prep(16, 32); - builder.pad(2); - builder.prep(2, 4); - builder.pad(1); - builder.putByte(test3_b); - builder.putShort(test3_a); - builder.pad(1); - builder.putByte(test2); - builder.putDouble(test1); - builder.pad(4); - builder.putFloat(z); - builder.putFloat(y); - builder.putFloat(x); - return builder.offset(); - } -}; - diff --git a/tests/MyGame/Example/Vec3.php b/tests/MyGame/Example/Vec3.php deleted file mode 100644 index 022254ce9c..0000000000 --- a/tests/MyGame/Example/Vec3.php +++ /dev/null @@ -1,96 +0,0 @@ -bb_pos = $_i; - $this->bb = $_bb; - return $this; - } - - /** - * @return float - */ - public function GetX() - { - return $this->bb->getFloat($this->bb_pos + 0); - } - - /** - * @return float - */ - public function GetY() - { - return $this->bb->getFloat($this->bb_pos + 4); - } - - /** - * @return float - */ - public function GetZ() - { - return $this->bb->getFloat($this->bb_pos + 8); - } - - /** - * @return double - */ - public function GetTest1() - { - return $this->bb->getDouble($this->bb_pos + 16); - } - - /** - * @return sbyte - */ - public function GetTest2() - { - return $this->bb->getSbyte($this->bb_pos + 24); - } - - /** - * @return Test - */ - public function getTest3() - { - $obj = new Test(); - $obj->init($this->bb_pos + 26, $this->bb); - return $obj; - } - - - /** - * @return int offset - */ - public static function createVec3(FlatBufferBuilder $builder, $x, $y, $z, $test1, $test2, $test3_a, $test3_b) - { - $builder->prep(16, 32); - $builder->pad(2); - $builder->prep(2, 4); - $builder->pad(1); - $builder->putSbyte($test3_b); - $builder->putShort($test3_a); - $builder->pad(1); - $builder->putSbyte($test2); - $builder->putDouble($test1); - $builder->pad(4); - $builder->putFloat($z); - $builder->putFloat($y); - $builder->putFloat($x); - return $builder->offset(); - } -} diff --git a/tests/MyGame/Example/Vec3.py b/tests/MyGame/Example/Vec3.py deleted file mode 100644 index c4ddfe230c..0000000000 --- a/tests/MyGame/Example/Vec3.py +++ /dev/null @@ -1,44 +0,0 @@ -# automatically generated, do not modify - -# namespace: Example - -import flatbuffers - -class Vec3(object): - __slots__ = ['_tab'] - - # Vec3 - def Init(self, buf, pos): - self._tab = flatbuffers.table.Table(buf, pos) - - # Vec3 - def X(self): return self._tab.Get(flatbuffers.number_types.Float32Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(0)) - # Vec3 - def Y(self): return self._tab.Get(flatbuffers.number_types.Float32Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(4)) - # Vec3 - def Z(self): return self._tab.Get(flatbuffers.number_types.Float32Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(8)) - # Vec3 - def Test1(self): return self._tab.Get(flatbuffers.number_types.Float64Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(16)) - # Vec3 - def Test2(self): return self._tab.Get(flatbuffers.number_types.Int8Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(24)) - # Vec3 - def Test3(self, obj): - obj.Init(self._tab.Bytes, self._tab.Pos + 26) - return obj - - -def CreateVec3(builder, x, y, z, test1, test2, test3_a, test3_b): - builder.Prep(16, 32) - builder.Pad(2) - builder.Prep(2, 4) - builder.Pad(1) - builder.PrependInt8(test3_b) - builder.PrependInt16(test3_a) - builder.Pad(1) - builder.PrependInt8(test2) - builder.PrependFloat64(test1) - builder.Pad(4) - builder.PrependFloat32(z) - builder.PrependFloat32(y) - builder.PrependFloat32(x) - return builder.Offset() diff --git a/tests/MyGame/Example/Vec3.rs b/tests/MyGame/Example/Vec3.rs index 65adddf354..ea595584d5 100644 --- a/tests/MyGame/Example/Vec3.rs +++ b/tests/MyGame/Example/Vec3.rs @@ -3,13 +3,33 @@ use flatbuffers; use super::*; -struct_object!{Vec3, 32, [ - (x,get_f32, f32, 0, 0.0), - (y,get_f32, f32, 4, 0.0), - (z,get_f32, f32, 8, 0.0), - (test1,get_f64, f64, 16, 0.0), - (test2,simple_enum,get_i8, i8, Color, 24, 0), - (test3,get_struct, Test, 26)]} +flatbuffers_object!{Struct => Vec3 ( size:32, align: 16) [ + field => { name = x, + typeOf = f32, + slot = 0, + default = 0.0 }, + field => { name = y, + typeOf = f32, + slot = 4, + default = 0.0 }, + field => { name = z, + typeOf = f32, + slot = 8, + default = 0.0, + padding = 4 }, + field => { name = test1, + typeOf = f64, + slot = 16, + default = 0.0 }, + field => { name = test2, + typeOf = enum Color i8, + slot = 24, + default = 0, + padding = 1 }, + field => { name = test3, + typeOf = Test, + slot = 26, + padding = 2 }]} pub trait Vec3Builder { fn build_vec3(&mut self, x: f32, y: f32, z: f32, test1: f64, test2: i8, test3_a: i16, test3_b: i8) -> flatbuffers::UOffsetT; diff --git a/tests/MyGame/Example/__init__.py b/tests/MyGame/Example/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/MyGame/__init__.py b/tests/MyGame/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/tests/RustTest.sh b/tests/RustTest.sh index d2f57ebf2f..84430efb22 100755 --- a/tests/RustTest.sh +++ b/tests/RustTest.sh @@ -29,6 +29,8 @@ fi ${sync_cmd} MyGame/Example/*.rs ${rust_src}/bin/test/MyGame/Example/ ${sync_cmd} MyGame/*.rs ${rust_src}/bin/test/MyGame/ ${sync_cmd} ../rust/* ${rust_path} +${sync_cmd} ../rust/macros/* ${rust_path}/macros +#{sync_cmd} ../rust/macros/src/* ${rust_path}/macros/src ${sync_cmd} ../rust/src/* ${rust_src} ${sync_cmd} ../rust/src/bin/* ${rust_src}/bin/ cp *.mon ${rust_path}/ From 772616425066aa31fa9895334befcae11be89a4b Mon Sep 17 00:00:00 2001 From: Hollin Wilkins Date: Wed, 23 Aug 2017 22:26:35 -0700 Subject: [PATCH 7/7] Fix to GenerateRust. --- src/flatc_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flatc_main.cpp b/src/flatc_main.cpp index 79ef297e75..0231312adc 100644 --- a/src/flatc_main.cpp +++ b/src/flatc_main.cpp @@ -101,7 +101,7 @@ int main(int argc, const char *argv[]) { flatbuffers::IDLOptions::kJsonSchema, "Generate Json schema", flatbuffers::GeneralMakeRule }, - { flatbuffers::GenerateJsonSchema, "-r", "--rust", "Rust", true, + { flatbuffers::GenerateRust, "-r", "--rust", "Rust", true, nullptr, flatbuffers::IDLOptions::kRust, "Generate Rust files for tables/structs",