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

namespace union_value_collsion
{

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

[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
public enum Value : byte
{
  NONE = 0,
  IntValue = 1,
};

public class ValueUnion {
  public Value Type { get; set; }
  public object Value_ { get; set; }

  public ValueUnion() {
    this.Type = Value.NONE;
    this.Value_ = null;
  }

  public T As<T>() where T : class { return this.Value_ as T; }
  public union_value_collsion.IntValueT AsIntValue() { return this.As<union_value_collsion.IntValueT>(); }
  public static ValueUnion FromIntValue(union_value_collsion.IntValueT _intvalue) { return new ValueUnion{ Type = Value.IntValue, Value_ = _intvalue }; }

  public static int Pack(Google.FlatBuffers.FlatBufferBuilder builder, ValueUnion _o) {
    switch (_o.Type) {
      default: return 0;
      case Value.IntValue: return union_value_collsion.IntValue.Pack(builder, _o.AsIntValue()).Value;
    }
  }
}

public class ValueUnion_JsonConverter : Newtonsoft.Json.JsonConverter {
  public override bool CanConvert(System.Type objectType) {
    return objectType == typeof(ValueUnion) || objectType == typeof(System.Collections.Generic.List<ValueUnion>);
  }
  public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) {
    var _olist = value as System.Collections.Generic.List<ValueUnion>;
    if (_olist != null) {
      writer.WriteStartArray();
      foreach (var _o in _olist) { this.WriteJson(writer, _o, serializer); }
      writer.WriteEndArray();
    } else {
      this.WriteJson(writer, value as ValueUnion, serializer);
    }
  }
  public void WriteJson(Newtonsoft.Json.JsonWriter writer, ValueUnion _o, Newtonsoft.Json.JsonSerializer serializer) {
    if (_o == null) return;
    serializer.Serialize(writer, _o.Value_);
  }
  public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) {
    var _olist = existingValue as System.Collections.Generic.List<ValueUnion>;
    if (_olist != null) {
      for (var _j = 0; _j < _olist.Count; ++_j) {
        reader.Read();
        _olist[_j] = this.ReadJson(reader, _olist[_j], serializer);
      }
      reader.Read();
      return _olist;
    } else {
      return this.ReadJson(reader, existingValue as ValueUnion, serializer);
    }
  }
  public ValueUnion ReadJson(Newtonsoft.Json.JsonReader reader, ValueUnion _o, Newtonsoft.Json.JsonSerializer serializer) {
    if (_o == null) return null;
    switch (_o.Type) {
      default: break;
      case Value.IntValue: _o.Value_ = serializer.Deserialize<union_value_collsion.IntValueT>(reader); break;
    }
    return _o;
  }
}



static public class ValueVerify
{
  static public bool Verify(Google.FlatBuffers.Verifier verifier, byte typeId, uint tablePos)
  {
    bool result = true;
    switch((Value)typeId)
    {
      case Value.IntValue:
        result = union_value_collsion.IntValueVerify.Verify(verifier, tablePos);
        break;
      default: result = true;
        break;
    }
    return result;
  }
}

[Newtonsoft.Json.JsonConverter(typeof(Newtonsoft.Json.Converters.StringEnumConverter))]
public enum Other : byte
{
  NONE = 0,
  IntValue = 1,
};

public class OtherUnion {
  public Other Type { get; set; }
  public object Value { get; set; }

  public OtherUnion() {
    this.Type = Other.NONE;
    this.Value = null;
  }

  public T As<T>() where T : class { return this.Value as T; }
  public union_value_collsion.IntValueT AsIntValue() { return this.As<union_value_collsion.IntValueT>(); }
  public static OtherUnion FromIntValue(union_value_collsion.IntValueT _intvalue) { return new OtherUnion{ Type = Other.IntValue, Value = _intvalue }; }

  public static int Pack(Google.FlatBuffers.FlatBufferBuilder builder, OtherUnion _o) {
    switch (_o.Type) {
      default: return 0;
      case Other.IntValue: return union_value_collsion.IntValue.Pack(builder, _o.AsIntValue()).Value;
    }
  }
}

