diff options
-rw-r--r-- | rust/flexbuffers/src/lib.rs | 1 | ||||
-rw-r--r-- | src/idl_gen_rust.cpp | 86 | ||||
-rw-r--r-- | src/idl_parser.cpp | 2 | ||||
-rw-r--r-- | tests/generate_code.bat | 3 | ||||
-rwxr-xr-x | tests/generate_code.sh | 3 | ||||
-rw-r--r-- | tests/monster_test_generated.rs | 2 | ||||
-rw-r--r-- | tests/optional_scalars.fbs | 44 | ||||
-rw-r--r-- | tests/optional_scalars_generated.rs | 481 | ||||
-rw-r--r-- | tests/rust_usage_test/Cargo.toml | 4 | ||||
-rw-r--r-- | tests/rust_usage_test/tests/integration_test.rs | 5 | ||||
-rw-r--r-- | tests/rust_usage_test/tests/optional_scalars_test.rs | 52 | ||||
-rw-r--r-- | tests/test.cpp | 2 |
12 files changed, 626 insertions, 59 deletions
diff --git a/rust/flexbuffers/src/lib.rs b/rust/flexbuffers/src/lib.rs index 482e15cd..20983b79 100644 --- a/rust/flexbuffers/src/lib.rs +++ b/rust/flexbuffers/src/lib.rs @@ -33,7 +33,6 @@ extern crate bitflags; extern crate byteorder; #[macro_use] extern crate serde_derive; -#[macro_use] extern crate num_enum; extern crate serde; diff --git a/src/idl_gen_rust.cpp b/src/idl_gen_rust.cpp index 45d5faff..8cdf647f 100644 --- a/src/idl_gen_rust.cpp +++ b/src/idl_gen_rust.cpp @@ -661,22 +661,15 @@ class RustGenerator : public BaseGenerator { return "VT_" + MakeUpper(Name(field)); } - std::string GetDefaultConstant(const FieldDef &field) { - return field.value.type.base_type == BASE_TYPE_FLOAT - ? field.value.constant + "" - : field.value.constant; - } - std::string GetDefaultScalarValue(const FieldDef &field) { switch (GetFullType(field.value.type)) { - case ftInteger: { - return GetDefaultConstant(field); - } + case ftInteger: case ftFloat: { - return GetDefaultConstant(field); + return field.nullable ? "None" : field.value.constant; } case ftBool: { - return field.value.constant == "0" ? "false" : "true"; + return field.nullable ? "None" : + field.value.constant == "0" ? "false" : "true"; } case ftUnionKey: case ftEnumKey: { @@ -714,7 +707,7 @@ class RustGenerator : public BaseGenerator { case ftFloat: case ftBool: { const auto typname = GetTypeBasic(type); - return typname; + return field.nullable ? "Option<" + typname + ">" : typname; } case ftStruct: { const auto typname = WrapInNameSpace(*type.struct_def); @@ -738,14 +731,12 @@ class RustGenerator : public BaseGenerator { } case ftVectorOfInteger: + case ftVectorOfBool: case ftVectorOfFloat: { const auto typname = GetTypeBasic(type.VectorType()); return "Option<flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime + ", " + typname + ">>>"; - } - case ftVectorOfBool: { - return "Option<flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime + - ", bool>>>"; + // TODO(cneo): Fix whitespace in generated code. } case ftVectorOfEnumKey: { const auto typname = WrapInNameSpace(*type.enum_def); @@ -815,15 +806,12 @@ class RustGenerator : public BaseGenerator { ">>>>"; } case ftVectorOfInteger: + case ftVectorOfBool: case ftVectorOfFloat: { const auto typname = GetTypeBasic(type.VectorType()); return "flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime + ", " + typname + ">>"; } - case ftVectorOfBool: { - return "flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime + - ", bool>>"; - } case ftVectorOfString: { return "flatbuffers::WIPOffset<flatbuffers::Vector<" + lifetime + ", flatbuffers::ForwardsUOffset<&" + lifetime + " str>>>"; @@ -851,12 +839,9 @@ class RustGenerator : public BaseGenerator { return "flatbuffers::WIPOffset<" + typname + "<" + lifetime + ">>"; } case ftInteger: + case ftBool: case ftFloat: { - const auto typname = GetTypeBasic(type); - return typname; - } - case ftBool: { - return "bool"; + return GetTypeBasic(type); } case ftString: { return "flatbuffers::WIPOffset<&" + lifetime + " str>"; @@ -878,14 +863,13 @@ class RustGenerator : public BaseGenerator { switch (GetFullType(field.value.type)) { case ftInteger: + case ftBool: case ftFloat: { const auto typname = GetTypeBasic(field.value.type); - return "self.fbb_.push_slot::<" + typname + ">"; + return (field.nullable ? + "self.fbb_.push_slot_always::<" : + "self.fbb_.push_slot::<") + typname + ">"; } - case ftBool: { - return "self.fbb_.push_slot::<bool>"; - } - case ftEnumKey: case ftUnionKey: { const auto underlying_typname = GetTypeBasic(type); @@ -924,12 +908,10 @@ class RustGenerator : public BaseGenerator { switch (GetFullType(field.value.type)) { case ftInteger: - case ftFloat: { - const auto typname = GetTypeBasic(type); - return typname; - } + case ftFloat: case ftBool: { - return "bool"; + const auto typname = GetTypeBasic(type); + return field.nullable ? "Option<" + typname + ">" : typname; } case ftStruct: { const auto typname = WrapInNameSpace(*type.struct_def); @@ -956,6 +938,7 @@ class RustGenerator : public BaseGenerator { field.required); } case ftVectorOfInteger: + case ftVectorOfBool: case ftVectorOfFloat: { const auto typname = GetTypeBasic(type.VectorType()); if (IsOneByte(type.VectorType().base_type)) { @@ -966,10 +949,6 @@ class RustGenerator : public BaseGenerator { "flatbuffers::Vector<" + lifetime + ", " + typname + ">", field.required); } - case ftVectorOfBool: { - return WrapInOptionIfNotRequired("&" + lifetime + " [bool]", - field.required); - } case ftVectorOfEnumKey: { const auto typname = WrapInNameSpace(*type.enum_def); return WrapInOptionIfNotRequired( @@ -1016,9 +995,13 @@ class RustGenerator : public BaseGenerator { case ftFloat: case ftBool: { const auto typname = GetTypeBasic(type); - const auto default_value = GetDefaultScalarValue(field); - return "self._tab.get::<" + typname + ">(" + offset_name + ", Some(" + - default_value + ")).unwrap()"; + if (field.nullable) { + return "self._tab.get::<" + typname + ">(" + offset_name + ", None)"; + } else { + const auto default_value = GetDefaultScalarValue(field); + return "self._tab.get::<" + typname + ">(" + offset_name + ", Some(" + + default_value + ")).unwrap()"; + } } case ftStruct: { const auto typname = WrapInNameSpace(*type.struct_def); @@ -1056,6 +1039,7 @@ class RustGenerator : public BaseGenerator { } case ftVectorOfInteger: + case ftVectorOfBool: case ftVectorOfFloat: { const auto typname = GetTypeBasic(type.VectorType()); std::string s = @@ -1068,14 +1052,6 @@ class RustGenerator : public BaseGenerator { } return AddUnwrapIfRequired(s, field.required); } - case ftVectorOfBool: { - return AddUnwrapIfRequired( - "self._tab.get::<flatbuffers::ForwardsUOffset<" - "flatbuffers::Vector<" + - lifetime + ", bool>>>(" + offset_name + - ", None).map(|v| v.safe_slice())", - field.required); - } case ftVectorOfEnumKey: { const auto typname = WrapInNameSpace(*type.enum_def); return AddUnwrapIfRequired( @@ -1116,8 +1092,9 @@ class RustGenerator : public BaseGenerator { return "INVALID_CODE_GENERATION"; // for return analysis } - bool TableFieldReturnsOption(const Type &type) { - switch (GetFullType(type)) { + bool TableFieldReturnsOption(const FieldDef &field) { + if (field.nullable) return true; + switch (GetFullType(field.value.type)) { case ftInteger: case ftFloat: case ftBool: @@ -1205,7 +1182,7 @@ class RustGenerator : public BaseGenerator { if (!field.deprecated && (!struct_def.sortbysize || size == SizeOf(field.value.type.base_type))) { code_.SetValue("FIELD_NAME", Name(field)); - if (TableFieldReturnsOption(field.value.type)) { + if (TableFieldReturnsOption(field)) { code_ += " if let Some(x) = args.{{FIELD_NAME}} " "{ builder.add_{{FIELD_NAME}}(x); }"; @@ -1421,7 +1398,6 @@ class RustGenerator : public BaseGenerator { const auto &field = **it; if (!field.deprecated) { const bool is_scalar = IsScalar(field.value.type.base_type); - std::string offset = GetFieldOffsetName(field); // Generate functions to add data, which take one of two forms. @@ -1443,7 +1419,7 @@ class RustGenerator : public BaseGenerator { code_ += " pub fn add_{{FIELD_NAME}}(&mut self, {{FIELD_NAME}}: " "{{FIELD_TYPE}}) {"; - if (is_scalar) { + if (is_scalar && !field.nullable) { code_.SetValue("FIELD_DEFAULT_VALUE", TableBuilderAddFuncDefaultValue(field)); code_ += diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 5ccd690d..eabf783c 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -2258,7 +2258,7 @@ CheckedError Parser::CheckClash(std::vector<FieldDef *> &fields, bool Parser::SupportsNullableScalars() const { - return opts.lang_to_generate == 0; // No support yet. + return !(opts.lang_to_generate & ~IDLOptions::kRust); } bool Parser::SupportsAdvancedUnionFeatures() const { diff --git a/tests/generate_code.bat b/tests/generate_code.bat index 6954c6b7..05c58ba4 100644 --- a/tests/generate_code.bat +++ b/tests/generate_code.bat @@ -53,6 +53,9 @@ set TEST_NOINCL_FLAGS=%TEST_BASE_FLAGS% --no-includes --no-fb-import ..\%buildtype%\flatc.exe --python %TEST_BASE_FLAGS% arrays_test.fbs || goto FAIL ..\%buildtype%\flatc.exe --cpp %TEST_BASE_FLAGS% --cpp-ptr-type flatbuffers::unique_ptr native_type_test.fbs || goto FAIL +@rem Generate the optional scalar code for tests. +..\%buildtype%\flatc.exe --rust optional_scalars.fbs || goto FAIL + @rem Generate the schema evolution tests ..\%buildtype%\flatc.exe --cpp --scoped-enums %TEST_CPP_FLAGS% -o evolution_test ./evolution_test/evolution_v1.fbs ./evolution_test/evolution_v2.fbs || goto FAIL diff --git a/tests/generate_code.sh b/tests/generate_code.sh index 0b3e1343..df583c3e 100755 --- a/tests/generate_code.sh +++ b/tests/generate_code.sh @@ -51,6 +51,9 @@ $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS -o namespace_test namespace_te ../flatc --python $TEST_BASE_FLAGS arrays_test.fbs ../flatc --dart monster_extra.fbs +# Generate optional scalar code for tests. +../flatc --rust optional_scalars.fbs + # Generate the schema evolution tests ../flatc --cpp --scoped-enums $TEST_CPP_FLAGS -o evolution_test ./evolution_test/evolution_v*.fbs diff --git a/tests/monster_test_generated.rs b/tests/monster_test_generated.rs index 528505c3..43fe7278 100644 --- a/tests/monster_test_generated.rs +++ b/tests/monster_test_generated.rs @@ -1488,7 +1488,7 @@ pub struct MonsterArgs<'a> { pub testhashu32_fnv1a: u32, pub testhashs64_fnv1a: i64, pub testhashu64_fnv1a: u64, - pub testarrayofbools: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a , bool>>>, + pub testarrayofbools: Option<flatbuffers::WIPOffset<flatbuffers::Vector<'a , bool>>>, pub testf: f32, pub testf2: f32, pub testf3: f32, diff --git a/tests/optional_scalars.fbs b/tests/optional_scalars.fbs new file mode 100644 index 00000000..051bae31 --- /dev/null +++ b/tests/optional_scalars.fbs @@ -0,0 +1,44 @@ +namespace optional_scalars; + +// This table tests optional scalars in tables. It should be integrated with +// the main monster test once most languages support optional scalars. +table ScalarStuff { + just_i8: int8; + maybe_i8: int8 = null; + default_i8: int8 = 42; + just_u8: uint8; + maybe_u8: uint8 = null; + default_u8: uint8 = 42; + + just_i16: int16; + maybe_i16: int16 = null; + default_i16: int16 = 42; + just_u16: uint16; + maybe_u16: uint16 = null; + default_u16: uint16 = 42; + + just_i32: int32; + maybe_i32: int32 = null; + default_i32: int32 = 42; + just_u32: uint32; + maybe_u32: uint32 = null; + default_u32: uint32 = 42; + + just_i64: int64; + maybe_i64: int64 = null; + default_i64: int64 = 42; + just_u64: uint64; + maybe_u64: uint64 = null; + default_u64: uint64 = 42; + + just_f32: float32; + maybe_f32: float32 = null; + default_f32: float32 = 42; + just_f64: float64; + maybe_f64: float64 = null; + default_f64: float64 = 42; + + just_bool: bool; + maybe_bool: bool = null; + default_bool: bool = true; +} diff --git a/tests/optional_scalars_generated.rs b/tests/optional_scalars_generated.rs new file mode 100644 index 00000000..78ee8560 --- /dev/null +++ b/tests/optional_scalars_generated.rs @@ -0,0 +1,481 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + + +use std::mem; +use std::cmp::Ordering; + +extern crate flatbuffers; +use self::flatbuffers::EndianScalar; + +#[allow(unused_imports, dead_code)] +pub mod optional_scalars { + + use std::mem; + use std::cmp::Ordering; + + extern crate flatbuffers; + use self::flatbuffers::EndianScalar; + +pub enum ScalarStuffOffset {} +#[derive(Copy, Clone, Debug, PartialEq)] + +pub struct ScalarStuff<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for ScalarStuff<'a> { + type Inner = ScalarStuff<'a>; + #[inline] + fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { + _tab: flatbuffers::Table { buf: buf, loc: loc }, + } + } +} + +impl<'a> ScalarStuff<'a> { + #[inline] + pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + ScalarStuff { + _tab: table, + } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>, + args: &'args ScalarStuffArgs) -> flatbuffers::WIPOffset<ScalarStuff<'bldr>> { + let mut builder = ScalarStuffBuilder::new(_fbb); + builder.add_default_f64(args.default_f64); + if let Some(x) = args.maybe_f64 { builder.add_maybe_f64(x); } + builder.add_just_f64(args.just_f64); + builder.add_default_u64(args.default_u64); + if let Some(x) = args.maybe_u64 { builder.add_maybe_u64(x); } + builder.add_just_u64(args.just_u64); + builder.add_default_i64(args.default_i64); + if let Some(x) = args.maybe_i64 { builder.add_maybe_i64(x); } + builder.add_just_i64(args.just_i64); + builder.add_default_f32(args.default_f32); + if let Some(x) = args.maybe_f32 { builder.add_maybe_f32(x); } + builder.add_just_f32(args.just_f32); + builder.add_default_u32(args.default_u32); + if let Some(x) = args.maybe_u32 { builder.add_maybe_u32(x); } + builder.add_just_u32(args.just_u32); + builder.add_default_i32(args.default_i32); + if let Some(x) = args.maybe_i32 { builder.add_maybe_i32(x); } + builder.add_just_i32(args.just_i32); + builder.add_default_u16(args.default_u16); + if let Some(x) = args.maybe_u16 { builder.add_maybe_u16(x); } + builder.add_just_u16(args.just_u16); + builder.add_default_i16(args.default_i16); + if let Some(x) = args.maybe_i16 { builder.add_maybe_i16(x); } + builder.add_just_i16(args.just_i16); + builder.add_default_bool(args.default_bool); + if let Some(x) = args.maybe_bool { builder.add_maybe_bool(x); } + builder.add_just_bool(args.just_bool); + builder.add_default_u8(args.default_u8); + if let Some(x) = args.maybe_u8 { builder.add_maybe_u8(x); } + builder.add_just_u8(args.just_u8); + builder.add_default_i8(args.default_i8); + if let Some(x) = args.maybe_i8 { builder.add_maybe_i8(x); } + builder.add_just_i8(args.just_i8); + builder.finish() + } + + pub const VT_JUST_I8: flatbuffers::VOffsetT = 4; + pub const VT_MAYBE_I8: flatbuffers::VOffsetT = 6; + pub const VT_DEFAULT_I8: flatbuffers::VOffsetT = 8; + pub const VT_JUST_U8: flatbuffers::VOffsetT = 10; + pub const VT_MAYBE_U8: flatbuffers::VOffsetT = 12; + pub const VT_DEFAULT_U8: flatbuffers::VOffsetT = 14; + pub const VT_JUST_I16: flatbuffers::VOffsetT = 16; + pub const VT_MAYBE_I16: flatbuffers::VOffsetT = 18; + pub const VT_DEFAULT_I16: flatbuffers::VOffsetT = 20; + pub const VT_JUST_U16: flatbuffers::VOffsetT = 22; + pub const VT_MAYBE_U16: flatbuffers::VOffsetT = 24; + pub const VT_DEFAULT_U16: flatbuffers::VOffsetT = 26; + pub const VT_JUST_I32: flatbuffers::VOffsetT = 28; + pub const VT_MAYBE_I32: flatbuffers::VOffsetT = 30; + pub const VT_DEFAULT_I32: flatbuffers::VOffsetT = 32; + pub const VT_JUST_U32: flatbuffers::VOffsetT = 34; + pub const VT_MAYBE_U32: flatbuffers::VOffsetT = 36; + pub const VT_DEFAULT_U32: flatbuffers::VOffsetT = 38; + pub const VT_JUST_I64: flatbuffers::VOffsetT = 40; + pub const VT_MAYBE_I64: flatbuffers::VOffsetT = 42; + pub const VT_DEFAULT_I64: flatbuffers::VOffsetT = 44; + pub const VT_JUST_U64: flatbuffers::VOffsetT = 46; + pub const VT_MAYBE_U64: flatbuffers::VOffsetT = 48; + pub const VT_DEFAULT_U64: flatbuffers::VOffsetT = 50; + pub const VT_JUST_F32: flatbuffers::VOffsetT = 52; + pub const VT_MAYBE_F32: flatbuffers::VOffsetT = 54; + pub const VT_DEFAULT_F32: flatbuffers::VOffsetT = 56; + pub const VT_JUST_F64: flatbuffers::VOffsetT = 58; + pub const VT_MAYBE_F64: flatbuffers::VOffsetT = 60; + pub const VT_DEFAULT_F64: flatbuffers::VOffsetT = 62; + pub const VT_JUST_BOOL: flatbuffers::VOffsetT = 64; + pub const VT_MAYBE_BOOL: flatbuffers::VOffsetT = 66; + pub const VT_DEFAULT_BOOL: flatbuffers::VOffsetT = 68; + + #[inline] + pub fn just_i8(&self) -> i8 { + self._tab.get::<i8>(ScalarStuff::VT_JUST_I8, Some(0)).unwrap() + } + #[inline] + pub fn maybe_i8(&self) -> Option<i8> { + self._tab.get::<i8>(ScalarStuff::VT_MAYBE_I8, None) + } + #[inline] + pub fn default_i8(&self) -> i8 { + self._tab.get::<i8>(ScalarStuff::VT_DEFAULT_I8, Some(42)).unwrap() + } + #[inline] + pub fn just_u8(&self) -> u8 { + self._tab.get::<u8>(ScalarStuff::VT_JUST_U8, Some(0)).unwrap() + } + #[inline] + pub fn maybe_u8(&self) -> Option<u8> { + self._tab.get::<u8>(ScalarStuff::VT_MAYBE_U8, None) + } + #[inline] + pub fn default_u8(&self) -> u8 { + self._tab.get::<u8>(ScalarStuff::VT_DEFAULT_U8, Some(42)).unwrap() + } + #[inline] + pub fn just_i16(&self) -> i16 { + self._tab.get::<i16>(ScalarStuff::VT_JUST_I16, Some(0)).unwrap() + } + #[inline] + pub fn maybe_i16(&self) -> Option<i16> { + self._tab.get::<i16>(ScalarStuff::VT_MAYBE_I16, None) + } + #[inline] + pub fn default_i16(&self) -> i16 { + self._tab.get::<i16>(ScalarStuff::VT_DEFAULT_I16, Some(42)).unwrap() + } + #[inline] + pub fn just_u16(&self) -> u16 { + self._tab.get::<u16>(ScalarStuff::VT_JUST_U16, Some(0)).unwrap() + } + #[inline] + pub fn maybe_u16(&self) -> Option<u16> { + self._tab.get::<u16>(ScalarStuff::VT_MAYBE_U16, None) + } + #[inline] + pub fn default_u16(&self) -> u16 { + self._tab.get::<u16>(ScalarStuff::VT_DEFAULT_U16, Some(42)).unwrap() + } + #[inline] + pub fn just_i32(&self) -> i32 { + self._tab.get::<i32>(ScalarStuff::VT_JUST_I32, Some(0)).unwrap() + } + #[inline] + pub fn maybe_i32(&self) -> Option<i32> { + self._tab.get::<i32>(ScalarStuff::VT_MAYBE_I32, None) + } + #[inline] + pub fn default_i32(&self) -> i32 { + self._tab.get::<i32>(ScalarStuff::VT_DEFAULT_I32, Some(42)).unwrap() + } + #[inline] + pub fn just_u32(&self) -> u32 { + self._tab.get::<u32>(ScalarStuff::VT_JUST_U32, Some(0)).unwrap() + } + #[inline] + pub fn maybe_u32(&self) -> Option<u32> { + self._tab.get::<u32>(ScalarStuff::VT_MAYBE_U32, None) + } + #[inline] + pub fn default_u32(&self) -> u32 { + self._tab.get::<u32>(ScalarStuff::VT_DEFAULT_U32, Some(42)).unwrap() + } + #[inline] + pub fn just_i64(&self) -> i64 { + self._tab.get::<i64>(ScalarStuff::VT_JUST_I64, Some(0)).unwrap() + } + #[inline] + pub fn maybe_i64(&self) -> Option<i64> { + self._tab.get::<i64>(ScalarStuff::VT_MAYBE_I64, None) + } + #[inline] + pub fn default_i64(&self) -> i64 { + self._tab.get::<i64>(ScalarStuff::VT_DEFAULT_I64, Some(42)).unwrap() + } + #[inline] + pub fn just_u64(&self) -> u64 { + self._tab.get::<u64>(ScalarStuff::VT_JUST_U64, Some(0)).unwrap() + } + #[inline] + pub fn maybe_u64(&self) -> Option<u64> { + self._tab.get::<u64>(ScalarStuff::VT_MAYBE_U64, None) + } + #[inline] + pub fn default_u64(&self) -> u64 { + self._tab.get::<u64>(ScalarStuff::VT_DEFAULT_U64, Some(42)).unwrap() + } + #[inline] + pub fn just_f32(&self) -> f32 { + self._tab.get::<f32>(ScalarStuff::VT_JUST_F32, Some(0.0)).unwrap() + } + #[inline] + pub fn maybe_f32(&self) -> Option<f32> { + self._tab.get::<f32>(ScalarStuff::VT_MAYBE_F32, None) + } + #[inline] + pub fn default_f32(&self) -> f32 { + self._tab.get::<f32>(ScalarStuff::VT_DEFAULT_F32, Some(42.0)).unwrap() + } + #[inline] + pub fn just_f64(&self) -> f64 { + self._tab.get::<f64>(ScalarStuff::VT_JUST_F64, Some(0.0)).unwrap() + } + #[inline] + pub fn maybe_f64(&self) -> Option<f64> { + self._tab.get::<f64>(ScalarStuff::VT_MAYBE_F64, None) + } + #[inline] + pub fn default_f64(&self) -> f64 { + self._tab.get::<f64>(ScalarStuff::VT_DEFAULT_F64, Some(42.0)).unwrap() + } + #[inline] + pub fn just_bool(&self) -> bool { + self._tab.get::<bool>(ScalarStuff::VT_JUST_BOOL, Some(false)).unwrap() + } + #[inline] + pub fn maybe_bool(&self) -> Option<bool> { + self._tab.get::<bool>(ScalarStuff::VT_MAYBE_BOOL, None) + } + #[inline] + pub fn default_bool(&self) -> bool { + self._tab.get::<bool>(ScalarStuff::VT_DEFAULT_BOOL, Some(true)).unwrap() + } +} + +pub struct ScalarStuffArgs { + pub just_i8: i8, + pub maybe_i8: Option<i8>, + pub default_i8: i8, + pub just_u8: u8, + pub maybe_u8: Option<u8>, + pub default_u8: u8, + pub just_i16: i16, + pub maybe_i16: Option<i16>, + pub default_i16: i16, + pub just_u16: u16, + pub maybe_u16: Option<u16>, + pub default_u16: u16, + pub just_i32: i32, + pub maybe_i32: Option<i32>, + pub default_i32: i32, + pub just_u32: u32, + pub maybe_u32: Option<u32>, + pub default_u32: u32, + pub just_i64: i64, + pub maybe_i64: Option<i64>, + pub default_i64: i64, + pub just_u64: u64, + pub maybe_u64: Option<u64>, + pub default_u64: u64, + pub just_f32: f32, + pub maybe_f32: Option<f32>, + pub default_f32: f32, + pub just_f64: f64, + pub maybe_f64: Option<f64>, + pub default_f64: f64, + pub just_bool: bool, + pub maybe_bool: Option<bool>, + pub default_bool: bool, +} +impl<'a> Default for ScalarStuffArgs { + #[inline] + fn default() -> Self { + ScalarStuffArgs { + just_i8: 0, + maybe_i8: None, + default_i8: 42, + just_u8: 0, + maybe_u8: None, + default_u8: 42, + just_i16: 0, + maybe_i16: None, + default_i16: 42, + just_u16: 0, + maybe_u16: None, + default_u16: 42, + just_i32: 0, + maybe_i32: None, + default_i32: 42, + just_u32: 0, + maybe_u32: None, + default_u32: 42, + just_i64: 0, + maybe_i64: None, + default_i64: 42, + just_u64: 0, + maybe_u64: None, + default_u64: 42, + just_f32: 0.0, + maybe_f32: None, + default_f32: 42.0, + just_f64: 0.0, + maybe_f64: None, + default_f64: 42.0, + just_bool: false, + maybe_bool: None, + default_bool: true, + } + } +} +pub struct ScalarStuffBuilder<'a: 'b, 'b> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>, + start_: flatbuffers::WIPOffset<flatbuffers::TableUnfinishedWIPOffset>, +} +impl<'a: 'b, 'b> ScalarStuffBuilder<'a, 'b> { + #[inline] + pub fn add_just_i8(&mut self, just_i8: i8) { + self.fbb_.push_slot::<i8>(ScalarStuff::VT_JUST_I8, just_i8, 0); + } + #[inline] + pub fn add_maybe_i8(&mut self, maybe_i8: i8) { + self.fbb_.push_slot_always::<i8>(ScalarStuff::VT_MAYBE_I8, maybe_i8); + } + #[inline] + pub fn add_default_i8(&mut self, default_i8: i8) { + self.fbb_.push_slot::<i8>(ScalarStuff::VT_DEFAULT_I8, default_i8, 42); + } + #[inline] + pub fn add_just_u8(&mut self, just_u8: u8) { + self.fbb_.push_slot::<u8>(ScalarStuff::VT_JUST_U8, just_u8, 0); + } + #[inline] + pub fn add_maybe_u8(&mut self, maybe_u8: u8) { + self.fbb_.push_slot_always::<u8>(ScalarStuff::VT_MAYBE_U8, maybe_u8); + } + #[inline] + pub fn add_default_u8(&mut self, default_u8: u8) { + self.fbb_.push_slot::<u8>(ScalarStuff::VT_DEFAULT_U8, default_u8, 42); + } + #[inline] + pub fn add_just_i16(&mut self, just_i16: i16) { + self.fbb_.push_slot::<i16>(ScalarStuff::VT_JUST_I16, just_i16, 0); + } + #[inline] + pub fn add_maybe_i16(&mut self, maybe_i16: i16) { + self.fbb_.push_slot_always::<i16>(ScalarStuff::VT_MAYBE_I16, maybe_i16); + } + #[inline] + pub fn add_default_i16(&mut self, default_i16: i16) { + self.fbb_.push_slot::<i16>(ScalarStuff::VT_DEFAULT_I16, default_i16, 42); + } + #[inline] + pub fn add_just_u16(&mut self, just_u16: u16) { + self.fbb_.push_slot::<u16>(ScalarStuff::VT_JUST_U16, just_u16, 0); + } + #[inline] + pub fn add_maybe_u16(&mut self, maybe_u16: u16) { + self.fbb_.push_slot_always::<u16>(ScalarStuff::VT_MAYBE_U16, maybe_u16); + } + #[inline] + pub fn add_default_u16(&mut self, default_u16: u16) { + self.fbb_.push_slot::<u16>(ScalarStuff::VT_DEFAULT_U16, default_u16, 42); + } + #[inline] + pub fn add_just_i32(&mut self, just_i32: i32) { + self.fbb_.push_slot::<i32>(ScalarStuff::VT_JUST_I32, just_i32, 0); + } + #[inline] + pub fn add_maybe_i32(&mut self, maybe_i32: i32) { + self.fbb_.push_slot_always::<i32>(ScalarStuff::VT_MAYBE_I32, maybe_i32); + } + #[inline] + pub fn add_default_i32(&mut self, default_i32: i32) { + self.fbb_.push_slot::<i32>(ScalarStuff::VT_DEFAULT_I32, default_i32, 42); + } + #[inline] + pub fn add_just_u32(&mut self, just_u32: u32) { + self.fbb_.push_slot::<u32>(ScalarStuff::VT_JUST_U32, just_u32, 0); + } + #[inline] + pub fn add_maybe_u32(&mut self, maybe_u32: u32) { + self.fbb_.push_slot_always::<u32>(ScalarStuff::VT_MAYBE_U32, maybe_u32); + } + #[inline] + pub fn add_default_u32(&mut self, default_u32: u32) { + self.fbb_.push_slot::<u32>(ScalarStuff::VT_DEFAULT_U32, default_u32, 42); + } + #[inline] + pub fn add_just_i64(&mut self, just_i64: i64) { + self.fbb_.push_slot::<i64>(ScalarStuff::VT_JUST_I64, just_i64, 0); + } + #[inline] + pub fn add_maybe_i64(&mut self, maybe_i64: i64) { + self.fbb_.push_slot_always::<i64>(ScalarStuff::VT_MAYBE_I64, maybe_i64); + } + #[inline] + pub fn add_default_i64(&mut self, default_i64: i64) { + self.fbb_.push_slot::<i64>(ScalarStuff::VT_DEFAULT_I64, default_i64, 42); + } + #[inline] + pub fn add_just_u64(&mut self, just_u64: u64) { + self.fbb_.push_slot::<u64>(ScalarStuff::VT_JUST_U64, just_u64, 0); + } + #[inline] + pub fn add_maybe_u64(&mut self, maybe_u64: u64) { + self.fbb_.push_slot_always::<u64>(ScalarStuff::VT_MAYBE_U64, maybe_u64); + } + #[inline] + pub fn add_default_u64(&mut self, default_u64: u64) { + self.fbb_.push_slot::<u64>(ScalarStuff::VT_DEFAULT_U64, default_u64, 42); + } + #[inline] + pub fn add_just_f32(&mut self, just_f32: f32) { + self.fbb_.push_slot::<f32>(ScalarStuff::VT_JUST_F32, just_f32, 0.0); + } + #[inline] + pub fn add_maybe_f32(&mut self, maybe_f32: f32) { + self.fbb_.push_slot_always::<f32>(ScalarStuff::VT_MAYBE_F32, maybe_f32); + } + #[inline] + pub fn add_default_f32(&mut self, default_f32: f32) { + self.fbb_.push_slot::<f32>(ScalarStuff::VT_DEFAULT_F32, default_f32, 42.0); + } + #[inline] + pub fn add_just_f64(&mut self, just_f64: f64) { + self.fbb_.push_slot::<f64>(ScalarStuff::VT_JUST_F64, just_f64, 0.0); + } + #[inline] + pub fn add_maybe_f64(&mut self, maybe_f64: f64) { + self.fbb_.push_slot_always::<f64>(ScalarStuff::VT_MAYBE_F64, maybe_f64); + } + #[inline] + pub fn add_default_f64(&mut self, default_f64: f64) { + self.fbb_.push_slot::<f64>(ScalarStuff::VT_DEFAULT_F64, default_f64, 42.0); + } + #[inline] + pub fn add_just_bool(&mut self, just_bool: bool) { + self.fbb_.push_slot::<bool>(ScalarStuff::VT_JUST_BOOL, just_bool, false); + } + #[inline] + pub fn add_maybe_bool(&mut self, maybe_bool: bool) { + self.fbb_.push_slot_always::<bool>(ScalarStuff::VT_MAYBE_BOOL, maybe_bool); + } + #[inline] + pub fn add_default_bool(&mut self, default_bool: bool) { + self.fbb_.push_slot::<bool>(ScalarStuff::VT_DEFAULT_BOOL, default_bool, true); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> ScalarStuffBuilder<'a, 'b> { + let start = _fbb.start_table(); + ScalarStuffBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset<ScalarStuff<'a>> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +} // pub mod optional_scalars + diff --git a/tests/rust_usage_test/Cargo.toml b/tests/rust_usage_test/Cargo.toml index e6a5c1df..6fa98a9a 100644 --- a/tests/rust_usage_test/Cargo.toml +++ b/tests/rust_usage_test/Cargo.toml @@ -1,7 +1,9 @@ [package] name = "rust_usage_test" version = "0.1.0" -authors = ["Robert Winslow <hello@rwinslow.com>", "FlatBuffers Maintainers"] +authors = ["Robert Winslow <hello@rwinslow.com>", + "Casper Neo <cneo@google.com>", + "FlatBuffers Maintainers"] [dependencies] flatbuffers = { path = "../../rust/flatbuffers" } diff --git a/tests/rust_usage_test/tests/integration_test.rs b/tests/rust_usage_test/tests/integration_test.rs index 1aea51c6..b861cf03 100644 --- a/tests/rust_usage_test/tests/integration_test.rs +++ b/tests/rust_usage_test/tests/integration_test.rs @@ -27,6 +27,7 @@ extern crate serde_derive; extern crate quickcheck_derive; mod flexbuffers_tests; +mod optional_scalars_test; #[allow(dead_code, unused_imports)] #[path = "../../include_test/include_test1_generated.rs"] @@ -41,6 +42,10 @@ pub mod include_test2_generated; mod monster_test_generated; pub use monster_test_generated::my_game; +#[allow(dead_code, unused_imports)] +#[path = "../../optional_scalars_generated.rs"] +mod optional_scalars_generated; + #[rustfmt::skip] // TODO: Use standard rust formatting and remove dead code. #[allow(dead_code)] mod flatbuffers_tests { diff --git a/tests/rust_usage_test/tests/optional_scalars_test.rs b/tests/rust_usage_test/tests/optional_scalars_test.rs new file mode 100644 index 00000000..4b63de2e --- /dev/null +++ b/tests/rust_usage_test/tests/optional_scalars_test.rs @@ -0,0 +1,52 @@ +#[allow(dead_code, unused_imports)] +#[path = "../../optional_scalars_generated.rs"] +mod optional_scalars_generated; +use crate::optional_scalars_generated::optional_scalars::*; + +// There are 3 variants of scalars in tables - those specified with default=42, +// optional scalars, and those with nothing specified (implicitly default=0). +// This tests that you can read what you write. +macro_rules! make_test { + ( + $test_name: ident, + $just: ident, $default: ident, $maybe: ident, + $five: expr, $zero: expr, $fortytwo: expr + ) => { + #[test] + fn $test_name() { + let mut builder = flatbuffers::FlatBufferBuilder::new(); + // Test five makes sense when specified. + let ss = ScalarStuff::create(&mut builder, &ScalarStuffArgs { + $just: $five, + $default: $five, + $maybe: Some($five), + ..Default::default() + }); + builder.finish(ss, None); + + let s = flatbuffers::get_root::<ScalarStuff>(builder.finished_data()); + assert_eq!(s.$just(), $five); + assert_eq!(s.$default(), $five); + assert_eq!(s.$maybe(), Some($five)); + + // Test defaults are used when not specified. + let s = flatbuffers::get_root::<ScalarStuff>(&[0; 8]); + assert_eq!(s.$just(), $zero); + assert_eq!(s.$default(), $fortytwo); + assert_eq!(s.$maybe(), None); + } + + }; +} + +make_test!(optional_i8, just_i8, default_i8, maybe_i8, 5, 0, 42); +make_test!(optional_u8, just_u8, default_u8, maybe_u8, 5, 0, 42); +make_test!(optional_i16, just_i16, default_i16, maybe_i16, 5, 0, 42); +make_test!(optional_u16, just_u16, default_u16, maybe_u16, 5, 0, 42); +make_test!(optional_i32, just_i32, default_i32, maybe_i32, 5, 0, 42); +make_test!(optional_u32, just_u32, default_u32, maybe_u32, 5, 0, 42); +make_test!(optional_i64, just_i64, default_i64, maybe_i64, 5, 0, 42); +make_test!(optional_u64, just_u64, default_u64, maybe_u64, 5, 0, 42); +make_test!(optional_f32, just_f32, default_f32, maybe_f32, 5.0, 0.0, 42.0); +make_test!(optional_f64, just_f64, default_f64, maybe_f64, 5.0, 0.0, 42.0); +make_test!(optional_bool, just_bool, default_bool, maybe_bool, true, false, true); diff --git a/tests/test.cpp b/tests/test.cpp index b4a358c7..50e2902a 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -3457,9 +3457,11 @@ void NullableScalarsTest() { // Test if nullable scalars are allowed for each language. const int kNumLanguages = 17; + const auto supported = flatbuffers::IDLOptions::kRust; for (int lang=0; lang<kNumLanguages; lang++) { flatbuffers::IDLOptions opts; opts.lang_to_generate |= 1 << lang; + if (opts.lang_to_generate & supported) continue; for (auto schema = schemas.begin(); schema < schemas.end(); schema++) { const bool has_null = schema->find("null") != std::string::npos; flatbuffers::Parser parser(opts); |