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

namespace NamespaceC
{

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

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

  public NamespaceA.TableInFirstNS? ReferToA1 { get { int o = __p.__offset(4); return o != 0 ? (NamespaceA.TableInFirstNS?)(new NamespaceA.TableInFirstNS()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
  public NamespaceA.SecondTableInA? ReferToA2 { get { int o = __p.__offset(6); return o != 0 ? (NamespaceA.SecondTableInA?)(new NamespaceA.SecondTableInA()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }

  public static Offset<NamespaceC.TableInC> CreateTableInC(FlatBufferBuilder builder,
      Offset<NamespaceA.TableInFirstNS> refer_to_a1Offset = default(Offset<NamespaceA.TableInFirstNS>),
      Offset<NamespaceA.SecondTableInA> refer_to_a2Offset = default(Offset<NamespaceA.SecondTableInA>)) {
    builder.StartTable(2);
    TableInC.AddReferToA2(builder, refer_to_a2Offset);
    TableInC.AddReferToA1(builder, refer_to_a1Offset);
    return TableInC.EndTableInC(builder);
  }

  public static void StartTableInC(FlatBufferBuilder builder) { builder.StartTable(2); }
  public static void AddReferToA1(FlatBufferBuilder builder, Offset<NamespaceA.TableInFirstNS> referToA1Offset) { builder.AddOffset(0, referToA1Offset.Value, 0); }
  public static void AddReferToA2(FlatBufferBuilder builder, Offset<NamespaceA.SecondTableInA> referToA2Offset) { builder.AddOffset(1, referToA2Offset.Value, 0); }
  public static Offset<NamespaceC.TableInC> EndTableInC(FlatBufferBuilder builder) {
    int o = builder.EndTable();
    return new Offset<NamespaceC.TableInC>(o);
  }
  public TableInCT UnPack() {
    var _o = new TableInCT();
    this.UnPackTo(_o);
    return _o;
  }
  public void UnPackTo(TableInCT _o) {
    _o.ReferToA1 = this.ReferToA1.HasValue ? this.ReferToA1.Value.UnPack() : null;
    _o.ReferToA2 = this.ReferToA2.HasValue ? this.ReferToA2.Value.UnPack() : null;
  }
  public static Offset<NamespaceC.TableInC> Pack(FlatBufferBuilder builder, TableInCT _o) {
    if (_o == null) return default(Offset<NamespaceC.TableInC>);
    var _refer_to_a1 = _o.ReferToA1 == null ? default(Offset<NamespaceA.TableInFirstNS>) : NamespaceA.TableInFirstNS.Pack(builder, _o.ReferToA1);
    var _refer_to_a2 = _o.ReferToA2 == null ? default(Offset<NamespaceA.SecondTableInA>) : NamespaceA.SecondTableInA.Pack(builder, _o.ReferToA2);
    return CreateTableInC(
      builder,
      _refer_to_a1,
      _refer_to_a2);
  }
}

public class TableInCT
{
  [Newtonsoft.Json.JsonProperty("refer_to_a1")]
  public NamespaceA.TableInFirstNST ReferToA1 { get; set; }
  [Newtonsoft.Json.JsonProperty("refer_to_a2")]
  public NamespaceA.SecondTableInAT ReferToA2 { get; set; }

  public TableInCT() {
    this.ReferToA1 = null;
    this.ReferToA2 = null;
  }
}


static public class TableInCVerify
{
  static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
  {
    return verifier.VerifyTableStart(tablePos)
      && verifier.VerifyTable(tablePos, 4 /*ReferToA1*/, NamespaceA.TableInFirstNSVerify.Verify, false)
      && verifier.VerifyTable(tablePos, 6 /*ReferToA2*/, NamespaceA.SecondTableInAVerify.Verify, false)
      && verifier.VerifyTableEnd(tablePos);
  }
}

}
