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

namespace Apache.Arrow.Flatbuf
{

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

/// ----------------------------------------------------------------------
/// Data structures for dense tensors
/// Shape data for a single axis in a tensor
internal struct TensorDim : IFlatbufferObject
{
  private Table __p;
  public ByteBuffer ByteBuffer { get { return __p.bb; } }
  public static void ValidateVersion() { FlatBufferConstants.FLATBUFFERS_23_5_9(); }
  public static TensorDim GetRootAsTensorDim(ByteBuffer _bb) { return GetRootAsTensorDim(_bb, new TensorDim()); }
  public static TensorDim GetRootAsTensorDim(ByteBuffer _bb, TensorDim obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
  public void __init(int _i, ByteBuffer _bb) { __p = new Table(_i, _bb); }
  public TensorDim __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }

  /// Length of dimension
  public long Size { get { int o = __p.__offset(4); return o != 0 ? __p.bb.GetLong(o + __p.bb_pos) : (long)0; } }
  /// Name of the dimension, optional
  public string Name { get { int o = __p.__offset(6); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
#if ENABLE_SPAN_T
  public Span<byte> GetNameBytes() { return __p.__vector_as_span<byte>(6, 1); }
#else
  public ArraySegment<byte>? GetNameBytes() { return __p.__vector_as_arraysegment(6); }
#endif
  public byte[] GetNameArray() { return __p.__vector_as_array<byte>(6); }

  public static Offset<TensorDim> CreateTensorDim(FlatBufferBuilder builder,
      long size = 0,
      StringOffset nameOffset = default(StringOffset)) {
    builder.StartTable(2);
    TensorDim.AddSize(builder, size);
    TensorDim.AddName(builder, nameOffset);
    return TensorDim.EndTensorDim(builder);
  }

  public static void StartTensorDim(FlatBufferBuilder builder) { builder.StartTable(2); }
  public static void AddSize(FlatBufferBuilder builder, long size) { builder.AddLong(0, size, 0); }
  public static void AddName(FlatBufferBuilder builder, StringOffset nameOffset) { builder.AddOffset(1, nameOffset.Value, 0); }
  public static Offset<TensorDim> EndTensorDim(FlatBufferBuilder builder) {
    int o = builder.EndTable();
    return new Offset<TensorDim>(o);
  }
}


static internal class TensorDimVerify
{
  static public bool Verify(Google.FlatBuffers.Verifier verifier, uint tablePos)
  {
    return verifier.VerifyTableStart(tablePos)
      && verifier.VerifyField(tablePos, 4 /*Size*/, 8 /*long*/, 8, false)
      && verifier.VerifyString(tablePos, 6 /*Name*/, false)
      && verifier.VerifyTableEnd(tablePos);
  }
}

}
