// <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_25(); }
  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);
  }
}

}
