Optional Scalars support for Rust (#6034)

* First draft of rust optionals

* Code cleanup around ftBool and ftVectorOfBool

* Tests for Rust optional scalars

* test bools too

Co-authored-by: Casper Neo <cneo@google.com>
This commit is contained in:
Casper
2020-07-23 16:30:27 -07:00
committed by GitHub
parent c8fa0afdfc
commit 043b52bd4a
12 changed files with 626 additions and 59 deletions

View File

@@ -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;

View File

@@ -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_ +=

View File

@@ -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 {

View File

@@ -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

View File

@@ -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

View File

@@ -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,

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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" }

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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);