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

  public short A { get { return __p.bb.GetShort(__p.bb_pos + 0); } }
  public void MutateA(short a) { __p.bb.PutShort(__p.bb_pos + 0, a); }
  public sbyte B { get { return __p.bb.GetSbyte(__p.bb_pos + 2); } }
  public void MutateB(sbyte b) { __p.bb.PutSbyte(__p.bb_pos + 2, b); }

  public static Offset<MyGame.Example.Test> CreateTest(FlatBufferBuilder builder, short A, sbyte B) {
    builder.Prep(2, 4);
    builder.Pad(1);
    builder.PutSbyte(B);
    builder.PutShort(A);
    return new Offset<MyGame.Example.Test>(builder.Offset);
  }
  public TestT UnPack() {
    var _o = new TestT();
    this.UnPackTo(_o);
    return _o;
  }
  public void UnPackTo(TestT _o) {
    _o.A = this.A;
    _o.B = this.B;
  }
  public static Offset<MyGame.Example.Test> Pack(FlatBufferBuilder builder, TestT _o) {
    if (_o == null) return default(Offset<MyGame.Example.Test>);
    return CreateTest(
      builder,
      _o.A,
      _o.B);
  }
}

public class TestT
{
  [Newtonsoft.Json.JsonProperty("a")]
  public short A { get; set; }
  [Newtonsoft.Json.JsonProperty("b")]
  public sbyte B { get; set; }

  public TestT() {
    this.A = 0;
    this.B = 0;
  }
}


}
