Ruopt enum (#6156)

* Rust support for optional enums

* make optional_scalars2 for languages that support optional enums

Co-authored-by: Casper Neo <cneo@google.com>
This commit is contained in:
Casper
2020-10-02 10:30:39 -07:00
committed by GitHub
parent bbcc85fd4c
commit 8ec8322f09
6 changed files with 143 additions and 24 deletions

View File

@@ -673,6 +673,9 @@ class RustGenerator : public BaseGenerator {
}
case ftUnionKey:
case ftEnumKey: {
if (field.optional) {
return "None";
}
auto ev = field.value.type.enum_def->FindByValue(field.value.constant);
assert(ev);
return WrapInNameSpace(field.value.type.enum_def->defined_namespace,
@@ -724,7 +727,7 @@ class RustGenerator : public BaseGenerator {
case ftEnumKey:
case ftUnionKey: {
const auto typname = WrapInNameSpace(*type.enum_def);
return typname;
return field.optional ? "Option<" + typname + ">" : typname;
}
case ftUnionValue: {
return "Option<flatbuffers::WIPOffset<flatbuffers::UnionWIPOffset>>";
@@ -872,7 +875,9 @@ class RustGenerator : public BaseGenerator {
case ftEnumKey:
case ftUnionKey: {
const auto underlying_typname = GetTypeBasic(type);
return "self.fbb_.push_slot::<" + underlying_typname + ">";
return (field.optional ?
"self.fbb_.push_slot_always::<" :
"self.fbb_.push_slot::<") + underlying_typname + ">";
}
case ftStruct: {
@@ -925,7 +930,7 @@ class RustGenerator : public BaseGenerator {
case ftEnumKey:
case ftUnionKey: {
const auto typname = WrapInNameSpace(*type.enum_def);
return typname;
return field.optional ? "Option<" + typname + ">" : typname;
}
case ftUnionValue: {
@@ -1027,8 +1032,12 @@ class RustGenerator : public BaseGenerator {
const auto underlying_typname = GetTypeBasic(type); //<- never used
const auto typname = WrapInNameSpace(*type.enum_def);
const auto default_value = GetDefaultScalarValue(field);
return "self._tab.get::<" + typname + ">(" + offset_name + ", Some(" +
default_value + ")).unwrap()";
if (field.optional) {
return "self._tab.get::<" + typname + ">(" + offset_name + ", None)";
} else {
return "self._tab.get::<" + typname + ">(" + offset_name + ", Some(" +
default_value + ")).unwrap()";
}
}
case ftString: {
return AddUnwrapIfRequired(

View File

@@ -53,7 +53,8 @@ $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS $TEST_JS_TS_FLAGS -o namespace
../flatc --dart monster_extra.fbs
# Generate optional scalar code for tests.
../flatc --kotlin --rust --lobster optional_scalars.fbs
../flatc --kotlin --lobster optional_scalars.fbs # These ones have not added optional enum support.
../flatc --rust optional_scalars2.fbs
../flatc $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS --cpp optional_scalars.fbs
# Generate the schema evolution tests

View File

@@ -0,0 +1,59 @@
namespace optional_scalars;
enum OptionalByte: byte {
None = 0,
One = 1,
Two = 2,
}
// 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;
just_enum: OptionalByte;
maybe_enum: OptionalByte = null;
default_enum: OptionalByte = One;
}
root_type ScalarStuff;
file_identifier "NULL";
file_extension "mon";

View File

@@ -23,11 +23,12 @@ pub mod optional_scalars {
pub enum OptionalByte {
None = 0,
One = 1,
Two = 2,
}
pub const ENUM_MIN_OPTIONAL_BYTE: i8 = 0;
pub const ENUM_MAX_OPTIONAL_BYTE: i8 = 1;
pub const ENUM_MAX_OPTIONAL_BYTE: i8 = 2;
impl<'a> flatbuffers::Follow<'a> for OptionalByte {
type Inner = Self;
@@ -61,15 +62,17 @@ impl flatbuffers::Push for OptionalByte {
}
#[allow(non_camel_case_types)]
pub const ENUM_VALUES_OPTIONAL_BYTE: [OptionalByte; 2] = [
pub const ENUM_VALUES_OPTIONAL_BYTE: [OptionalByte; 3] = [
OptionalByte::None,
OptionalByte::One
OptionalByte::One,
OptionalByte::Two
];
#[allow(non_camel_case_types)]
pub const ENUM_NAMES_OPTIONAL_BYTE: [&str; 2] = [
pub const ENUM_NAMES_OPTIONAL_BYTE: [&str; 3] = [
"None",
"One"
"One",
"Two"
];
pub fn enum_name_optional_byte(e: OptionalByte) -> &'static str {
@@ -129,6 +132,7 @@ impl<'a> ScalarStuff<'a> {
if let Some(x) = args.maybe_i16 { builder.add_maybe_i16(x); }
builder.add_just_i16(args.just_i16);
builder.add_default_enum(args.default_enum);
if let Some(x) = args.maybe_enum { builder.add_maybe_enum(x); }
builder.add_just_enum(args.just_enum);
builder.add_default_bool(args.default_bool);
if let Some(x) = args.maybe_bool { builder.add_maybe_bool(x); }
@@ -176,7 +180,8 @@ impl<'a> ScalarStuff<'a> {
pub const VT_MAYBE_BOOL: flatbuffers::VOffsetT = 66;
pub const VT_DEFAULT_BOOL: flatbuffers::VOffsetT = 68;
pub const VT_JUST_ENUM: flatbuffers::VOffsetT = 70;
pub const VT_DEFAULT_ENUM: flatbuffers::VOffsetT = 72;
pub const VT_MAYBE_ENUM: flatbuffers::VOffsetT = 72;
pub const VT_DEFAULT_ENUM: flatbuffers::VOffsetT = 74;
#[inline]
pub fn just_i8(&self) -> i8 {
@@ -315,6 +320,10 @@ impl<'a> ScalarStuff<'a> {
self._tab.get::<OptionalByte>(ScalarStuff::VT_JUST_ENUM, Some(OptionalByte::None)).unwrap()
}
#[inline]
pub fn maybe_enum(&self) -> Option<OptionalByte> {
self._tab.get::<OptionalByte>(ScalarStuff::VT_MAYBE_ENUM, None)
}
#[inline]
pub fn default_enum(&self) -> OptionalByte {
self._tab.get::<OptionalByte>(ScalarStuff::VT_DEFAULT_ENUM, Some(OptionalByte::One)).unwrap()
}
@@ -355,6 +364,7 @@ pub struct ScalarStuffArgs {
pub maybe_bool: Option<bool>,
pub default_bool: bool,
pub just_enum: OptionalByte,
pub maybe_enum: Option<OptionalByte>,
pub default_enum: OptionalByte,
}
impl<'a> Default for ScalarStuffArgs {
@@ -395,6 +405,7 @@ impl<'a> Default for ScalarStuffArgs {
maybe_bool: None,
default_bool: true,
just_enum: OptionalByte::None,
maybe_enum: None,
default_enum: OptionalByte::One,
}
}
@@ -541,6 +552,10 @@ impl<'a: 'b, 'b> ScalarStuffBuilder<'a, 'b> {
self.fbb_.push_slot::<OptionalByte>(ScalarStuff::VT_JUST_ENUM, just_enum, OptionalByte::None);
}
#[inline]
pub fn add_maybe_enum(&mut self, maybe_enum: OptionalByte) {
self.fbb_.push_slot_always::<OptionalByte>(ScalarStuff::VT_MAYBE_ENUM, maybe_enum);
}
#[inline]
pub fn add_default_enum(&mut self, default_enum: OptionalByte) {
self.fbb_.push_slot::<OptionalByte>(ScalarStuff::VT_DEFAULT_ENUM, default_enum, OptionalByte::One);
}

View File

@@ -43,7 +43,7 @@ mod monster_test_generated;
pub use monster_test_generated::my_game;
#[allow(dead_code, unused_imports)]
#[path = "../../optional_scalars_generated.rs"]
#[path = "../../optional_scalars2_generated.rs"]
mod optional_scalars_generated;
#[rustfmt::skip] // TODO: Use standard rust formatting and remove dead code.

View File

@@ -1,5 +1,5 @@
#[allow(dead_code, unused_imports)]
#[path = "../../optional_scalars_generated.rs"]
#[path = "../../optional_scalars2_generated.rs"]
mod optional_scalars_generated;
use crate::optional_scalars_generated::optional_scalars::*;
@@ -16,12 +16,15 @@ macro_rules! make_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()
});
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());
@@ -35,7 +38,6 @@ macro_rules! make_test {
assert_eq!(s.$default(), $fortytwo);
assert_eq!(s.$maybe(), None);
}
};
}
@@ -47,6 +49,39 @@ 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);
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
);
make_test!(
optional_enum,
just_enum,
default_enum,
maybe_enum,
OptionalByte::Two,
OptionalByte::None,
OptionalByte::One
);