// automatically generated by the FlatBuffers compiler, do not modify

package NamespaceA;

import com.google.flatbuffers.*;
import java.nio.*;
import java.util.*;

@SuppressWarnings("unused")
public final class TableInFirstNS extends Table {
  public static void ValidateVersion() {
    Constants.FLATBUFFERS_25_12_19();
  }

  public static TableInFirstNS getRootAsTableInFirstNS(ByteBuffer _bb) {
    return getRootAsTableInFirstNS(_bb, new TableInFirstNS());
  }

  public static TableInFirstNS getRootAsTableInFirstNS(ByteBuffer _bb, TableInFirstNS obj) {
    _bb.order(ByteOrder.LITTLE_ENDIAN);
    return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb));
  }

  public void __init(int _i, ByteBuffer _bb) {
    __reset(_i, _bb);
  }

  public TableInFirstNS __assign(int _i, ByteBuffer _bb) {
    __init(_i, _bb);
    return this;
  }

  public NamespaceA.NamespaceB.TableInNestedNS fooTable() {
    return fooTable(new NamespaceA.NamespaceB.TableInNestedNS());
  }

  public NamespaceA.NamespaceB.TableInNestedNS fooTable(NamespaceA.NamespaceB.TableInNestedNS obj) {
    int o = __offset(4);
    return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null;
  }

  public byte fooEnum() {
    int o = __offset(6);
    return o != 0 ? bb.get(o + bb_pos) : 0;
  }

  public boolean mutateFooEnum(byte foo_enum) {
    int o = __offset(6);
    if (o != 0) {
      bb.put(o + bb_pos, foo_enum);
      return true;
    } else {
      return false;
    }
  }

  public byte fooUnionType() {
    int o = __offset(8);
    return o != 0 ? bb.get(o + bb_pos) : 0;
  }

  public Table fooUnion(Table obj) {
    int o = __offset(10);
    return o != 0 ? __union(obj, o + bb_pos) : null;
  }

  public NamespaceA.NamespaceB.StructInNestedNS fooStruct() {
    return fooStruct(new NamespaceA.NamespaceB.StructInNestedNS());
  }

  public NamespaceA.NamespaceB.StructInNestedNS fooStruct(
      NamespaceA.NamespaceB.StructInNestedNS obj) {
    int o = __offset(12);
    return o != 0 ? obj.__assign(o + bb_pos, bb) : null;
  }

  public static void startTableInFirstNS(FlatBufferBuilder builder) {
    builder.startTable(5);
  }

  public static void addFooTable(FlatBufferBuilder builder, int fooTableOffset) {
    builder.addOffset(0, fooTableOffset, 0);
  }

  public static void addFooEnum(FlatBufferBuilder builder, byte fooEnum) {
    builder.addByte(1, fooEnum, 0);
  }

  public static void addFooUnionType(FlatBufferBuilder builder, byte fooUnionType) {
    builder.addByte(2, fooUnionType, 0);
  }

  public static void addFooUnion(FlatBufferBuilder builder, int fooUnionOffset) {
    builder.addOffset(3, fooUnionOffset, 0);
  }

  public static void addFooStruct(FlatBufferBuilder builder, int fooStructOffset) {
    builder.addStruct(4, fooStructOffset, 0);
  }

  public static int endTableInFirstNS(FlatBufferBuilder builder) {
    int o = builder.endTable();
    return o;
  }

  public static final class Vector extends BaseVector {
    public Vector __assign(int _vector, int _element_size, ByteBuffer _bb) {
      __reset(_vector, _element_size, _bb);
      return this;
    }

    public TableInFirstNS get(int j) {
      return get(new TableInFirstNS(), j);
    }

    public TableInFirstNS get(TableInFirstNS obj, int j) {
      return obj.__assign(__indirect(__element(j), bb), bb);
    }
  }

  public TableInFirstNST unpack() {
    TableInFirstNST _o = new TableInFirstNST();
    unpackTo(_o);
    return _o;
  }

  public void unpackTo(TableInFirstNST _o) {
    if (fooTable() != null) _o.setFooTable(fooTable().unpack());
    else _o.setFooTable(null);
    byte _oFooEnum = fooEnum();
    _o.setFooEnum(_oFooEnum);
    NamespaceA.NamespaceB.UnionInNestedNSUnion _oFooUnion =
        new NamespaceA.NamespaceB.UnionInNestedNSUnion();
    byte _oFooUnionType = fooUnionType();
    _oFooUnion.setType(_oFooUnionType);
    Table _oFooUnionValue;
    switch (_oFooUnionType) {
      case NamespaceA.NamespaceB.UnionInNestedNS.TableInNestedNS:
        _oFooUnionValue = fooUnion(new NamespaceA.NamespaceB.TableInNestedNS());
        _oFooUnion.setValue(
            _oFooUnionValue != null
                ? ((NamespaceA.NamespaceB.TableInNestedNS) _oFooUnionValue).unpack()
                : null);
        break;
      default:
        break;
    }
    _o.setFooUnion(_oFooUnion);
    if (fooStruct() != null) fooStruct().unpackTo(_o.getFooStruct());
    else _o.setFooStruct(null);
  }

  public static int pack(FlatBufferBuilder builder, TableInFirstNST _o) {
    if (_o == null) return 0;
    int _foo_table =
        _o.getFooTable() == null
            ? 0
            : NamespaceA.NamespaceB.TableInNestedNS.pack(builder, _o.getFooTable());
    byte _fooUnionType =
        _o.getFooUnion() == null
            ? NamespaceA.NamespaceB.UnionInNestedNS.NONE
            : _o.getFooUnion().getType();
    int _fooUnion =
        _o.getFooUnion() == null
            ? 0
            : NamespaceA.NamespaceB.UnionInNestedNSUnion.pack(builder, _o.getFooUnion());
    startTableInFirstNS(builder);
    addFooTable(builder, _foo_table);
    addFooEnum(builder, _o.getFooEnum());
    addFooUnionType(builder, _fooUnionType);
    addFooUnion(builder, _fooUnion);
    addFooStruct(builder, NamespaceA.NamespaceB.StructInNestedNS.pack(builder, _o.getFooStruct()));
    return endTableInFirstNS(builder);
  }
}
