"use strict";
/**
 * Copyright (c) 2023 The xterm.js authors. All rights reserved.
 * @license MIT
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.HeaderParser = void 0;
// field value decoders
// ASCII bytes to string
function toStr(data) {
    let s = '';
    for (let i = 0; i < data.length; ++i) {
        s += String.fromCharCode(data[i]);
    }
    return s;
}
// digits to integer
function toInt(data) {
    let v = 0;
    for (let i = 0; i < data.length; ++i) {
        if (data[i] < 48 || data[i] > 57) {
            throw new Error('illegal char');
        }
        v = v * 10 + data[i] - 48;
    }
    return v;
}
// check for correct size entry
function toSize(data) {
    const v = toStr(data);
    if (!v.match(/^((auto)|(\d+?((px)|(%)){0,1}))$/)) {
        throw new Error('illegal size');
    }
    return v;
}
// name is base64 encoded utf-8
function toName(data) {
    if (typeof Buffer !== 'undefined') {
        return Buffer.from(toStr(data), 'base64').toString();
    }
    const bs = atob(toStr(data));
    const b = new Uint8Array(bs.length);
    for (let i = 0; i < b.length; ++i) {
        b[i] = bs.charCodeAt(i);
    }
    return new TextDecoder().decode(b);
}
const DECODERS = {
    inline: toInt,
    size: toInt,
    name: toName,
    width: toSize,
    height: toSize,
    preserveAspectRatio: toInt
};
const FILE_MARKER = [70, 105, 108, 101];
const MAX_FIELDCHARS = 1024;
class HeaderParser {
    constructor() {
        this.state = 0 /* HeaderState.START */;
        this._buffer = new Uint32Array(MAX_FIELDCHARS);
        this._position = 0;
        this._key = '';
        this.fields = {};
    }
    reset() {
        this._buffer.fill(0);
        this.state = 0 /* HeaderState.START */;
        this._position = 0;
        this.fields = {};
        this._key = '';
    }
    parse(data, start, end) {
        let state = this.state;
        let pos = this._position;
        const buffer = this._buffer;
        if (state === 1 /* HeaderState.ABORT */ || state === 4 /* HeaderState.END */)
            return -1;
        if (state === 0 /* HeaderState.START */ && pos > 6)
            return -1;
        for (let i = start; i < end; ++i) {
            const c = data[i];
            switch (c) {
                case 59: // ;
                    if (!this._storeValue(pos))
                        return this._a();
                    state = 2 /* HeaderState.KEY */;
                    pos = 0;
                    break;
                case 61: // =
                    if (state === 0 /* HeaderState.START */) {
                        for (let k = 0; k < FILE_MARKER.length; ++k) {
                            if (buffer[k] !== FILE_MARKER[k])
                                return this._a();
                        }
                        state = 2 /* HeaderState.KEY */;
                        pos = 0;
                    }
                    else if (state === 2 /* HeaderState.KEY */) {
                        if (!this._storeKey(pos))
                            return this._a();
                        state = 3 /* HeaderState.VALUE */;
                        pos = 0;
                    }
                    else if (state === 3 /* HeaderState.VALUE */) {
                        if (pos >= MAX_FIELDCHARS)
                            return this._a();
                        buffer[pos++] = c;
                    }
                    break;
                case 58: // :
                    if (state === 3 /* HeaderState.VALUE */) {
                        if (!this._storeValue(pos))
                            return this._a();
                    }
                    this.state = 4 /* HeaderState.END */;
                    return i + 1;
                default:
                    if (pos >= MAX_FIELDCHARS)
                        return this._a();
                    buffer[pos++] = c;
            }
        }
        this.state = state;
        this._position = pos;
        return -2;
    }
    _a() {
        this.state = 1 /* HeaderState.ABORT */;
        return -1;
    }
    _storeKey(pos) {
        const k = toStr(this._buffer.subarray(0, pos));
        if (k) {
            this._key = k;
            this.fields[k] = null;
            return true;
        }
        return false;
    }
    _storeValue(pos) {
        if (this._key) {
            try {
                const v = this._buffer.slice(0, pos);
                this.fields[this._key] = DECODERS[this._key] ? DECODERS[this._key](v) : v;
            }
            catch (e) {
                return false;
            }
            return true;
        }
        return false;
    }
}
exports.HeaderParser = HeaderParser;