public class OtherUnion_JsonConverter : Newtonsoft.Json.JsonConverter {
  public override bool CanConvert(System.Type objectType) {
    return objectType == typeof(OtherUnion) || objectType == typeof(System.Collections.Generic.List<OtherUnion>);
  }
  public override void WriteJson(Newtonsoft.Json.JsonWriter writer, object value, Newtonsoft.Json.JsonSerializer serializer) {
    var _olist = value as System.Collections.Generic.List<OtherUnion>;
    if (_olist != null) {
      writer.WriteStartArray();
      foreach (var _o in _olist) { this.WriteJson(writer, _o, serializer); }
      writer.WriteEndArray();
    } else {
      this.WriteJson(writer, value as OtherUnion, serializer);
    }
  }
  public void WriteJson(Newtonsoft.Json.JsonWriter writer, OtherUnion _o, Newtonsoft.Json.JsonSerializer serializer) {
    if (_o == null) return;
    serializer.Serialize(writer, _o.Value);
  }
  public override object ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) {
    var _olist = existingValue as System.Collections.Generic.List<OtherUnion>;
    if (_olist != null) {
      for (var _j = 0; _j < _olist.Count; ++_j) {
        reader.Read();
        _olist[_j] = this.ReadJson(reader, _olist[_j], serializer);
      }
      reader.Read();
      return _olist;
    } else {
      return this.ReadJson(reader, existingValue as OtherUnion, serializer);
    }
  }
  public OtherUnion ReadJson(Newtonsoft.Json.JsonReader reader, OtherUnion _o, Newtonsoft.Json.JsonSerializer serializer) {
    if (_o == null) return null;
    switch (_o.Type) {
      default: break;
      case Other.IntValue: _o.Value = serializer.Deserialize<union_value_collsion.IntValueT>(reader); break;
    }
    return _o;
  }
}



static public class OtherVerify
{
  static public bool Verify(Google.FlatBuffers.Verifier verifier, byte typeId, uint tablePos)
  {
    bool result = true;
    switch((Other)typeId)
    {
      case Other.IntValue:
        result = union_value_collsion.IntValueVerify.Verify(verifier, tablePos);
        break;
      default: result = true;
        break;
    }
    return result;
  }
}

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

  public int Value { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } }

  public static Offset<union_value_collsion.IntValue> CreateIntValue(FlatBufferBuilder builder,
      int value = 0) {
    builder.StartTable(1);
    IntValue.AddValue(builder, value);
    return IntValue.EndIntValue(builder);
  }

  public static void StartIntValue(FlatBufferBuilder builder) { builder.StartTable(1); }
  public static void AddValue(FlatBufferBuilder builder, int value) { builder.AddInt(0, value, 0); }
  public static Offset<union_value_collsion.IntValue> EndIntValue(FlatBufferBuilder builder) {
    int o = builder.EndTable();
    return new Offset<union_value_collsion.IntValue>(o);
  }
  public IntValueT UnPack() {
    var _o = new IntValueT();
    this.UnPackTo(_o);
    return _o;
  }
  public void UnPackTo(IntValueT _o) {
    _o.Value = this.Value;
  }
  public static Offset<union_value_collsion.IntValue> Pack(FlatBufferBuilder builder, IntValueT _o) {
    if (_o == null) return default(Offset<union_value_collsion.IntValue>);
    return CreateIntValue(
      builder,
      _o.Value);
  }
}

public class IntValueT
{
  [Newtonsoft.Json.JsonProperty("value")]
  public int Value { get; set; }

  public IntValueT() {
    this.Value = 0;
  }
}


