// automatically generated by the FlatBuffers compiler, do not modify
import * as flatbuffers from 'flatbuffers';
import { Color } from '../../my-game/example/color';
export class TestSimpleTableWithEnum {
    constructor() {
        this.bb = null;
        this.bb_pos = 0;
    }
    __init(i, bb) {
        this.bb_pos = i;
        this.bb = bb;
        return this;
    }
    static getRootAsTestSimpleTableWithEnum(bb, obj) {
        return (obj || new TestSimpleTableWithEnum()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
    }
    static getSizePrefixedRootAsTestSimpleTableWithEnum(bb, obj) {
        bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
        return (obj || new TestSimpleTableWithEnum()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
    }
    color() {
        const offset = this.bb.__offset(this.bb_pos, 4);
        return offset ? this.bb.readUint8(this.bb_pos + offset) : Color.Green;
    }
    mutate_color(value) {
        const offset = this.bb.__offset(this.bb_pos, 4);
        if (offset === 0) {
            return false;
        }
        this.bb.writeUint8(this.bb_pos + offset, value);
        return true;
    }
    static getFullyQualifiedName() {
        return 'MyGame_Example_TestSimpleTableWithEnum';
    }
    static startTestSimpleTableWithEnum(builder) {
        builder.startObject(1);
    }
    static addColor(builder, color) {
        builder.addFieldInt8(0, color, Color.Green);
    }
    static endTestSimpleTableWithEnum(builder) {
        const offset = builder.endObject();
        return offset;
    }
    static createTestSimpleTableWithEnum(builder, color) {
        TestSimpleTableWithEnum.startTestSimpleTableWithEnum(builder);
        TestSimpleTableWithEnum.addColor(builder, color);
        return TestSimpleTableWithEnum.endTestSimpleTableWithEnum(builder);
    }
    serialize() {
        return this.bb.bytes();
    }
    static deserialize(buffer) {
        return TestSimpleTableWithEnum.getRootAsTestSimpleTableWithEnum(new flatbuffers.ByteBuffer(buffer));
    }
    unpack() {
        return new TestSimpleTableWithEnumT(this.color());
    }
    unpackTo(_o) {
        _o.color = this.color();
    }
}
export class TestSimpleTableWithEnumT {
    constructor(color = Color.Green) {
        this.color = color;
    }
    pack(builder) {
        return TestSimpleTableWithEnum.createTestSimpleTableWithEnum(builder, this.color);
    }
}
