// automatically generated by the FlatBuffers compiler, do not modify
// ignore_for_file: unused_import, unused_field, unused_element, unused_local_variable

library my_game.other_name_space;

import 'dart:typed_data' show Uint8List;
import 'package:flat_buffers/flat_buffers.dart' as fb;


import './include_test1_generated.dart';

class FromInclude {
  final int value;
  const FromInclude._(this.value);

  factory FromInclude.fromValue(int value) {
    final result = values[value];
    if (result == null) {
        throw StateError('Invalid value $value for bit flag enum FromInclude');
    }
    return result;
  }

  static FromInclude? _createOrNull(int? value) => 
      value == null ? null : FromInclude.fromValue(value);

  static const int minValue = 0;
  static const int maxValue = 0;
  static bool containsValue(int value) => values.containsKey(value);

  static const FromInclude IncludeVal = FromInclude._(0);
  static const Map<int, FromInclude> values = {
    0: IncludeVal};

  static const fb.Reader<FromInclude> reader = _FromIncludeReader();

  @override
  String toString() {
    return 'FromInclude{value: $value}';
  }
}

class _FromIncludeReader extends fb.Reader<FromInclude> {
  const _FromIncludeReader();

  @override
  int get size => 8;

  @override
  FromInclude read(fb.BufferContext bc, int offset) =>
      FromInclude.fromValue(const fb.Int64Reader().read(bc, offset));
}

class Unused {
  Unused._(this._bc, this._bcOffset);

  static const fb.Reader<Unused> reader = _UnusedReader();

  final fb.BufferContext _bc;
  final int _bcOffset;

  int get a => const fb.Int32Reader().read(_bc, _bcOffset + 0);

  @override
  String toString() {
    return 'Unused{a: ${a}}';
  }

  UnusedT unpack() => UnusedT(
      a: a);

  static int pack(fb.Builder fbBuilder, UnusedT? object) {
    if (object == null) return 0;
    return object.pack(fbBuilder);
  }
}

class UnusedT implements fb.Packable {
  int a;

  UnusedT({
      required this.a});

  @override
  int pack(fb.Builder fbBuilder) {
    fbBuilder.putInt32(a);
    return fbBuilder.offset;
  }

  @override
  String toString() {
    return 'UnusedT{a: ${a}}';
  }
}

class _UnusedReader extends fb.StructReader<Unused> {
  const _UnusedReader();

  @override
  int get size => 4;

  @override
  Unused createObject(fb.BufferContext bc, int offset) => 
    Unused._(bc, offset);
}

class UnusedBuilder {
  UnusedBuilder(this.fbBuilder);

  final fb.Builder fbBuilder;

  int finish(int a) {
    fbBuilder.putInt32(a);
    return fbBuilder.offset;
  }

}

class UnusedObjectBuilder extends fb.ObjectBuilder {
  final int _a;

  UnusedObjectBuilder({
    required int a,
  })
      : _a = a;

  /// Finish building, and store into the [fbBuilder].
  @override
  int finish(fb.Builder fbBuilder) {
    fbBuilder.putInt32(_a);
    return fbBuilder.offset;
  }

  /// Convenience method to serialize to byte list.
  @override
  Uint8List toBytes([String? fileIdentifier]) {
    final fbBuilder = fb.Builder(deduplicateTables: false);
    fbBuilder.finish(finish(fbBuilder), fileIdentifier);
    return fbBuilder.buffer;
  }
}
class TableB {
  TableB._(this._bc, this._bcOffset);
  factory TableB(List<int> bytes) {
    final rootRef = fb.BufferContext.fromBytes(bytes);
    return reader.read(rootRef, 0);
  }

  static const fb.Reader<TableB> reader = _TableBReader();

  final fb.BufferContext _bc;
  final int _bcOffset;

  TableA? get a => TableA.reader.vTableGetNullable(_bc, _bcOffset, 4);

  @override
  String toString() {
    return 'TableB{a: ${a}}';
  }

  TableBT unpack() => TableBT(
      a: a?.unpack());

  static int pack(fb.Builder fbBuilder, TableBT? object) {
    if (object == null) return 0;
    return object.pack(fbBuilder);
  }
}

class TableBT implements fb.Packable {
  TableAT? a;

  TableBT({
      this.a});

  @override
  int pack(fb.Builder fbBuilder) {
    final int? aOffset = a?.pack(fbBuilder);
    fbBuilder.startTable(1);
    fbBuilder.addOffset(0, aOffset);
    return fbBuilder.endTable();
  }

  @override
  String toString() {
    return 'TableBT{a: ${a}}';
  }
}

class _TableBReader extends fb.TableReader<TableB> {
  const _TableBReader();

  @override
  TableB createObject(fb.BufferContext bc, int offset) => 
    TableB._(bc, offset);
}

class TableBBuilder {
  TableBBuilder(this.fbBuilder);

  final fb.Builder fbBuilder;

  void begin() {
    fbBuilder.startTable(1);
  }

  int addAOffset(int? offset) {
    fbBuilder.addOffset(0, offset);
    return fbBuilder.offset;
  }

  int finish() {
    return fbBuilder.endTable();
  }
}

class TableBObjectBuilder extends fb.ObjectBuilder {
  final TableAObjectBuilder? _a;

  TableBObjectBuilder({
    TableAObjectBuilder? a,
  })
      : _a = a;

  /// Finish building, and store into the [fbBuilder].
  @override
  int finish(fb.Builder fbBuilder) {
    final int? aOffset = _a?.getOrCreateOffset(fbBuilder);
    fbBuilder.startTable(1);
    fbBuilder.addOffset(0, aOffset);
    return fbBuilder.endTable();
  }

  /// Convenience method to serialize to byte list.
  @override
  Uint8List toBytes([String? fileIdentifier]) {
    final fbBuilder = fb.Builder(deduplicateTables: false);
    fbBuilder.finish(finish(fbBuilder), fileIdentifier);
    return fbBuilder.buffer;
  }
}