static public class IntValueVerify
{
  static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
  {
    return verifier.VerifyTableStart(tablePos)
      && verifier.VerifyField(tablePos, 4 /*Value*/, 4 /*int*/, 4, false)
      && verifier.VerifyTableEnd(tablePos);
  }
}
public struct Collide : IFlatbufferObject
{
  private Table __p;
  public ByteBuffer ByteBuffer { get { return __p.bb; } }
  public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_24_3_7(); }
  public static Collide GetRootAsCollide(ByteBuffer _bb) { return GetRootAsCollide(_bb, new Collide()); }
  public static Collide GetRootAsCollide(ByteBuffer _bb, Collide obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
  public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
  public Collide __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }

  public string Collide_ { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
  public Span<byte> GetCollideBytes() { return __p.__vector_as_span<byte>(4, 1); }
#else
  public ArraySegment<byte>? GetCollideBytes() { return __p.__vector_as_arraysegment(4); }
#endif
  public byte[] GetCollideArray() { return __p.__vector_as_array<byte>(4); }
  public string Value { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
  public Span<byte> GetValueBytes() { return __p.__vector_as_span<byte>(6, 1); }
#else
  public ArraySegment<byte>? GetValueBytes() { return __p.__vector_as_arraysegment(6); }
#endif
  public byte[] GetValueArray() { return __p.__vector_as_array<byte>(6); }

  public static Offset<union_value_collsion.Collide> CreateCollide(FlatBufferBuilder builder,
      StringOffset collideOffset = default(StringOffset),
      StringOffset valueOffset = default(StringOffset)) {
    builder.StartTable(2);
    Collide.AddValue(builder, valueOffset);
    Collide.AddCollide(builder, collideOffset);
    return Collide.EndCollide(builder);
  }

  public static void StartCollide(FlatBufferBuilder builder) { builder.StartTable(2); }
  public static void AddCollide(FlatBufferBuilder builder, StringOffset collideOffset) { builder.AddOffset(0, collideOffset.Value, 0); }
  public static void AddValue(FlatBufferBuilder builder, StringOffset valueOffset) { builder.AddOffset(1, valueOffset.Value, 0); }
  public static Offset<union_value_collsion.Collide> EndCollide(FlatBufferBuilder builder) {
    int o = builder.EndTable();
    builder.Required(o, 4);  // collide
    return new Offset<union_value_collsion.Collide>(o);
  }

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

  public static Collide? __lookup_by_key(int vectorLocation, string key, ByteBuffer bb) {
    Collide obj_ = new Collide();
    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_.Collide_.CompareTo(key);
      if (comp > 0) {
        span = middle;
      } else if (comp < 0) {
        middle++;
        start += middle;
        span -= middle;
      } else {
        return obj_;
      }
    }
    return null;
  }
  public CollideT UnPack() {
    var _o = new CollideT();
    this.UnPackTo(_o);
    return _o;
  }
  public void UnPackTo(CollideT _o) {
    _o.Collide_ = this.Collide_;
    _o.Value = this.Value;
  }
  public static Offset<union_value_collsion.Collide> Pack(FlatBufferBuilder builder, CollideT _o) {
    if (_o == null) return default(Offset<union_value_collsion.Collide>);
    var _collide = _o.Collide_ == null ? default(StringOffset) : builder.CreateString(_o.Collide_);
    var _value = _o.Value == null ? default(StringOffset) : builder.CreateString(_o.Value);
    return CreateCollide(
      builder,
      _collide,
      _value);
  }
}

public class CollideT
{
  [Newtonsoft.Json.JsonProperty("collide")]
  public string Collide_ { get; set; }
  [Newtonsoft.Json.JsonProperty("value")]
  public string Value { get; set; }

  public CollideT() {
    this.Collide_ = null;
    this.Value = null;
  }
}


