diff --git a/src/idl_gen_rust.cpp b/src/idl_gen_rust.cpp index 83973cf4f..64998af42 100644 --- a/src/idl_gen_rust.cpp +++ b/src/idl_gen_rust.cpp @@ -51,6 +51,10 @@ std::string MakeUpper(const std::string &in) { return s; } +std::string UnionTypeFieldName(const FieldDef &field) { + return MakeSnakeCase(field.name + "_type"); +} + // Encapsulate all logical field types in this enum. This allows us to write // field logic based on type switches, instead of branches on the properties // set on the Type. @@ -407,7 +411,7 @@ class RustGenerator : public BaseGenerator { gen_symbol(symbol); std::stringstream file_path; file_path << path_; - // DO NOT SUBMIT: CASPER: Refactor out common path name generation. + // Create filepath. if (symbol.defined_namespace) for (auto i = symbol.defined_namespace->components.begin(); i != symbol.defined_namespace->components.end(); i++) { @@ -1634,6 +1638,7 @@ class RustGenerator : public BaseGenerator { code_.SetValue("OFFSET_VALUE", NumToString(field.value.offset)); code_.SetValue("FIELD_NAME", Name(field)); code_.SetValue("BLDR_DEF_VAL", GetDefaultValue(field, kBuilder)); + code_.SetValue("DISCRIMINANT", UnionTypeFieldName(field)); cb(field); }; const auto &fields = struct_def.fields.vec; @@ -1905,7 +1910,6 @@ class RustGenerator : public BaseGenerator { // Explicit specializations for union accessors ForAllTableFields(struct_def, [&](const FieldDef &field) { if (field.value.type.base_type != BASE_TYPE_UNION) return; - code_.SetValue("FIELD_TYPE_FIELD_NAME", field.name); ForAllUnionVariantsBesidesNone( *field.value.type.enum_def, [&](const EnumVal &unused) { (void)unused; @@ -1926,8 +1930,7 @@ class RustGenerator : public BaseGenerator { // // To avoid this problem the type field name is used unescaped here: code_ += - " if self.{{FIELD_TYPE_FIELD_NAME}}_type() == " - "{{U_ELEMENT_ENUM_TYPE}} {"; + " if self.{{DISCRIMINANT}}() == {{U_ELEMENT_ENUM_TYPE}} {"; // The following logic is not tested in the integration test, // as of April 10, 2020 @@ -1973,11 +1976,16 @@ class RustGenerator : public BaseGenerator { return; } // Unions. - EnumDef &union_def = *field.value.type.enum_def; + const EnumDef &union_def = *field.value.type.enum_def; code_.SetValue("UNION_TYPE", WrapInNameSpace(union_def)); + // TODO: Use the same function that generates the _type field for + // consistency. We do not call Name() because it inconsistently + // escapes keywords. + code_.SetValue("UNION_TYPE_OFFSET_NAME", + "VT_" + MakeUpper(field.name + "_type")); code_ += "\n .visit_union::<{{UNION_TYPE}}, _>(" - "\"{{FIELD_NAME}}_type\", Self::{{OFFSET_NAME}}_TYPE, " + "\"{{FIELD_NAME}}_type\", Self::{{UNION_TYPE_OFFSET_NAME}}, " "\"{{FIELD_NAME}}\", Self::{{OFFSET_NAME}}, {{IS_REQ}}, " "|key, v, pos| {"; code_ += " match key {"; @@ -2101,19 +2109,18 @@ class RustGenerator : public BaseGenerator { if (GetFullType(field.value.type) == ftUnionValue) { // Generate a match statement to handle unions properly. code_.SetValue("KEY_TYPE", GenTableAccessorFuncReturnType(field, "")); - code_.SetValue("FIELD_TYPE_FIELD_NAME", field.name); code_.SetValue("UNION_ERR", "&\"InvalidFlatbuffer: Union discriminant" " does not match value.\""); - code_ += " match self.{{FIELD_NAME}}_type() {"; + code_ += " match self.{{DISCRIMINANT}}() {"; ForAllUnionVariantsBesidesNone( *field.value.type.enum_def, [&](const EnumVal &unused) { (void)unused; code_ += " {{U_ELEMENT_ENUM_TYPE}} => {"; code_ += " if let Some(x) = " - "self.{{FIELD_TYPE_FIELD_NAME}}_as_" + "self.{{FIELD_NAME}}_as_" "{{U_ELEMENT_NAME}}() {"; code_ += " ds.field(\"{{FIELD_NAME}}\", &x)"; code_ += " } else {"; diff --git a/tests/generate_code.sh b/tests/generate_code.sh index e8d74decc..009b67a30 100755 --- a/tests/generate_code.sh +++ b/tests/generate_code.sh @@ -75,6 +75,7 @@ $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS $TEST_CS_FLAGS $TEST_TS_FLAGS -o namespace_te # Generate the keywords tests ../flatc --csharp $TEST_BASE_FLAGS $TEST_CS_FLAGS -o keyword_test ./keyword_test.fbs +../flatc --rust $TEST_RUST_FLAGS -o keyword_test ./keyword_test.fbs working_dir=`pwd` cd FlatBuffers.Test.Swift/Tests/FlatBuffers.Test.SwiftTests diff --git a/tests/keyword_test.fbs b/tests/keyword_test.fbs index f6be25ba6..a7187eb2b 100644 --- a/tests/keyword_test.fbs +++ b/tests/keyword_test.fbs @@ -6,9 +6,10 @@ enum public: int { } table KeywordsInTable { is: ABC = void; private: public; + type: int; } union KeywordsInUnion { static: KeywordsInTable, - internal: string + internal: KeywordsInTable, } diff --git a/tests/keyword_test/KeywordsInTable.cs b/tests/keyword_test/KeywordsInTable.cs index fe91e8b23..88019babf 100644 --- a/tests/keyword_test/KeywordsInTable.cs +++ b/tests/keyword_test/KeywordsInTable.cs @@ -20,19 +20,24 @@ public struct KeywordsInTable : IFlatbufferObject public bool MutateIs(ABC is_) { int o = __p.__offset(4); if (o != 0) { __p.bb.PutInt(o + __p.bb_pos, (int)is_); return true; } else { return false; } } public public_ Private { get { int o = __p.__offset(6); return o != 0 ? (public_)__p.bb.GetInt(o + __p.bb_pos) : public_.NONE; } } public bool MutatePrivate(public_ private_) { int o = __p.__offset(6); if (o != 0) { __p.bb.PutInt(o + __p.bb_pos, (int)private_); return true; } else { return false; } } + public int Type { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } } + public bool MutateType(int type) { int o = __p.__offset(8); if (o != 0) { __p.bb.PutInt(o + __p.bb_pos, type); return true; } else { return false; } } public static Offset CreateKeywordsInTable(FlatBufferBuilder builder, ABC is_ = ABC.void_, - public_ private_ = public_.NONE) { - builder.StartTable(2); + public_ private_ = public_.NONE, + int type = 0) { + builder.StartTable(3); + KeywordsInTable.AddType(builder, type); KeywordsInTable.AddPrivate(builder, private_); KeywordsInTable.AddIs(builder, is_); return KeywordsInTable.EndKeywordsInTable(builder); } - public static void StartKeywordsInTable(FlatBufferBuilder builder) { builder.StartTable(2); } + public static void StartKeywordsInTable(FlatBufferBuilder builder) { builder.StartTable(3); } public static void AddIs(FlatBufferBuilder builder, ABC is_) { builder.AddInt(0, (int)is_, 0); } public static void AddPrivate(FlatBufferBuilder builder, public_ private_) { builder.AddInt(1, (int)private_, 0); } + public static void AddType(FlatBufferBuilder builder, int type) { builder.AddInt(2, type, 0); } public static Offset EndKeywordsInTable(FlatBufferBuilder builder) { int o = builder.EndTable(); return new Offset(o); @@ -45,13 +50,15 @@ public struct KeywordsInTable : IFlatbufferObject public void UnPackTo(KeywordsInTableT _o) { _o.Is = this.Is; _o.Private = this.Private; + _o.Type = this.Type; } public static Offset Pack(FlatBufferBuilder builder, KeywordsInTableT _o) { if (_o == null) return default(Offset); return CreateKeywordsInTable( builder, _o.Is, - _o.Private); + _o.Private, + _o.Type); } } @@ -61,10 +68,13 @@ public class KeywordsInTableT public ABC Is { get; set; } [Newtonsoft.Json.JsonProperty("private")] public public_ Private { get; set; } + [Newtonsoft.Json.JsonProperty("type")] + public int Type { get; set; } public KeywordsInTableT() { this.Is = ABC.void_; this.Private = public_.NONE; + this.Type = 0; } } diff --git a/tests/keyword_test/KeywordsInUnion.cs b/tests/keyword_test/KeywordsInUnion.cs index 1f26f3160..24b126eee 100644 --- a/tests/keyword_test/KeywordsInUnion.cs +++ b/tests/keyword_test/KeywordsInUnion.cs @@ -22,14 +22,14 @@ public class KeywordsInUnionUnion { public T As() where T : class { return this.Value as T; } public KeywordsInTableT Asstatic() { return this.As(); } public static KeywordsInUnionUnion Fromstatic(KeywordsInTableT _static) { return new KeywordsInUnionUnion{ Type = KeywordsInUnion.static_, Value = _static }; } - public string Asinternal() { return this.As(); } - public static KeywordsInUnionUnion Frominternal(string _internal) { return new KeywordsInUnionUnion{ Type = KeywordsInUnion.internal_, Value = _internal }; } + public KeywordsInTableT Asinternal() { return this.As(); } + public static KeywordsInUnionUnion Frominternal(KeywordsInTableT _internal) { return new KeywordsInUnionUnion{ Type = KeywordsInUnion.internal_, Value = _internal }; } public static int Pack(FlatBuffers.FlatBufferBuilder builder, KeywordsInUnionUnion _o) { switch (_o.Type) { default: return 0; case KeywordsInUnion.static_: return KeywordsInTable.Pack(builder, _o.Asstatic()).Value; - case KeywordsInUnion.internal_: return builder.CreateString(_o.Asinternal()).Value; + case KeywordsInUnion.internal_: return KeywordsInTable.Pack(builder, _o.Asinternal()).Value; } } } @@ -70,7 +70,7 @@ public class KeywordsInUnionUnion_JsonConverter : Newtonsoft.Json.JsonConverter switch (_o.Type) { default: break; case KeywordsInUnion.static_: _o.Value = serializer.Deserialize(reader); break; - case KeywordsInUnion.internal_: _o.Value = serializer.Deserialize(reader); break; + case KeywordsInUnion.internal_: _o.Value = serializer.Deserialize(reader); break; } return _o; } diff --git a/tests/keyword_test/abc_generated.rs b/tests/keyword_test/abc_generated.rs new file mode 100644 index 000000000..99b43e466 --- /dev/null +++ b/tests/keyword_test/abc_generated.rs @@ -0,0 +1,97 @@ +// automatically generated by the FlatBuffers compiler, do not modify +extern crate flatbuffers; +use std::mem; +use std::cmp::Ordering; +use self::flatbuffers::{EndianScalar, Follow}; +use super::*; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_ABC: i32 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_ABC: i32 = 2; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_ABC: [ABC; 3] = [ + ABC::void, + ABC::where_, + ABC::stackalloc, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct ABC(pub i32); +#[allow(non_upper_case_globals)] +impl ABC { + pub const void: Self = Self(0); + pub const where_: Self = Self(1); + pub const stackalloc: Self = Self(2); + + pub const ENUM_MIN: i32 = 0; + pub const ENUM_MAX: i32 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::void, + Self::where_, + Self::stackalloc, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::void => Some("void"), + Self::where_ => Some("where_"), + Self::stackalloc => Some("stackalloc"), + _ => None, + } + } +} +impl std::fmt::Debug for ABC { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> flatbuffers::Follow<'a> for ABC { + type Inner = Self; + #[inline] + fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { + flatbuffers::read_scalar_at::(buf, loc) + }; + Self(b) + } +} + +impl flatbuffers::Push for ABC { + type Output = ABC; + #[inline] + fn push(&self, dst: &mut [u8], _rest: &[u8]) { + unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + } +} + +impl flatbuffers::EndianScalar for ABC { + #[inline] + fn to_little_endian(self) -> Self { + let b = i32::to_le(self.0); + Self(b) + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(self) -> Self { + let b = i32::from_le(self.0); + Self(b) + } +} + +impl<'a> flatbuffers::Verifiable for ABC { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + i32::run_verifier(v, pos) + } +} + +impl flatbuffers::SimpleToVerifyInSlice for ABC {} diff --git a/tests/keyword_test/keywords_in_table_generated.rs b/tests/keyword_test/keywords_in_table_generated.rs new file mode 100644 index 000000000..44cf08d92 --- /dev/null +++ b/tests/keyword_test/keywords_in_table_generated.rs @@ -0,0 +1,170 @@ +// automatically generated by the FlatBuffers compiler, do not modify +extern crate flatbuffers; +use std::mem; +use std::cmp::Ordering; +use self::flatbuffers::{EndianScalar, Follow}; +use super::*; +pub enum KeywordsInTableOffset {} +#[derive(Copy, Clone, PartialEq)] + +pub struct KeywordsInTable<'a> { + pub _tab: flatbuffers::Table<'a>, +} + +impl<'a> flatbuffers::Follow<'a> for KeywordsInTable<'a> { + type Inner = KeywordsInTable<'a>; + #[inline] + fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + Self { _tab: flatbuffers::Table { buf, loc } } + } +} + +impl<'a> KeywordsInTable<'a> { + pub const fn get_fully_qualified_name() -> &'static str { + "KeywordsInTable" + } + + #[inline] + pub fn init_from_table(table: flatbuffers::Table<'a>) -> Self { + KeywordsInTable { _tab: table } + } + #[allow(unused_mut)] + pub fn create<'bldr: 'args, 'args: 'mut_bldr, 'mut_bldr>( + _fbb: &'mut_bldr mut flatbuffers::FlatBufferBuilder<'bldr>, + args: &'args KeywordsInTableArgs) -> flatbuffers::WIPOffset> { + let mut builder = KeywordsInTableBuilder::new(_fbb); + builder.add_type_(args.type_); + builder.add_private(args.private); + builder.add_is(args.is); + builder.finish() + } + + pub fn unpack(&self) -> KeywordsInTableT { + let is = self.is(); + let private = self.private(); + let type_ = self.type_(); + KeywordsInTableT { + is, + private, + type_, + } + } + pub const VT_IS: flatbuffers::VOffsetT = 4; + pub const VT_PRIVATE: flatbuffers::VOffsetT = 6; + pub const VT_TYPE_: flatbuffers::VOffsetT = 8; + + #[inline] + pub fn is(&self) -> ABC { + self._tab.get::(KeywordsInTable::VT_IS, Some(ABC::void)).unwrap() + } + #[inline] + pub fn private(&self) -> public { + self._tab.get::(KeywordsInTable::VT_PRIVATE, Some(public::NONE)).unwrap() + } + #[inline] + pub fn type_(&self) -> i32 { + self._tab.get::(KeywordsInTable::VT_TYPE_, Some(0)).unwrap() + } +} + +impl flatbuffers::Verifiable for KeywordsInTable<'_> { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::("is", Self::VT_IS, false)? + .visit_field::("private", Self::VT_PRIVATE, false)? + .visit_field::("type_", Self::VT_TYPE_, false)? + .finish(); + Ok(()) + } +} +pub struct KeywordsInTableArgs { + pub is: ABC, + pub private: public, + pub type_: i32, +} +impl<'a> Default for KeywordsInTableArgs { + #[inline] + fn default() -> Self { + KeywordsInTableArgs { + is: ABC::void, + private: public::NONE, + type_: 0, + } + } +} +pub struct KeywordsInTableBuilder<'a: 'b, 'b> { + fbb_: &'b mut flatbuffers::FlatBufferBuilder<'a>, + start_: flatbuffers::WIPOffset, +} +impl<'a: 'b, 'b> KeywordsInTableBuilder<'a, 'b> { + #[inline] + pub fn add_is(&mut self, is: ABC) { + self.fbb_.push_slot::(KeywordsInTable::VT_IS, is, ABC::void); + } + #[inline] + pub fn add_private(&mut self, private: public) { + self.fbb_.push_slot::(KeywordsInTable::VT_PRIVATE, private, public::NONE); + } + #[inline] + pub fn add_type_(&mut self, type_: i32) { + self.fbb_.push_slot::(KeywordsInTable::VT_TYPE_, type_, 0); + } + #[inline] + pub fn new(_fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>) -> KeywordsInTableBuilder<'a, 'b> { + let start = _fbb.start_table(); + KeywordsInTableBuilder { + fbb_: _fbb, + start_: start, + } + } + #[inline] + pub fn finish(self) -> flatbuffers::WIPOffset> { + let o = self.fbb_.end_table(self.start_); + flatbuffers::WIPOffset::new(o.value()) + } +} + +impl std::fmt::Debug for KeywordsInTable<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut ds = f.debug_struct("KeywordsInTable"); + ds.field("is", &self.is()); + ds.field("private", &self.private()); + ds.field("type_", &self.type_()); + ds.finish() + } +} +#[non_exhaustive] +#[derive(Debug, Clone, PartialEq)] +pub struct KeywordsInTableT { + pub is: ABC, + pub private: public, + pub type_: i32, +} +impl Default for KeywordsInTableT { + fn default() -> Self { + Self { + is: ABC::void, + private: public::NONE, + type_: 0, + } + } +} +impl KeywordsInTableT { + pub fn pack<'b>( + &self, + _fbb: &mut flatbuffers::FlatBufferBuilder<'b> + ) -> flatbuffers::WIPOffset> { + let is = self.is; + let private = self.private; + let type_ = self.type_; + KeywordsInTable::create(_fbb, &KeywordsInTableArgs{ + is, + private, + type_, + }) + } +} diff --git a/tests/keyword_test/keywords_in_union_generated.rs b/tests/keyword_test/keywords_in_union_generated.rs new file mode 100644 index 000000000..cf03797f9 --- /dev/null +++ b/tests/keyword_test/keywords_in_union_generated.rs @@ -0,0 +1,170 @@ +// automatically generated by the FlatBuffers compiler, do not modify +extern crate flatbuffers; +use std::mem; +use std::cmp::Ordering; +use self::flatbuffers::{EndianScalar, Follow}; +use super::*; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_KEYWORDS_IN_UNION: u8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_KEYWORDS_IN_UNION: u8 = 2; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_KEYWORDS_IN_UNION: [KeywordsInUnion; 3] = [ + KeywordsInUnion::NONE, + KeywordsInUnion::static_, + KeywordsInUnion::internal, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct KeywordsInUnion(pub u8); +#[allow(non_upper_case_globals)] +impl KeywordsInUnion { + pub const NONE: Self = Self(0); + pub const static_: Self = Self(1); + pub const internal: Self = Self(2); + + pub const ENUM_MIN: u8 = 0; + pub const ENUM_MAX: u8 = 2; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::NONE, + Self::static_, + Self::internal, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + Self::static_ => Some("static_"), + Self::internal => Some("internal"), + _ => None, + } + } +} +impl std::fmt::Debug for KeywordsInUnion { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> flatbuffers::Follow<'a> for KeywordsInUnion { + type Inner = Self; + #[inline] + fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { + flatbuffers::read_scalar_at::(buf, loc) + }; + Self(b) + } +} + +impl flatbuffers::Push for KeywordsInUnion { + type Output = KeywordsInUnion; + #[inline] + fn push(&self, dst: &mut [u8], _rest: &[u8]) { + unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + } +} + +impl flatbuffers::EndianScalar for KeywordsInUnion { + #[inline] + fn to_little_endian(self) -> Self { + let b = u8::to_le(self.0); + Self(b) + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(self) -> Self { + let b = u8::from_le(self.0); + Self(b) + } +} + +impl<'a> flatbuffers::Verifiable for KeywordsInUnion { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + u8::run_verifier(v, pos) + } +} + +impl flatbuffers::SimpleToVerifyInSlice for KeywordsInUnion {} +pub struct KeywordsInUnionUnionTableOffset {} + +#[allow(clippy::upper_case_acronyms)] +#[non_exhaustive] +#[derive(Debug, Clone, PartialEq)] +pub enum KeywordsInUnionT { + NONE, + Static_(Box), + Internal(Box), +} +impl Default for KeywordsInUnionT { + fn default() -> Self { + Self::NONE + } +} +impl KeywordsInUnionT { + pub fn keywords_in_union_type(&self) -> KeywordsInUnion { + match self { + Self::NONE => KeywordsInUnion::NONE, + Self::Static_(_) => KeywordsInUnion::static_, + Self::Internal(_) => KeywordsInUnion::internal, + } + } + pub fn pack(&self, fbb: &mut flatbuffers::FlatBufferBuilder) -> Option> { + match self { + Self::NONE => None, + Self::Static_(v) => Some(v.pack(fbb).as_union_value()), + Self::Internal(v) => Some(v.pack(fbb).as_union_value()), + } + } + /// If the union variant matches, return the owned KeywordsInTableT, setting the union to NONE. + pub fn take_static_(&mut self) -> Option> { + if let Self::Static_(_) = self { + let v = std::mem::replace(self, Self::NONE); + if let Self::Static_(w) = v { + Some(w) + } else { + unreachable!() + } + } else { + None + } + } + /// If the union variant matches, return a reference to the KeywordsInTableT. + pub fn as_static_(&self) -> Option<&KeywordsInTableT> { + if let Self::Static_(v) = self { Some(v.as_ref()) } else { None } + } + /// If the union variant matches, return a mutable reference to the KeywordsInTableT. + pub fn as_static__mut(&mut self) -> Option<&mut KeywordsInTableT> { + if let Self::Static_(v) = self { Some(v.as_mut()) } else { None } + } + /// If the union variant matches, return the owned KeywordsInTableT, setting the union to NONE. + pub fn take_internal(&mut self) -> Option> { + if let Self::Internal(_) = self { + let v = std::mem::replace(self, Self::NONE); + if let Self::Internal(w) = v { + Some(w) + } else { + unreachable!() + } + } else { + None + } + } + /// If the union variant matches, return a reference to the KeywordsInTableT. + pub fn as_internal(&self) -> Option<&KeywordsInTableT> { + if let Self::Internal(v) = self { Some(v.as_ref()) } else { None } + } + /// If the union variant matches, return a mutable reference to the KeywordsInTableT. + pub fn as_internal_mut(&mut self) -> Option<&mut KeywordsInTableT> { + if let Self::Internal(v) = self { Some(v.as_mut()) } else { None } + } +} diff --git a/tests/keyword_test/mod.rs b/tests/keyword_test/mod.rs new file mode 100644 index 000000000..02506f8ee --- /dev/null +++ b/tests/keyword_test/mod.rs @@ -0,0 +1,9 @@ +// Automatically generated by the Flatbuffers compiler. Do not modify. +mod abc_generated; +pub use self::abc_generated::*; +mod public_generated; +pub use self::public_generated::*; +mod keywords_in_union_generated; +pub use self::keywords_in_union_generated::*; +mod keywords_in_table_generated; +pub use self::keywords_in_table_generated::*; diff --git a/tests/keyword_test/public_generated.rs b/tests/keyword_test/public_generated.rs new file mode 100644 index 000000000..2de4c0b24 --- /dev/null +++ b/tests/keyword_test/public_generated.rs @@ -0,0 +1,89 @@ +// automatically generated by the FlatBuffers compiler, do not modify +extern crate flatbuffers; +use std::mem; +use std::cmp::Ordering; +use self::flatbuffers::{EndianScalar, Follow}; +use super::*; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_PUBLIC: i32 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_PUBLIC: i32 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_PUBLIC: [public; 1] = [ + public::NONE, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct public(pub i32); +#[allow(non_upper_case_globals)] +impl public { + pub const NONE: Self = Self(0); + + pub const ENUM_MIN: i32 = 0; + pub const ENUM_MAX: i32 = 0; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::NONE, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + _ => None, + } + } +} +impl std::fmt::Debug for public { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> flatbuffers::Follow<'a> for public { + type Inner = Self; + #[inline] + fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { + flatbuffers::read_scalar_at::(buf, loc) + }; + Self(b) + } +} + +impl flatbuffers::Push for public { + type Output = public; + #[inline] + fn push(&self, dst: &mut [u8], _rest: &[u8]) { + unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + } +} + +impl flatbuffers::EndianScalar for public { + #[inline] + fn to_little_endian(self) -> Self { + let b = i32::to_le(self.0); + Self(b) + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(self) -> Self { + let b = i32::from_le(self.0); + Self(b) + } +} + +impl<'a> flatbuffers::Verifiable for public { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + i32::run_verifier(v, pos) + } +} + +impl flatbuffers::SimpleToVerifyInSlice for public {} diff --git a/tests/keyword_test/type.cs b/tests/keyword_test/type.cs new file mode 100644 index 000000000..9938a2fae --- /dev/null +++ b/tests/keyword_test/type.cs @@ -0,0 +1,10 @@ +// +// automatically generated by the FlatBuffers compiler, do not modify +// + +[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))] +public enum type : sbyte +{ + NONE = 0, +}; + diff --git a/tests/keyword_test/type_generated.rs b/tests/keyword_test/type_generated.rs new file mode 100644 index 000000000..ff9323911 --- /dev/null +++ b/tests/keyword_test/type_generated.rs @@ -0,0 +1,89 @@ +// automatically generated by the FlatBuffers compiler, do not modify +extern crate flatbuffers; +use std::mem; +use std::cmp::Ordering; +use self::flatbuffers::{EndianScalar, Follow}; +use super::*; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MIN_TYPE_: i8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +pub const ENUM_MAX_TYPE_: i8 = 0; +#[deprecated(since = "2.0.0", note = "Use associated constants instead. This will no longer be generated in 2021.")] +#[allow(non_camel_case_types)] +pub const ENUM_VALUES_TYPE_: [type_; 1] = [ + type_::NONE, +]; + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[repr(transparent)] +pub struct type_(pub i8); +#[allow(non_upper_case_globals)] +impl type_ { + pub const NONE: Self = Self(0); + + pub const ENUM_MIN: i8 = 0; + pub const ENUM_MAX: i8 = 0; + pub const ENUM_VALUES: &'static [Self] = &[ + Self::NONE, + ]; + /// Returns the variant's name or "" if unknown. + pub fn variant_name(self) -> Option<&'static str> { + match self { + Self::NONE => Some("NONE"), + _ => None, + } + } +} +impl std::fmt::Debug for type_ { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + if let Some(name) = self.variant_name() { + f.write_str(name) + } else { + f.write_fmt(format_args!("", self.0)) + } + } +} +impl<'a> flatbuffers::Follow<'a> for type_ { + type Inner = Self; + #[inline] + fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { + let b = unsafe { + flatbuffers::read_scalar_at::(buf, loc) + }; + Self(b) + } +} + +impl flatbuffers::Push for type_ { + type Output = type_; + #[inline] + fn push(&self, dst: &mut [u8], _rest: &[u8]) { + unsafe { flatbuffers::emplace_scalar::(dst, self.0); } + } +} + +impl flatbuffers::EndianScalar for type_ { + #[inline] + fn to_little_endian(self) -> Self { + let b = i8::to_le(self.0); + Self(b) + } + #[inline] + #[allow(clippy::wrong_self_convention)] + fn from_little_endian(self) -> Self { + let b = i8::from_le(self.0); + Self(b) + } +} + +impl<'a> flatbuffers::Verifiable for type_ { + #[inline] + fn run_verifier( + v: &mut flatbuffers::Verifier, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + i8::run_verifier(v, pos) + } +} + +impl flatbuffers::SimpleToVerifyInSlice for type_ {} diff --git a/tests/rust_usage_test/tests/integration_test.rs b/tests/rust_usage_test/tests/integration_test.rs index aa7bfc54e..49c0390d2 100644 --- a/tests/rust_usage_test/tests/integration_test.rs +++ b/tests/rust_usage_test/tests/integration_test.rs @@ -57,6 +57,10 @@ mod optional_scalars_generated; #[path = "../../arrays_test/mod.rs"] mod arrays_test_generated; +#[allow(dead_code, unused_imports)] +#[path = "../../keyword_test/mod.rs"] +mod keyword_test_generated; + #[rustfmt::skip] // TODO: Use standard rust formatting and remove dead code. #[allow(dead_code)] mod flatbuffers_tests {