// <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 TypeAliases : IFlatbufferObject
{
  private Table __p;
  public ByteBuffer ByteBuffer { get { return __p.bb; } }
  public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_23_5_26(); }
  public static TypeAliases GetRootAsTypeAliases(ByteBuffer _bb) { return GetRootAsTypeAliases(_bb, new TypeAliases()); }
  public static TypeAliases GetRootAsTypeAliases(ByteBuffer _bb, TypeAliases obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
  public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
  public TypeAliases __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }

  public sbyte I8 { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetSbyte(o + __p.bb_pos) : (sbyte)0; } }
  public bool MutateI8(sbyte i8) { int o = __p.__offset(4); if (o != 0) { __p.bb.PutSbyte(o + __p.bb_pos, i8); return true; } else { return false; } }
  public byte U8 { get { int o = __p.__offset(6); return o != 0 ? __p.bb.Get(o + __p.bb_pos) : (byte)0; } }
  public bool MutateU8(byte u8) { int o = __p.__offset(6); if (o != 0) { __p.bb.Put(o + __p.bb_pos, u8); return true; } else { return false; } }
  public short I16 { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetShort(o + __p.bb_pos) : (short)0; } }
  public bool MutateI16(short i16) { int o = __p.__offset(8); if (o != 0) { __p.bb.PutShort(o + __p.bb_pos, i16); return true; } else { return false; } }
  public ushort U16 { get { int o = __p.__offset(10); return o != 0 ? __p.bb.GetUshort(o + __p.bb_pos) : (ushort)0; } }
  public bool MutateU16(ushort u16) { int o = __p.__offset(10); if (o != 0) { __p.bb.PutUshort(o + __p.bb_pos, u16); return true; } else { return false; } }
  public int I32 { get { int o = __p.__offset(12); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } }
  public bool MutateI32(int i32) { int o = __p.__offset(12); if (o != 0) { __p.bb.PutInt(o + __p.bb_pos, i32); return true; } else { return false; } }
  public uint U32 { get { int o = __p.__offset(14); return o != 0 ? __p.bb.GetUint(o + __p.bb_pos) : (uint)0; } }
  public bool MutateU32(uint u32) { int o = __p.__offset(14); if (o != 0) { __p.bb.PutUint(o + __p.bb_pos, u32); return true; } else { return false; } }
  public long I64 { get { int o = __p.__offset(16); return o != 0 ? __p.bb.GetLong(o + __p.bb_pos) : (long)0; } }
  public bool MutateI64(long i64) { int o = __p.__offset(16); if (o != 0) { __p.bb.PutLong(o + __p.bb_pos, i64); return true; } else { return false; } }
  public ulong U64 { get { int o = __p.__offset(18); return o != 0 ? __p.bb.GetUlong(o + __p.bb_pos) : (ulong)0; } }
  public bool MutateU64(ulong u64) { int o = __p.__offset(18); if (o != 0) { __p.bb.PutUlong(o + __p.bb_pos, u64); return true; } else { return false; } }
  public float F32 { get { int o = __p.__offset(20); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)0.0f; } }
  public bool MutateF32(float f32) { int o = __p.__offset(20); if (o != 0) { __p.bb.PutFloat(o + __p.bb_pos, f32); return true; } else { return false; } }
  public double F64 { get { int o = __p.__offset(22); return o != 0 ? __p.bb.GetDouble(o + __p.bb_pos) : (double)0.0; } }
  public bool MutateF64(double f64) { int o = __p.__offset(22); if (o != 0) { __p.bb.PutDouble(o + __p.bb_pos, f64); return true; } else { return false; } }
  public sbyte V8(int j) { int o = __p.__offset(24); return o != 0 ? __p.bb.GetSbyte(__p.__vector(o) + j * 1) : (sbyte)0; }
  public int V8Length { get { int o = __p.__offset(24); return o != 0 ? __p.__vector_len(o) : 0; } }
#if ENABLE_SPAN_T
  public Span<sbyte> GetV8Bytes() { return __p.__vector_as_span<sbyte>(24, 1); }
#else
  public ArraySegment<byte>? GetV8Bytes() { return __p.__vector_as_arraysegment(24); }
#endif
  public sbyte[] GetV8Array() { return __p.__vector_as_array<sbyte>(24); }
  public bool MutateV8(int j, sbyte v8) { int o = __p.__offset(24); if (o != 0) { __p.bb.PutSbyte(__p.__vector(o) + j * 1, v8); return true; } else { return false; } }
  public double Vf64(int j) { int o = __p.__offset(26); return o != 0 ? __p.bb.GetDouble(__p.__vector(o) + j * 8) : (double)0; }
  public int Vf64Length { get { int o = __p.__offset(26); return o != 0 ? __p.__vector_len(o) : 0; } }
#if ENABLE_SPAN_T
  public Span<double> GetVf64Bytes() { return __p.__vector_as_span<double>(26, 8); }