static public class CollideVerify
{
  static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
  {
    return verifier.VerifyTableStart(tablePos)
      && verifier.VerifyString(tablePos, 4 /*Collide*/, true)
      && verifier.VerifyString(tablePos, 6 /*Value*/, false)
      && verifier.VerifyTableEnd(tablePos);
  }
}
public struct Collision : IFlatbufferObject
{
  private Table __p;
  public ByteBuffer ByteBuffer { get { return __p.bb; } }
  public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_24_3_7(); }
  public static Collision GetRootAsCollision(ByteBuffer _bb) { return GetRootAsCollision(_bb, new Collision()); }
  public static Collision GetRootAsCollision(ByteBuffer _bb, Collision obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
  public static bool VerifyCollision(ByteBuffer _bb) {Google.FlatBuffers.Verifier verifier = new Google.FlatBuffers.Verifier(_bb); return verifier.VerifyBuffer("", false, CollisionVerify.Verify); }
  public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
  public Collision __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }

  public union_value_collsion.Value SomeValueType { get { int o = __p.__offset(4); return o != 0 ? (union_value_collsion.Value)__p.bb.Get(o + __p.bb_pos) : union_value_collsion.Value.NONE; } }
  public TTable? SomeValue<TTable>() where TTable : struct, IFlatbufferObject { int o = __p.__offset(6); return o != 0 ? (TTable?)__p.__union<TTable>(o + __p.bb_pos) : null; }
  public union_value_collsion.IntValue SomeValueAsIntValue() { return SomeValue<union_value_collsion.IntValue>().Value; }
  public union_value_collsion.Other ValueType { get { int o = __p.__offset(8); return o != 0 ? (union_value_collsion.Other)__p.bb.Get(o + __p.bb_pos) : union_value_collsion.Other.NONE; } }
  public TTable? Value<TTable>() where TTable : struct, IFlatbufferObject { int o = __p.__offset(10); return o != 0 ? (TTable?)__p.__union<TTable>(o + __p.bb_pos) : null; }
  public union_value_collsion.IntValue ValueAsIntValue() { return Value<union_value_collsion.IntValue>().Value; }
  public union_value_collsion.Collision? Collide(int j) { int o = __p.__offset(12); return o != 0 ? (union_value_collsion.Collision?)(new union_value_collsion.Collision()).__assign(__p.__indirect(__p.__vector(o) + j * 4), __p.bb) : null; }
  public int CollideLength { get { int o = __p.__offset(12); return o != 0 ? __p.__vector_len(o) : 0; } }

  public static Offset<union_value_collsion.Collision> CreateCollision(FlatBufferBuilder builder,
      union_value_collsion.Value some_value_type = union_value_collsion.Value.NONE,
      int some_valueOffset = 0,
      union_value_collsion.Other value_type = union_value_collsion.Other.NONE,
      int valueOffset = 0,
      VectorOffset collideOffset = default(VectorOffset)) {
    builder.StartTable(5);
    Collision.AddCollide(builder, collideOffset);
    Collision.AddValue(builder, valueOffset);
    Collision.AddSomeValue(builder, some_valueOffset);
    Collision.AddValueType(builder, value_type);
    Collision.AddSomeValueType(builder, some_value_type);
    return Collision.EndCollision(builder);
  }

  public static void StartCollision(FlatBufferBuilder builder) { builder.StartTable(5); }
  public static void AddSomeValueType(FlatBufferBuilder builder, union_value_collsion.Value someValueType) { builder.AddByte(0, (byte)someValueType, 0); }
  public static void AddSomeValue(FlatBufferBuilder builder, int someValueOffset) { builder.AddOffset(1, someValueOffset, 0); }
  public static void AddValueType(FlatBufferBuilder builder, union_value_collsion.Other valueType) { builder.AddByte(2, (byte)valueType, 0); }
  public static void AddValue(FlatBufferBuilder builder, int valueOffset) { builder.AddOffset(3, valueOffset, 0); }
  public static void AddCollide(FlatBufferBuilder builder, VectorOffset collideOffset) { builder.AddOffset(4, collideOffset.Value, 0); }
  public static VectorOffset CreateCollideVector(FlatBufferBuilder builder, Offset<union_value_collsion.Collision>[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); }
  public static VectorOffset CreateCollideVectorBlock(FlatBufferBuilder builder, Offset<union_value_collsion.Collision>[] data) { builder.StartVector(4, data.Length, 4); builder.Add(data); return builder.EndVector(); }
  public static VectorOffset CreateCollideVectorBlock(FlatBufferBuilder builder, ArraySegment<Offset<union_value_collsion.Collision>> data) { builder.StartVector(4, data.Count, 4); builder.Add(data); return builder.EndVector(); }
  public static VectorOffset CreateCollideVectorBlock(FlatBufferBuilder builder, IntPtr dataPtr, int sizeInBytes) { builder.StartVector(1, sizeInBytes, 1); builder.Add<Offset<union_value_collsion.Collision>>(dataPtr, sizeInBytes); return builder.EndVector(); }
  public static void StartCollideVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); }
  public static Offset<union_value_collsion.Collision> EndCollision(FlatBufferBuilder builder) {
    int o = builder.EndTable();
    return new Offset<union_value_collsion.Collision>(o);
  }
  public static void FinishCollisionBuffer(FlatBufferBuilder builder, Offset<union_value_collsion.Collision> offset) { builder.Finish(offset.Value); }
  public static void FinishSizePrefixedCollisionBuffer(FlatBufferBuilder builder, Offset<union_value_collsion.Collision> offset) { builder.FinishSizePrefixed(offset.Value); }
  public CollisionT UnPack() {
    var _o = new CollisionT();
    this.UnPackTo(_o);
    return _o;
  }
  public void UnPackTo(CollisionT _o) {
    _o.SomeValue = new union_value_collsion.ValueUnion();
    _o.SomeValue.Type = this.SomeValueType;
    switch (this.SomeValueType) {
      default: break;
      case union_value_collsion.Value.IntValue:
        _o.SomeValue.Value_ = this.SomeValue<union_value_collsion.IntValue>().HasValue ? this.SomeValue<union_value_collsion.IntValue>().Value.UnPack() : null;
        break;
    }
    _o.Value = new union_value_collsion.OtherUnion();
    _o.Value.Type = this.ValueType;
    switch (this.ValueType) {
      default: break;
      case union_value_collsion.Other.IntValue:
        _o.Value.Value = this.Value<union_value_collsion.IntValue>().HasValue ? this.Value<union_value_collsion.IntValue>().Value.UnPack() : null;
        break;
    }
    _o.Collide = new List<union_value_collsion.CollisionT>();
    for (var _j = 0; _j < this.CollideLength; ++_j) {_o.Collide.Add(this.Collide(_j).HasValue ? this.Collide(_j).Value.UnPack() : null);}
  }
  public static Offset<union_value_collsion.Collision> Pack(FlatBufferBuilder builder, CollisionT _o) {
    if (_o == null) return default(Offset<union_value_collsion.Collision>);
    var _some_value_type = _o.SomeValue == null ? union_value_collsion.Value.NONE : _o.SomeValue.Type;
    var _some_value = _o.SomeValue == null ? 0 : union_value_collsion.ValueUnion.Pack(builder, _o.SomeValue);
    var _value_type = _o.Value == null ? union_value_collsion.Other.NONE : _o.Value.Type;
    var _value = _o.Value == null ? 0 : union_value_collsion.OtherUnion.Pack(builder, _o.Value);
    var _collide = default(VectorOffset);
    if (_o.Collide != null) {
      var __collide = new Offset<union_value_collsion.Collision>[_o.Collide.Count];
      for (var _j = 0; _j < __collide.Length; ++_j) { __collide[_j] = union_value_collsion.Collision.Pack(builder, _o.Collide[_j]); }
      _collide = CreateCollideVector(builder, __collide);
    }
    return CreateCollision(
      builder,
      _some_value_type,
      _some_value,
      _value_type,
      _value,
      _collide);
  }
}

