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

namespace MyGame.Example
{

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

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

  public ulong Id { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetUlong(o + __p.bb_pos) : (ulong)0; } }
  public bool MutateId(ulong id) { int o = __p.__offset(4); if (o != 0) { __p.bb.PutUlong(o + __p.bb_pos, id); return true; } else { return false; } }

  public static Offset<MyGame.Example.Referrable> CreateReferrable(FlatBufferBuilder builder,
      ulong id = 0) {
    builder.StartTable(1);
    Referrable.AddId(builder, id);
    return Referrable.EndReferrable(builder);
  }

  public static void StartReferrable(FlatBufferBuilder builder) { builder.StartTable(1); }
  public static void AddId(FlatBufferBuilder builder, ulong id) { builder.AddUlong(0, id, 0); }
  public static Offset<MyGame.Example.Referrable> EndReferrable(FlatBufferBuilder builder) {
    int o = builder.EndTable();
    return new Offset<MyGame.Example.Referrable>(o);
  }

  public static VectorOffset CreateSortedVectorOfReferrable(FlatBufferBuilder builder, Offset<Referrable>[] offsets) {
    Array.Sort(offsets,
      (Offset<Referrable> o1, Offset<Referrable> o2) =>
        new Referrable().__assign(builder.DataBuffer.Length - o1.Value, builder.DataBuffer).Id.CompareTo(new Referrable().__assign(builder.DataBuffer.Length - o2.Value, builder.DataBuffer).Id));
    return builder.CreateVectorOfTables(offsets);
  }

  public static Referrable? __lookup_by_key(int vectorLocation, ulong key, ByteBuffer bb) {
    Referrable obj_ = new Referrable();
    int span = bb.GetInt(vectorLocation - 4);
    int start = 0;
    while (span != 0) {
      int middle = span / 2;
      int tableOffset = Table.__indirect(vectorLocation + 4 * (start + middle), bb);
      obj_.__assign(tableOffset, bb);
      int comp = obj_.Id.CompareTo(key);
      if (comp > 0) {
        span = middle;
      } else if (comp < 0) {
        middle++;
        start += middle;
        span -= middle;
      } else {
        return obj_;
      }
    }
    return null;
  }
  public ReferrableT UnPack() {
    var _o = new ReferrableT();
    this.UnPackTo(_o);
    return _o;
  }
  public void UnPackTo(ReferrableT _o) {
    _o.Id = this.Id;
  }
  public static Offset<MyGame.Example.Referrable> Pack(FlatBufferBuilder builder, ReferrableT _o) {
    if (_o == null) return default(Offset<MyGame.Example.Referrable>);
    return CreateReferrable(
      builder,
      _o.Id);
  }
}

public class ReferrableT
{
  [Newtonsoft.Json.JsonProperty("id")]
  [Newtonsoft.Json.JsonIgnore()]
  public ulong Id { get; set; }

  public ReferrableT() {
    this.Id = 0;
  }
}


static public class ReferrableVerify
{
  static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
  {
    return verifier.VerifyTableStart(tablePos)
      && verifier.VerifyField(tablePos, 4 /*Id*/, 8 /*ulong*/, 8, false)
      && verifier.VerifyTableEnd(tablePos);
  }
}

}
