Generate nullable properties in C# object-based API for optional scalars. (without...
authorStefan F <32997632+stefan301@users.noreply.github.com>
Fri, 11 Dec 2020 00:50:30 +0000 (01:50 +0100)
committerGitHub <noreply@github.com>
Fri, 11 Dec 2020 00:50:30 +0000 (16:50 -0800)
* Added missing EndTable() call to VerifyObject()

VerifyObject called VerifyTableStart() but not EndTable(). This made Verifier::VerifyComplexity() increase depth_ with each table, not with the depth of tables.

https://groups.google.com/forum/#!topic/flatbuffers/OpxtW5UFAdg

* Added Check to VerifyAlignment

https://stackoverflow.com/questions/59376308/flatbuffers-verifier-returns-false-without-any-assertion-flatbuffers-debug-veri

* Add GetStringView (Convenience function to get string_view from a String returning an empty string_view on null pointer) like GetString, GetCstring

* flatc should warn, when an attribute is attached more than once.

flatc.exe -b duplicate.fbs
warning: duplicate.fbs(5, 36): warning: attribute already found: priority

duplicate.fbs:

namespace MyGame;

attribute "priority";

table Monster (priority:1, priority:2) {
}

root_type Monster;

* flatc should support --binary --schema with optional scalar fields.

This fixes 'error: Optional scalars are not yet supported in at least one the of the specified programming languages.' when calling flatc.exe --binary --schema with a schema containing optional scalars.

* Generate nullable properties in C# object-based API for optional scalars.
tests\generate_code.bat extended to test this.

Ran tests\generate_code.bat
Ran tests\Flatbuffers.Test\NetTest.bat

* %TEST_BASE_FLAGS% replaced with --gen-object-api in generate_code.bat, because only this is part of this PR. Added this same flag to generate_code.sh

* generate_code.bat and generate_code.sh changed to only test c# with object based api.

src/idl_gen_csharp.cpp
tests/generate_code.bat
tests/generate_code.sh
tests/optional_scalars/ScalarStuff.cs