public class CollisionT
{
  [Newtonsoft.Json.JsonProperty("some_value_type")]
  private union_value_collsion.Value SomeValueType {
    get {
      return this.SomeValue != null ? this.SomeValue.Type : union_value_collsion.Value.NONE;
    }
    set {
      this.SomeValue = new union_value_collsion.ValueUnion();
      this.SomeValue.Type = value;
    }
  }
  [Newtonsoft.Json.JsonProperty("some_value")]
  [Newtonsoft.Json.JsonConverter(typeof(union_value_collsion.ValueUnion_JsonConverter))]
  public union_value_collsion.ValueUnion SomeValue { get; set; }
  [Newtonsoft.Json.JsonProperty("value_type")]
  private union_value_collsion.Other ValueType {
    get {
      return this.Value != null ? this.Value.Type : union_value_collsion.Other.NONE;
    }
    set {
      this.Value = new union_value_collsion.OtherUnion();
      this.Value.Type = value;
    }
  }
  [Newtonsoft.Json.JsonProperty("value")]
  [Newtonsoft.Json.JsonConverter(typeof(union_value_collsion.OtherUnion_JsonConverter))]
  public union_value_collsion.OtherUnion Value { get; set; }
  [Newtonsoft.Json.JsonProperty("collide")]
  public List<union_value_collsion.CollisionT> Collide { get; set; }

  public CollisionT() {
    this.SomeValue = null;
    this.Value = null;
    this.Collide = null;
  }

  public static CollisionT DeserializeFromJson(string jsonText) {
    return Newtonsoft.Json.JsonConvert.DeserializeObject<CollisionT>(jsonText);
  }
  public string SerializeToJson() {
    return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented);
  }
  public static CollisionT DeserializeFromBinary(byte[] fbBuffer) {
    return Collision.GetRootAsCollision(new ByteBuffer(fbBuffer)).UnPack();
  }
  public byte[] SerializeToBinary() {
    var fbb = new FlatBufferBuilder(0x10000);
    Collision.FinishCollisionBuffer(fbb, Collision.Pack(fbb, this));
    return fbb.DataBuffer.ToSizedArray();
  }
}


static public class CollisionVerify
{
  static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
  {
    return verifier.VerifyTableStart(tablePos)
      && verifier.VerifyField(tablePos, 4 /*SomeValueType*/, 1 /*union_value_collsion.Value*/, 1, false)
      && verifier.VerifyUnion(tablePos, 4, 6 /*SomeValue*/, union_value_collsion.ValueVerify.Verify, false)
      && verifier.VerifyField(tablePos, 8 /*ValueType*/, 1 /*union_value_collsion.Other*/, 1, false)
      && verifier.VerifyUnion(tablePos, 8, 10 /*Value*/, union_value_collsion.OtherVerify.Verify, false)
      && verifier.VerifyVectorOfTables(tablePos, 12 /*Collide*/, union_value_collsion.CollisionVerify.Verify, false)
      && verifier.VerifyTableEnd(tablePos);
  }
}

}
