// automatically generated by the FlatBuffers compiler, do not modify
import * as flatbuffers from 'flatbuffers';
import { KeyValue } from '../reflection/key-value.js';
import { Type } from '../reflection/type.js';
export class EnumVal {
    constructor() {
        this.bb = null;
        this.bb_pos = 0;
    }
    __init(i, bb) {
        this.bb_pos = i;
        this.bb = bb;
        return this;
    }
    static getRootAsEnumVal(bb, obj) {
        return (obj || new EnumVal()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
    }
    static getSizePrefixedRootAsEnumVal(bb, obj) {
        bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
        return (obj || new EnumVal()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
    }
    name(optionalEncoding) {
        const offset = this.bb.__offset(this.bb_pos, 4);
        return offset ? this.bb.__string(this.bb_pos + offset, optionalEncoding) : null;
    }
    value() {
        const offset = this.bb.__offset(this.bb_pos, 6);
        return offset ? this.bb.readInt64(this.bb_pos + offset) : BigInt('0');
    }
    mutate_value(value) {
        const offset = this.bb.__offset(this.bb_pos, 6);
        if (offset === 0) {
            return false;
        }
        this.bb.writeInt64(this.bb_pos + offset, value);
        return true;
    }
    unionType(obj) {
        const offset = this.bb.__offset(this.bb_pos, 10);
        return offset ? (obj || new Type()).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null;
    }
    documentation(index, optionalEncoding) {
        const offset = this.bb.__offset(this.bb_pos, 12);
        return offset ? this.bb.__string(this.bb.__vector(this.bb_pos + offset) + index * 4, optionalEncoding) : null;
    }
    documentationLength() {
        const offset = this.bb.__offset(this.bb_pos, 12);
        return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
    }
    attributes(index, obj) {
        const offset = this.bb.__offset(this.bb_pos, 14);
        return offset ? (obj || new KeyValue()).__init(this.bb.__indirect(this.bb.__vector(this.bb_pos + offset) + index * 4), this.bb) : null;
    }
    attributesLength() {
        const offset = this.bb.__offset(this.bb_pos, 14);
        return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
    }
    static getFullyQualifiedName() {
        return 'reflection_EnumVal';
    }
    static startEnumVal(builder) {
        builder.startObject(6);
    }
    static addName(builder, nameOffset) {
        builder.addFieldOffset(0, nameOffset, 0);
    }
    static addValue(builder, value) {
        builder.addFieldInt64(1, value, BigInt('0'));
    }
    static addUnionType(builder, unionTypeOffset) {
        builder.addFieldOffset(3, unionTypeOffset, 0);
    }
    static addDocumentation(builder, documentationOffset) {
        builder.addFieldOffset(4, documentationOffset, 0);
    }
    static createDocumentationVector(builder, data) {
        builder.startVector(4, data.length, 4);
        for (let i = data.length - 1; i >= 0; i--) {
            builder.addOffset(data[i]);
        }
        return builder.endVector();
    }
    static startDocumentationVector(builder, numElems) {
        builder.startVector(4, numElems, 4);
    }
    static addAttributes(builder, attributesOffset) {
        builder.addFieldOffset(5, attributesOffset, 0);
    }
    static createAttributesVector(builder, data) {
        builder.startVector(4, data.length, 4);
        for (let i = data.length - 1; i >= 0; i--) {
            builder.addOffset(data[i]);
        }
        return builder.endVector();
    }
    static startAttributesVector(builder, numElems) {
        builder.startVector(4, numElems, 4);
    }
    static endEnumVal(builder) {
        const offset = builder.endObject();
        builder.requiredField(offset, 4); // name
        return offset;
    }
    unpack() {
        return new EnumValT(this.name(), this.value(), (this.unionType() !== null ? this.unionType().unpack() : null), this.bb.createScalarList(this.documentation.bind(this), this.documentationLength()), this.bb.createObjList(this.attributes.bind(this), this.attributesLength()));
    }
    unpackTo(_o) {
        _o.name = this.name();
        _o.value = this.value();
        _o.unionType = (this.unionType() !== null ? this.unionType().unpack() : null);
        _o.documentation = this.bb.createScalarList(this.documentation.bind(this), this.documentationLength());
        _o.attributes = this.bb.createObjList(this.attributes.bind(this), this.attributesLength());
    }
}
export class EnumValT {
    constructor(name = null, value = BigInt('0'), unionType = null, documentation = [], attributes = []) {
        this.name = name;
        this.value = value;
        this.unionType = unionType;
        this.documentation = documentation;
        this.attributes = attributes;
    }
    pack(builder) {
        const name = (this.name !== null ? builder.createString(this.name) : 0);
        const unionType = (this.unionType !== null ? this.unionType.pack(builder) : 0);
        const documentation = EnumVal.createDocumentationVector(builder, builder.createObjectOffsetList(this.documentation));
        const attributes = EnumVal.createAttributesVector(builder, builder.createObjectOffsetList(this.attributes));
        EnumVal.startEnumVal(builder);
        EnumVal.addName(builder, name);
        EnumVal.addValue(builder, this.value);
        EnumVal.addUnionType(builder, unionType);
        EnumVal.addDocumentation(builder, documentation);
        EnumVal.addAttributes(builder, attributes);
        return EnumVal.endEnumVal(builder);
    }
}