index d2f14f0..bc2f9bd 100644 (file)
@@ -1959,6 +1959,7 @@ class CSharpGenerator : public BaseGenerator {
       if (field.value.type.base_type == BASE_TYPE_UTYPE) continue;
       if (field.value.type.element == BASE_TYPE_UTYPE) continue;
       auto type_name = GenTypeGet_ObjectAPI(field.value.type, opts);
+      if (field.IsScalarOptional()) type_name += "?";
       auto camel_name = MakeCamel(field.name, true);
       if (opts.cs_gen_json_serializer) {
         if (IsUnion(field.value.type)) {
index 1fc96a2..764e3f4 100644 (file)
@@ -55,7 +55,8 @@ set TEST_NOINCL_FLAGS=%TEST_BASE_FLAGS% --no-includes --no-fb-import
 ..\%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 --csharp --java --kotlin --rust --lobster --ts --js optional_scalars.fbs || goto FAIL
+..\%buildtype%\flatc.exe --java --kotlin --rust --lobster --ts --js optional_scalars.fbs || goto FAIL
+..\%buildtype%\flatc.exe --csharp --gen-object-api optional_scalars.fbs || goto FAIL
 ..\%buildtype%\flatc.exe %TEST_NOINCL_FLAGS% %TEST_CPP_FLAGS% --cpp optional_scalars.fbs || goto FAIL
 
 @rem Generate the schema evolution tests
index 89d9429..671bfbe 100755 (executable)
@@ -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 --csharp --java --kotlin --rust --lobster --ts --js optional_scalars.fbs
+../flatc --java --kotlin --rust --lobster --ts --js optional_scalars.fbs
+../flatc --csharp --gen-object-api optional_scalars.fbs
 ../flatc $TEST_NOINCL_FLAGS $TEST_CPP_FLAGS --cpp optional_scalars.fbs
 
 # Generate the schema evolution tests
index a5c9ffb..64d030e 100644 (file)
@@ -177,7 +177,178 @@ public struct ScalarStuff : IFlatbufferObject
   }
   public static void FinishScalarStuffBuffer(FlatBufferBuilder builder, Offset<optional_scalars.ScalarStuff> offset) { builder.Finish(offset.Value, "NULL"); }
   public static void FinishSizePrefixedScalarStuffBuffer(FlatBufferBuilder builder, Offset<optional_scalars.ScalarStuff> offset) { builder.FinishSizePrefixed(offset.Value, "NULL"); }
+  public ScalarStuffT UnPack() {
+    var _o = new ScalarStuffT();
+    this.UnPackTo(_o);
+    return _o;
+  }
+  public void UnPackTo(ScalarStuffT _o) {
+    _o.JustI8 = this.JustI8;
+    _o.MaybeI8 = this.MaybeI8;
+    _o.DefaultI8 = this.DefaultI8;
+    _o.JustU8 = this.JustU8;
+    _o.MaybeU8 = this.MaybeU8;
+    _o.DefaultU8 = this.DefaultU8;
+    _o.JustI16 = this.JustI16;
+    _o.MaybeI16 = this.MaybeI16;
+    _o.DefaultI16 = this.DefaultI16;
+    _o.JustU16 = this.JustU16;
+    _o.MaybeU16 = this.MaybeU16;
+    _o.DefaultU16 = this.DefaultU16;
+    _o.JustI32 = this.JustI32;
+    _o.MaybeI32 = this.MaybeI32;
+    _o.DefaultI32 = this.DefaultI32;
+    _o.JustU32 = this.JustU32;
+    _o.MaybeU32 = this.MaybeU32;
+    _o.DefaultU32 = this.DefaultU32;
+    _o.JustI64 = this.JustI64;
+    _o.MaybeI64 = this.MaybeI64;
+    _o.DefaultI64 = this.DefaultI64;
+    _o.JustU64 = this.JustU64;
+    _o.MaybeU64 = this.MaybeU64;
+    _o.DefaultU64 = this.DefaultU64;
+    _o.JustF32 = this.JustF32;
+    _o.MaybeF32 = this.MaybeF32;
+    _o.DefaultF32 = this.DefaultF32;
+    _o.JustF64 = this.JustF64;
+    _o.MaybeF64 = this.MaybeF64;
+    _o.DefaultF64 = this.DefaultF64;
+    _o.JustBool = this.JustBool;
+    _o.MaybeBool = this.MaybeBool;
+    _o.DefaultBool = this.DefaultBool;
+    _o.JustEnum = this.JustEnum;
+    _o.MaybeEnum = this.MaybeEnum;
+    _o.DefaultEnum = this.DefaultEnum;
+  }
+  public static Offset<optional_scalars.ScalarStuff> Pack(FlatBufferBuilder builder, ScalarStuffT _o) {
+    if (_o == null) return default(Offset<optional_scalars.ScalarStuff>);
+    return CreateScalarStuff(
+      builder,
+      _o.JustI8,
+      _o.MaybeI8,
+      _o.DefaultI8,
+      _o.JustU8,
+      _o.MaybeU8,
+      _o.DefaultU8,
+      _o.JustI16,
+      _o.MaybeI16,
+      _o.DefaultI16,
+      _o.JustU16,
+      _o.MaybeU16,
+      _o.DefaultU16,
+      _o.JustI32,
+      _o.MaybeI32,
+      _o.DefaultI32,
+      _o.JustU32,
+      _o.MaybeU32,
+      _o.DefaultU32,
+      _o.JustI64,
+      _o.MaybeI64,
+      _o.DefaultI64,
+      _o.JustU64,
+      _o.MaybeU64,
+      _o.DefaultU64,
+      _o.JustF32,
+      _o.MaybeF32,
+      _o.DefaultF32,
+      _o.JustF64,
+      _o.MaybeF64,
+      _o.DefaultF64,
+      _o.JustBool,
+      _o.MaybeBool,
+      _o.DefaultBool,
+      _o.JustEnum,
+      _o.MaybeEnum,
+      _o.DefaultEnum);
+  }
 };
 
+public class ScalarStuffT
+{
+  public sbyte JustI8 { get; set; }
+  public sbyte? MaybeI8 { get; set; }
+  public sbyte DefaultI8 { get; set; }
+  public byte JustU8 { get; set; }
+  public byte? MaybeU8 { get; set; }
+  public byte DefaultU8 { get; set; }
+  public short JustI16 { get; set; }
+  public short? MaybeI16 { get; set; }
+  public short DefaultI16 { get; set; }
+  public ushort JustU16 { get; set; }
+  public ushort? MaybeU16 { get; set; }
+  public ushort DefaultU16 { get; set; }
+  public int JustI32 { get; set; }
+  public int? MaybeI32 { get; set; }
+  public int DefaultI32 { get; set; }
+  public uint JustU32 { get; set; }
+  public uint? MaybeU32 { get; set; }
+  public uint DefaultU32 { get; set; }
+  public long JustI64 { get; set; }
+  public long? MaybeI64 { get; set; }
+  public long DefaultI64 { get; set; }
+  public ulong JustU64 { get; set; }
+  public ulong? MaybeU64 { get; set; }
+  public ulong DefaultU64 { get; set; }
+  public float JustF32 { get; set; }
+  public float? MaybeF32 { get; set; }
+  public float DefaultF32 { get; set; }
+  public double JustF64 { get; set; }
+  public double? MaybeF64 { get; set; }
+  public double DefaultF64 { get; set; }
+  public bool JustBool { get; set; }
+  public bool? MaybeBool { get; set; }
+  public bool DefaultBool { get; set; }
+  public optional_scalars.OptionalByte JustEnum { get; set; }
+  public optional_scalars.OptionalByte? MaybeEnum { get; set; }
+  public optional_scalars.OptionalByte DefaultEnum { get; set; }
+
+  public ScalarStuffT() {
+    this.JustI8 = 0;
+    this.MaybeI8 = null;
+    this.DefaultI8 = 42;
+    this.JustU8 = 0;
+    this.MaybeU8 = null;
+    this.DefaultU8 = 42;
+    this.JustI16 = 0;
+    this.MaybeI16 = null;
+    this.DefaultI16 = 42;
+    this.JustU16 = 0;
+    this.MaybeU16 = null;
+    this.DefaultU16 = 42;
+    this.JustI32 = 0;
+    this.MaybeI32 = null;
+    this.DefaultI32 = 42;
+    this.JustU32 = 0;
+    this.MaybeU32 = null;
+    this.DefaultU32 = 42;
+    this.JustI64 = 0;
+    this.MaybeI64 = null;
+    this.DefaultI64 = 42;
+    this.JustU64 = 0;
+    this.MaybeU64 = null;
+    this.DefaultU64 = 42;
+    this.JustF32 = 0.0f;
+    this.MaybeF32 = null;
+    this.DefaultF32 = 42.0f;
+    this.JustF64 = 0.0;
+    this.MaybeF64 = null;
+    this.DefaultF64 = 42.0;
+    this.JustBool = false;
+    this.MaybeBool = null;
+    this.DefaultBool = true;
+    this.JustEnum = optional_scalars.OptionalByte.None;
+    this.MaybeEnum = null;
+    this.DefaultEnum = optional_scalars.OptionalByte.One;
+  }
+  public static ScalarStuffT DeserializeFromBinary(byte[] fbBuffer) {
+    return ScalarStuff.GetRootAsScalarStuff(new ByteBuffer(fbBuffer)).UnPack();
+  }
+  public byte[] SerializeToBinary() {
+    var fbb = new FlatBufferBuilder(0x10000);
+    ScalarStuff.FinishScalarStuffBuffer(fbb, ScalarStuff.Pack(fbb, this));
+    return fbb.DataBuffer.ToSizedArray();
+  }
+}
+
 
 }