[Issue 252] Add type cast for default enum values in C#
authorMormegil <mormegil@centrum.cz>
Tue, 11 Aug 2015 16:01:43 +0000 (18:01 +0200)
committerMormegil <mormegil@centrum.cz>
Tue, 11 Aug 2015 16:07:38 +0000 (18:07 +0200)
When creating a \93CreateXxx(...)\94 method for a \93simple table\94 type,
enum-type fields with a non-zero default must have an explicit
cast for the respective argument default value, because in C#,
there is an implicit cast from int to an enum only for 0.

Also, added an example of such type into the example monster_test
type, so that we test this feature.

src/idl_gen_general.cpp
tests/FlatBuffers.Test/FlatBuffers.Test.csproj
tests/MyGame/Example/Any.cs
tests/MyGame/Example/Any.go
tests/MyGame/Example/Any.java
tests/MyGame/Example/TestSimpleTableWithEnum.cs [new file with mode: 0644]
tests/MyGame/Example/TestSimpleTableWithEnum.go [new file with mode: 0644]
tests/MyGame/Example/TestSimpleTableWithEnum.java [new file with mode: 0644]
tests/monster_test.fbs
tests/monster_test_generated.h

index def1ad3..b2b7146 100644 (file)
@@ -789,7 +789,15 @@ static void GenStruct(const LanguageParameters &lang, const Parser &parser,
         // Java doesn't have defaults, which means this method must always
         // supply all arguments, and thus won't compile when fields are added.
         if (lang.language != GeneratorOptions::kJava) {
-          code += " = " + GenDefaultValue(lang, field.value, false);
+          code += " = ";
+          // in C#, enum values have their own type, so we need to cast the
+          // numeric value to the proper type
+          if (lang.language == GeneratorOptions::kCSharp &&
+            field.value.type.enum_def != nullptr &&
+            field.value.type.base_type != BASE_TYPE_UNION) {
+            code += "(" + field.value.type.enum_def->name + ")";
+          }
+          code += GenDefaultValue(lang, field.value, false);
         }
       }
       code += ") {\n    builder.";
index fd1c602..bfc0fe1 100644 (file)
@@ -71,6 +71,9 @@
     <Compile Include="..\MyGame\Example\Test.cs">
       <Link>MyGame\Example\Test.cs</Link>
     </Compile>
+    <Compile Include="..\MyGame\Example\TestSimpleTableWithEnum.cs">
+      <Link>MyGame\Example\TestSimpleTableWithEnum.cs</Link>
+    </Compile>
     <Compile Include="..\MyGame\Example\Vec3.cs">
       <Link>MyGame\Example\Vec3.cs</Link>
     </Compile>
index b7a5b36..a05a918 100644 (file)
@@ -7,6 +7,7 @@ public enum Any : byte
 {
  NONE = 0,
  Monster = 1,
+ TestSimpleTableWithEnum = 2,
 };
 
 
index 0039bb8..a23de4c 100644 (file)
@@ -5,4 +5,5 @@ package Example
 const (
        AnyNONE = 0
        AnyMonster = 1
+       AnyTestSimpleTableWithEnum = 2
 )
index f811f97..cdc3ec5 100644 (file)
@@ -6,8 +6,9 @@ public final class Any {
   private Any() { }
   public static final byte NONE = 0;
   public static final byte Monster = 1;
+  public static final byte TestSimpleTableWithEnum = 2;
 
-  private static final String[] names = { "NONE", "Monster", };
+  private static final String[] names = { "NONE", "Monster", "TestSimpleTableWithEnum", };
 
   public static String name(int e) { return names[e]; }
 };
diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.cs b/tests/MyGame/Example/TestSimpleTableWithEnum.cs
new file mode 100644 (file)
index 0000000..d2e75b5
--- /dev/null
@@ -0,0 +1,31 @@
+// automatically generated, do not modify
+
+namespace MyGame.Example
+{
+
+using FlatBuffers;
+
+public sealed class TestSimpleTableWithEnum : Table {
+  public static TestSimpleTableWithEnum GetRootAsTestSimpleTableWithEnum(ByteBuffer _bb) { return GetRootAsTestSimpleTableWithEnum(_bb, new TestSimpleTableWithEnum()); }
+  public static TestSimpleTableWithEnum GetRootAsTestSimpleTableWithEnum(ByteBuffer _bb, TestSimpleTableWithEnum obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
+  public TestSimpleTableWithEnum __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+
+  public Color Color { get { int o = __offset(4); return o != 0 ? (Color)bb.GetSbyte(o + bb_pos) : (Color)2; } }
+
+  public static Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(FlatBufferBuilder builder,
+      Color color = (Color)2) {
+    builder.StartObject(1);
+    TestSimpleTableWithEnum.AddColor(builder, color);
+    return TestSimpleTableWithEnum.EndTestSimpleTableWithEnum(builder);
+  }
+
+  public static void StartTestSimpleTableWithEnum(FlatBufferBuilder builder) { builder.StartObject(1); }
+  public static void AddColor(FlatBufferBuilder builder, Color color) { builder.AddSbyte(0, (sbyte)(color), 2); }
+  public static Offset<TestSimpleTableWithEnum> EndTestSimpleTableWithEnum(FlatBufferBuilder builder) {
+    int o = builder.EndObject();
+    return new Offset<TestSimpleTableWithEnum>(o);
+  }
+};
+
+
+}
diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.go b/tests/MyGame/Example/TestSimpleTableWithEnum.go
new file mode 100644 (file)
index 0000000..a26a53e
--- /dev/null
@@ -0,0 +1,27 @@
+// automatically generated, do not modify
+
+package Example
+
+import (
+       flatbuffers "github.com/google/flatbuffers/go"
+)
+type TestSimpleTableWithEnum struct {
+       _tab flatbuffers.Table
+}
+
+func (rcv *TestSimpleTableWithEnum) Init(buf []byte, i flatbuffers.UOffsetT) {
+       rcv._tab.Bytes = buf
+       rcv._tab.Pos = i
+}
+
+func (rcv *TestSimpleTableWithEnum) Color() int8 {
+       o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
+       if o != 0 {
+               return rcv._tab.GetInt8(o + rcv._tab.Pos)
+       }
+       return 2
+}
+
+func TestSimpleTableWithEnumStart(builder *flatbuffers.Builder) { builder.StartObject(1) }
+func TestSimpleTableWithEnumAddColor(builder *flatbuffers.Builder, color int8) { builder.PrependInt8Slot(0, color, 2) }
+func TestSimpleTableWithEnumEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { return builder.EndObject() }
diff --git a/tests/MyGame/Example/TestSimpleTableWithEnum.java b/tests/MyGame/Example/TestSimpleTableWithEnum.java
new file mode 100644 (file)
index 0000000..af9d7db
--- /dev/null
@@ -0,0 +1,31 @@
+// automatically generated, do not modify
+
+package MyGame.Example;
+
+import java.nio.*;
+import java.lang.*;
+import java.util.*;
+import com.google.flatbuffers.*;
+
+public final class TestSimpleTableWithEnum extends Table {
+  public static TestSimpleTableWithEnum getRootAsTestSimpleTableWithEnum(ByteBuffer _bb) { return getRootAsTestSimpleTableWithEnum(_bb, new TestSimpleTableWithEnum()); }
+  public static TestSimpleTableWithEnum getRootAsTestSimpleTableWithEnum(ByteBuffer _bb, TestSimpleTableWithEnum obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
+  public TestSimpleTableWithEnum __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
+
+  public byte color() { int o = __offset(4); return o != 0 ? bb.get(o + bb_pos) : 2; }
+
+  public static int createTestSimpleTableWithEnum(FlatBufferBuilder builder,
+      byte color) {
+    builder.startObject(1);
+    TestSimpleTableWithEnum.addColor(builder, color);
+    return TestSimpleTableWithEnum.endTestSimpleTableWithEnum(builder);
+  }
+
+  public static void startTestSimpleTableWithEnum(FlatBufferBuilder builder) { builder.startObject(1); }
+  public static void addColor(FlatBufferBuilder builder, byte color) { builder.addByte(0, color, 2); }
+  public static int endTestSimpleTableWithEnum(FlatBufferBuilder builder) {
+    int o = builder.endObject();
+    return o;
+  }
+};
+
index 53fa87b..6a205b0 100755 (executable)
@@ -8,10 +8,14 @@ attribute "priority";
 
 enum Color:byte (bit_flags) { Red = 0, Green, Blue = 3, }
 
-union Any { Monster }  // TODO: add more elements
+union Any { Monster, TestSimpleTableWithEnum }  // TODO: add more elements
 
 struct Test { a:short; b:byte; }
 
+table TestSimpleTableWithEnum {
+  color: Color = Green;
+}
+
 struct Vec3 (force_align: 16) {
   x:float;
   y:float;
index 7fb698b..93262dd 100644 (file)
@@ -15,6 +15,7 @@ namespace MyGame {
 namespace Example {
 
 struct Test;
+struct TestSimpleTableWithEnum;
 struct Vec3;
 struct Stat;
 struct Monster;
@@ -34,11 +35,12 @@ inline const char *EnumNameColor(Color e) { return EnumNamesColor()[e - Color_Re
 
 enum Any {
   Any_NONE = 0,
-  Any_Monster = 1
+  Any_Monster = 1,
+  Any_TestSimpleTableWithEnum = 2
 };
 
 inline const char **EnumNamesAny() {
-  static const char *names[] = { "NONE", "Monster", nullptr };
+  static const char *names[] = { "NONE", "Monster", "TestSimpleTableWithEnum", nullptr };
   return names;
 }
 
@@ -94,6 +96,35 @@ MANUALLY_ALIGNED_STRUCT(16) Vec3 FLATBUFFERS_FINAL_CLASS {
 };
 STRUCT_END(Vec3, 32);
 
+struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
+  Color color() const { return static_cast<Color>(GetField<int8_t>(4, 2)); }
+  bool mutate_color(Color color) { return SetField(4, static_cast<int8_t>(color)); }
+  bool Verify(flatbuffers::Verifier &verifier) const {
+    return VerifyTableStart(verifier) &&
+           VerifyField<int8_t>(verifier, 4 /* color */) &&
+           verifier.EndTable();
+  }
+};
+
+struct TestSimpleTableWithEnumBuilder {
+  flatbuffers::FlatBufferBuilder &fbb_;
+  flatbuffers::uoffset_t start_;
+  void add_color(Color color) { fbb_.AddElement<int8_t>(4, static_cast<int8_t>(color), 2); }
+  TestSimpleTableWithEnumBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
+  TestSimpleTableWithEnumBuilder &operator=(const TestSimpleTableWithEnumBuilder &);
+  flatbuffers::Offset<TestSimpleTableWithEnum> Finish() {
+    auto o = flatbuffers::Offset<TestSimpleTableWithEnum>(fbb_.EndTable(start_, 1));
+    return o;
+  }
+};
+
+inline flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatbuffers::FlatBufferBuilder &_fbb,
+   Color color = Color_Green) {
+  TestSimpleTableWithEnumBuilder builder_(_fbb);
+  builder_.add_color(color);
+  return builder_.Finish();
+}
+
 struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
   const flatbuffers::String *id() const { return GetPointer<const flatbuffers::String *>(4); }
   flatbuffers::String *mutable_id() { return GetPointer<flatbuffers::String *>(4); }
@@ -318,6 +349,7 @@ inline bool VerifyAny(flatbuffers::Verifier &verifier, const void *union_obj, An
   switch (type) {
     case Any_NONE: return true;
     case Any_Monster: return verifier.VerifyTable(reinterpret_cast<const Monster *>(union_obj));
+    case Any_TestSimpleTableWithEnum: return verifier.VerifyTable(reinterpret_cast<const TestSimpleTableWithEnum *>(union_obj));
     default: return false;
   }
 }