#else
  public ArraySegment<byte>? GetVf64Bytes() { return __p.__vector_as_arraysegment(26); }
#endif
  public double[] GetVf64Array() { return __p.__vector_as_array<double>(26); }
  public bool MutateVf64(int j, double vf64) { int o = __p.__offset(26); if (o != 0) { __p.bb.PutDouble(__p.__vector(o) + j * 8, vf64); return true; } else { return false; } }

  public static Offset<MyGame.Example.TypeAliases> CreateTypeAliases(FlatBufferBuilder builder,
      sbyte i8 = 0,
      byte u8 = 0,
      short i16 = 0,
      ushort u16 = 0,
      int i32 = 0,
      uint u32 = 0,
      long i64 = 0,
      ulong u64 = 0,
      float f32 = 0.0f,
      double f64 = 0.0,
      VectorOffset v8Offset = default(VectorOffset),
      VectorOffset vf64Offset = default(VectorOffset)) {
    builder.StartTable(12);
    TypeAliases.AddF64(builder, f64);
    TypeAliases.AddU64(builder, u64);
    TypeAliases.AddI64(builder, i64);
    TypeAliases.AddVf64(builder, vf64Offset);
    TypeAliases.AddV8(builder, v8Offset);
    TypeAliases.AddF32(builder, f32);
    TypeAliases.AddU32(builder, u32);
    TypeAliases.AddI32(builder, i32);
    TypeAliases.AddU16(builder, u16);
    TypeAliases.AddI16(builder, i16);
    TypeAliases.AddU8(builder, u8);
    TypeAliases.AddI8(builder, i8);
    return TypeAliases.EndTypeAliases(builder);
  }

  public static void StartTypeAliases(FlatBufferBuilder builder) { builder.StartTable(12); }
  public static void AddI8(FlatBufferBuilder builder, sbyte i8) { builder.AddSbyte(0, i8, 0); }
  public static void AddU8(FlatBufferBuilder builder, byte u8) { builder.AddByte(1, u8, 0); }
  public static void AddI16(FlatBufferBuilder builder, short i16) { builder.AddShort(2, i16, 0); }
  public static void AddU16(FlatBufferBuilder builder, ushort u16) { builder.AddUshort(3, u16, 0); }
  public static void AddI32(FlatBufferBuilder builder, int i32) { builder.AddInt(4, i32, 0); }
  public static void AddU32(FlatBufferBuilder builder, uint u32) { builder.AddUint(5, u32, 0); }
  public static void AddI64(FlatBufferBuilder builder, long i64) { builder.AddLong(6, i64, 0); }
  public static void AddU64(FlatBufferBuilder builder, ulong u64) { builder.AddUlong(7, u64, 0); }
  public static void AddF32(FlatBufferBuilder builder, float f32) { builder.AddFloat(8, f32, 0.0f); }
  public static void AddF64(FlatBufferBuilder builder, double f64) { builder.AddDouble(9, f64, 0.0); }
  public static void AddV8(FlatBufferBuilder builder, VectorOffset v8Offset) { builder.AddOffset(10, v8Offset.Value, 0); }
  public static VectorOffset CreateV8Vector(FlatBufferBuilder builder, sbyte[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddSbyte(data[i]); return builder.EndVector(); }
  public static VectorOffset CreateV8VectorBlock(FlatBufferBuilder builder, sbyte[] data) { builder.StartVector(1, data.Length, 1); builder.Add(data); return builder.EndVector(); }
  public static VectorOffset CreateV8VectorBlock(FlatBufferBuilder builder, ArraySegment<sbyte> data) { builder.StartVector(1, data.Count, 1); builder.Add(data); return builder.EndVector(); }
  public static VectorOffset CreateV8VectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add<sbyte>(dataPtr, sizeInBytes); return builder.EndVector(); }
  public static void StartV8Vector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); }
  public static void AddVf64(FlatBufferBuilder builder, VectorOffset vf64Offset) { builder.AddOffset(11, vf64Offset.Value, 0); }
  public static VectorOffset CreateVf64Vector(FlatBufferBuilder builder, double[] data) { builder.StartVector(8, data.Length, 8); for (int i = data.Length - 1; i >= 0; i--) builder.AddDouble(data[i]); return builder.EndVector(); }
  public static VectorOffset CreateVf64VectorBlock(FlatBufferBuilder builder, double[] data) { builder.StartVector(8, data.Length, 8); builder.Add(data); return builder.EndVector(); }
  public static VectorOffset CreateVf64VectorBlock(FlatBufferBuilder builder, ArraySegment<double> data) { builder.StartVector(8, data.Count, 8); builder.Add(data); return builder.EndVector(); }
  public static VectorOffset CreateVf64VectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add<double>(dataPtr, sizeInBytes); return builder.EndVector(); }
  public static void StartVf64Vector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 8); }
  public static Offset<MyGame.Example.TypeAliases> EndTypeAliases(FlatBufferBuilder builder) {
    int o = builder.EndTable();
    return new Offset<MyGame.Example.TypeAliases>(o);
  }
  public TypeAliasesT UnPack() {
    var _o = new TypeAliasesT();
    this.UnPackTo(_o);
    return _o;
  }
  public void UnPackTo(TypeAliasesT _o) {
    _o.I8 = this.I8;
    _o.U8 = this.U8;
    _o.I16 = this.I16;
    _o.U16 = this.U16;
    _o.I32 = this.I32;
    _o.U32 = this.U32;
    _o.I64 = this.I64;
    _o.U64 = this.U64;
    _o.F32 = this.F32;
    _o.F64 = this.F64;
    _o.V8 = new List<sbyte>();
    for (var _j = 0; _j < this.V8Length; ++_j) {_o.V8.Add(this.V8(_j));}
    _o.Vf64 = new List<double>();
    for (var _j = 0; _j < this.Vf64Length; ++_j) {_o.Vf64.Add(this.Vf64(_j));}
  }
  public static Offset<MyGame.Example.TypeAliases> Pack(FlatBufferBuilder builder, TypeAliasesT _o) {
    if (_o == null) return default(Offset<MyGame.Example.TypeAliases>);
    var _v8 = default(VectorOffset);
    if (_o.V8 != null) {
      var __v8 = _o.V8.ToArray();
      _v8 = CreateV8Vector(builder, __v8);
    }
    var _vf64 = default(VectorOffset);
    if (_o.Vf64 != null) {
      var __vf64 = _o.Vf64.ToArray();
      _vf64 = CreateVf64Vector(builder, __vf64);
    }
    return CreateTypeAliases(
      builder,
      _o.I8,
      _o.U8,
      _o.I16,
      _o.U16,
      _o.I32,
      _o.U32,
      _o.I64,
      _o.U64,
      _o.F32,
      _o.F64,
      _v8,
      _vf64);
  }
}

