// <auto-generated>
//  automatically generated by the FlatBuffers compiler, do not modify
// </auto-generated>

namespace KeywordTest
{

using global::System;
using global::System.Collections.Generic;
using global::Google.FlatBuffers;

public struct KeywordsInTable : IFlatbufferObject
{
  private Table __p;
  public ByteBuffer ByteBuffer { get { return __p.bb; } }
  public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_24_3_25(); }
  public static KeywordsInTable GetRootAsKeywordsInTable(ByteBuffer _bb) { return GetRootAsKeywordsInTable(_bb, new KeywordsInTable()); }
  public static KeywordsInTable GetRootAsKeywordsInTable(ByteBuffer _bb, KeywordsInTable obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
  public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
  public KeywordsInTable __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }

  public KeywordTest.ABC Is { get { int o = __p.__offset(4); return o != 0 ? (KeywordTest.ABC)__p.bb.GetInt(o + __p.bb_pos) : KeywordTest.ABC.@void; } }
  public bool MutateIs(KeywordTest.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 KeywordTest.@public Private { get { int o = __p.__offset(6); return o != 0 ? (KeywordTest.@public)__p.bb.GetInt(o + __p.bb_pos) : KeywordTest.@public.NONE; } }
  public bool MutatePrivate(KeywordTest.@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 bool Default { get { int o = __p.__offset(10); return o != 0 ? 0!=__p.bb.Get(o + __p.bb_pos) : (bool)false; } }
  public bool MutateDefault(bool @default) { int o = __p.__offset(10); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (byte)(@default ? 1 : 0)); return true; } else { return false; } }

  public static Offset<KeywordTest.KeywordsInTable> CreateKeywordsInTable(FlatBufferBuilder builder,
      KeywordTest.ABC @is = KeywordTest.ABC.@void,
      KeywordTest.@public @private = KeywordTest.@public.NONE,
      int type = 0,
      bool @default = false) {
    builder.StartTable(4);
    KeywordsInTable.AddType(builder, type);
    KeywordsInTable.AddPrivate(builder, @private);
    KeywordsInTable.AddIs(builder, @is);
    KeywordsInTable.AddDefault(builder, @default);
    return KeywordsInTable.EndKeywordsInTable(builder);
  }

  public static void StartKeywordsInTable(FlatBufferBuilder builder) { builder.StartTable(4); }
  public static void AddIs(FlatBufferBuilder builder, KeywordTest.ABC @is) { builder.AddInt(0, (int)@is, 0); }
  public static void AddPrivate(FlatBufferBuilder builder, KeywordTest.@public @private) { builder.AddInt(1, (int)@private, 0); }
  public static void AddType(FlatBufferBuilder builder, int type) { builder.AddInt(2, type, 0); }
  public static void AddDefault(FlatBufferBuilder builder, bool @default) { builder.AddBool(3, @default, false); }
  public static Offset<KeywordTest.KeywordsInTable> EndKeywordsInTable(FlatBufferBuilder builder) {
    int o = builder.EndTable();
    return new Offset<KeywordTest.KeywordsInTable>(o);
  }
  public KeywordsInTableT UnPack() {
    var _o = new KeywordsInTableT();
    this.UnPackTo(_o);
    return _o;
  }
  public void UnPackTo(KeywordsInTableT _o) {
    _o.Is = this.Is;
    _o.Private = this.Private;
    _o.Type = this.Type;
    _o.Default = this.Default;
  }
  public static Offset<KeywordTest.KeywordsInTable> Pack(FlatBufferBuilder builder, KeywordsInTableT _o) {
    if (_o == null) return default(Offset<KeywordTest.KeywordsInTable>);
    return CreateKeywordsInTable(
      builder,
      _o.Is,
      _o.Private,
      _o.Type,
      _o.Default);
  }
}

public class KeywordsInTableT
{
  [Newtonsoft.Json.JsonProperty("is")]
  public KeywordTest.ABC Is { get; set; }
  [Newtonsoft.Json.JsonProperty("private")]
  public KeywordTest.@public Private { get; set; }
  [Newtonsoft.Json.JsonProperty("type")]
  public int Type { get; set; }
  [Newtonsoft.Json.JsonProperty("default")]
  public bool Default { get; set; }

  public KeywordsInTableT() {
    this.Is = KeywordTest.ABC.@void;
    this.Private = KeywordTest.@public.NONE;
    this.Type = 0;
    this.Default = false;
  }
}


static public class KeywordsInTableVerify
{
  static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
  {
    return verifier.VerifyTableStart(tablePos)
      && verifier.VerifyField(tablePos, 4 /*Is*/, 4 /*KeywordTest.ABC*/, 4, false)
      && verifier.VerifyField(tablePos, 6 /*Private*/, 4 /*KeywordTest.@public*/, 4, false)
      && verifier.VerifyField(tablePos, 8 /*Type*/, 4 /*int*/, 4, false)
      && verifier.VerifyField(tablePos, 10 /*Default*/, 1 /*bool*/, 1, false)
      && verifier.VerifyTableEnd(tablePos);
  }
}

}
