// <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 NestedStruct : IFlatbufferObject
{
  private Struct __p;
  public ByteBuffer ByteBuffer { get { return __p.bb; } }
  public void __init(int _i, ByteBuffer _bb) { __p = new Struct(_i, _bb); }
  public NestedStruct __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }

  public int A(int j) { return __p.bb.GetInt(__p.bb_pos + 0 + j * 4); }
  public const int ALength = 2;
#if ENABLE_SPAN_T
  public Span<int> GetABytes() { return System.Runtime.InteropServices.MemoryMarshal.Cast<byte, int>(__p.bb.ToSpan(__p.bb_pos + 0, 8)); }
#else
  public ArraySegment<byte>? GetABytes() { return __p.bb.ToArraySegment(__p.bb_pos + 0, 8);}
#endif
  public void MutateA(int j, int a) { __p.bb.PutInt(__p.bb_pos + 0 + j * 4, a); }
  public MyGame.Example.TestEnum B { get { return (MyGame.Example.TestEnum)__p.bb.GetSbyte(__p.bb_pos + 8); } }
  public void MutateB(MyGame.Example.TestEnum b) { __p.bb.PutSbyte(__p.bb_pos + 8, (sbyte)b); }
  public MyGame.Example.TestEnum C(int j) { return (MyGame.Example.TestEnum)__p.bb.GetSbyte(__p.bb_pos + 9 + j * 1); }
  public const int CLength = 2;
#if ENABLE_SPAN_T
  public Span<MyGame.Example.TestEnum> GetCBytes() { return System.Runtime.InteropServices.MemoryMarshal.Cast<byte, MyGame.Example.TestEnum>(__p.bb.ToSpan(__p.bb_pos + 9, 2)); }
#else
  public ArraySegment<byte>? GetCBytes() { return __p.bb.ToArraySegment(__p.bb_pos + 9, 2);}
#endif
  public void MutateC(int j, MyGame.Example.TestEnum c) { __p.bb.PutSbyte(__p.bb_pos + 9 + j * 1, (sbyte)c); }
  public long D(int j) { return __p.bb.GetLong(__p.bb_pos + 16 + j * 8); }
  public const int DLength = 2;
#if ENABLE_SPAN_T
  public Span<long> GetDBytes() { return System.Runtime.InteropServices.MemoryMarshal.Cast<byte, long>(__p.bb.ToSpan(__p.bb_pos + 16, 16)); }
#else
  public ArraySegment<byte>? GetDBytes() { return __p.bb.ToArraySegment(__p.bb_pos + 16, 16);}
#endif
  public void MutateD(int j, long d) { __p.bb.PutLong(__p.bb_pos + 16 + j * 8, d); }

  public static Offset<MyGame.Example.NestedStruct> CreateNestedStruct(FlatBufferBuilder builder, int[] A, MyGame.Example.TestEnum B, MyGame.Example.TestEnum[] C, long[] D) {
    builder.Prep(8, 32);
    for (int _idx0 = 2; _idx0 > 0; _idx0--) {
      builder.PutLong(D[_idx0-1]);
    }
    builder.Pad(5);
    for (int _idx0 = 2; _idx0 > 0; _idx0--) {
      builder.PutSbyte((sbyte)C[_idx0-1]);
    }
    builder.PutSbyte((sbyte)B);
    for (int _idx0 = 2; _idx0 > 0; _idx0--) {
      builder.PutInt(A[_idx0-1]);
    }
    return new Offset<MyGame.Example.NestedStruct>(builder.Offset);
  }
  public NestedStructT UnPack() {
    var _o = new NestedStructT();
    this.UnPackTo(_o);
    return _o;
  }
  public void UnPackTo(NestedStructT _o) {
    _o.A = new int[2];
    for (var _j = 0; _j < 2; ++_j) { _o.A[_j] = this.A(_j); }
    _o.B = this.B;
    _o.C = new MyGame.Example.TestEnum[2];
    for (var _j = 0; _j < 2; ++_j) { _o.C[_j] = this.C(_j); }
    _o.D = new long[2];
    for (var _j = 0; _j < 2; ++_j) { _o.D[_j] = this.D(_j); }
  }
  public static Offset<MyGame.Example.NestedStruct> Pack(FlatBufferBuilder builder, NestedStructT _o) {
    if (_o == null) return default(Offset<MyGame.Example.NestedStruct>);
    var _a = _o.A;
    var _c = _o.C;
    var _d = _o.D;
    return CreateNestedStruct(
      builder,
      _a,
      _o.B,
      _c,
      _d);
  }
}

public class NestedStructT
{
  [Newtonsoft.Json.JsonProperty("a")]
  public int[] A { get; set; }
  [Newtonsoft.Json.JsonProperty("b")]
  public MyGame.Example.TestEnum B { get; set; }
  [Newtonsoft.Json.JsonProperty("c")]
  public MyGame.Example.TestEnum[] C { get; set; }
  [Newtonsoft.Json.JsonProperty("d")]
  public long[] D { get; set; }

  public NestedStructT() {
    this.A = new int[2];
    this.B = MyGame.Example.TestEnum.A;
    this.C = new MyGame.Example.TestEnum[2];
    this.D = new long[2];
  }
}


}