public class TypeAliasesT
{
  [Newtonsoft.Json.JsonProperty("i8")]
  public sbyte I8 { get; set; }
  [Newtonsoft.Json.JsonProperty("u8")]
  public byte U8 { get; set; }
  [Newtonsoft.Json.JsonProperty("i16")]
  public short I16 { get; set; }
  [Newtonsoft.Json.JsonProperty("u16")]
  public ushort U16 { get; set; }
  [Newtonsoft.Json.JsonProperty("i32")]
  public int I32 { get; set; }
  [Newtonsoft.Json.JsonProperty("u32")]
  public uint U32 { get; set; }
  [Newtonsoft.Json.JsonProperty("i64")]
  public long I64 { get; set; }
  [Newtonsoft.Json.JsonProperty("u64")]
  public ulong U64 { get; set; }
  [Newtonsoft.Json.JsonProperty("f32")]
  public float F32 { get; set; }
  [Newtonsoft.Json.JsonProperty("f64")]
  public double F64 { get; set; }
  [Newtonsoft.Json.JsonProperty("v8")]
  public List<sbyte> V8 { get; set; }
  [Newtonsoft.Json.JsonProperty("vf64")]
  public List<double> Vf64 { get; set; }

  public TypeAliasesT() {
    this.I8 = 0;
    this.U8 = 0;
    this.I16 = 0;
    this.U16 = 0;
    this.I32 = 0;
    this.U32 = 0;
    this.I64 = 0;
    this.U64 = 0;
    this.F32 = 0.0f;
    this.F64 = 0.0;
    this.V8 = null;
    this.Vf64 = null;
  }
}


static public class TypeAliasesVerify
{
  static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
  {
    return verifier.VerifyTableStart(tablePos)
      && verifier.VerifyField(tablePos, 4 /*I8*/, 1 /*sbyte*/, 1, false)
      && verifier.VerifyField(tablePos, 6 /*U8*/, 1 /*byte*/, 1, false)
      && verifier.VerifyField(tablePos, 8 /*I16*/, 2 /*short*/, 2, false)
      && verifier.VerifyField(tablePos, 10 /*U16*/, 2 /*ushort*/, 2, false)
      && verifier.VerifyField(tablePos, 12 /*I32*/, 4 /*int*/, 4, false)
      && verifier.VerifyField(tablePos, 14 /*U32*/, 4 /*uint*/, 4, false)
      && verifier.VerifyField(tablePos, 16 /*I64*/, 8 /*long*/, 8, false)
      && verifier.VerifyField(tablePos, 18 /*U64*/, 8 /*ulong*/, 8, false)
      && verifier.VerifyField(tablePos, 20 /*F32*/, 4 /*float*/, 4, false)
      && verifier.VerifyField(tablePos, 22 /*F64*/, 8 /*double*/, 8, false)
      && verifier.VerifyVectorOfData(tablePos, 24 /*V8*/, 1 /*sbyte*/, false)
      && verifier.VerifyVectorOfData(tablePos, 26 /*Vf64*/, 8 /*double*/, false)
      && verifier.VerifyTableEnd(tablePos);
  }
}

}
