const comma = ','.charCodeAt(0);
const semicolon = ';'.charCodeAt(0);
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
const intToChar = new Uint8Array(64); // 64 possible chars.
const charToInt = new Uint8Array(128); // z is 122 in ASCII
for (let i = 0; i < chars.length; i++) {
    const c = chars.charCodeAt(i);
    intToChar[i] = c;
    charToInt[c] = i;
}
function decodeInteger(reader, relative) {
    let value = 0;
    let shift = 0;
    let integer = 0;
    do {
        const c = reader.next();
        integer = charToInt[c];
        value |= (integer & 31) << shift;
        shift += 5;
    } while (integer & 32);
    const shouldNegate = value & 1;
    value >>>= 1;
    if (shouldNegate) {
        value = -0x80000000 | -value;
    }
    return relative + value;
}
function encodeInteger(builder, num, relative) {
    let delta = num - relative;
    delta = delta < 0 ? (-delta << 1) | 1 : delta << 1;
    do {
        let clamped = delta & 0b011111;
        delta >>>= 5;
        if (delta > 0)
            clamped |= 0b100000;
        builder.write(intToChar[clamped]);
    } while (delta > 0);
    return num;
}
function hasMoreVlq(reader, max) {
    if (reader.pos >= max)
        return false;
    return reader.peek() !== comma;
}

const bufLength = 1024 * 16;
// Provide a fallback for older environments.
const td = typeof TextDecoder !== 'undefined'
    ? /* #__PURE__ */ new TextDecoder()
    : typeof Buffer !== 'undefined'
        ? {
            decode(buf) {
                const out = Buffer.from(buf.buffer, buf.byteOffset, buf.byteLength);
                return out.toString();
            },
        }
        : {
            decode(buf) {
                let out = '';
                for (let i = 0; i < buf.length; i++) {
                    out += String.fromCharCode(buf[i]);
                }
                return out;
            },
        };
class StringWriter {
    constructor() {
        this.pos = 0;
        this.out = '';
        this.buffer = new Uint8Array(bufLength);
    }
    write(v) {
        const { buffer } = this;
        buffer[this.pos++] = v;
        if (this.pos === bufLength) {
            this.out += td.decode(buffer);
            this.pos = 0;
        }
    }
    flush() {
        const { buffer, out, pos } = this;
        return pos > 0 ? out + td.decode(buffer.subarray(0, pos)) : out;
    }
}
class StringReader {
    constructor(buffer) {
        this.pos = 0;
        this.buffer = buffer;
    }
    next() {
        return this.buffer.charCodeAt(this.pos++);
    }
    peek() {
        return this.buffer.charCodeAt(this.pos);
    }
    indexOf(char) {
        const { buffer, pos } = this;
        const idx = buffer.indexOf(char, pos);
        return idx === -1 ? buffer.length : idx;
    }
}

const EMPTY = [];
function decodeOriginalScopes(input) {
    const { length } = input;
    const reader = new StringReader(input);
    const scopes = [];
    const stack = [];
    let line = 0;
    for (; reader.pos < length; reader.pos++) {
        line = decodeInteger(reader, line);
        const column = decodeInteger(reader, 0);
        if (!hasMoreVlq(reader, length)) {
            const last = stack.pop();
            last[2] = line;
            last[3] = column;
            continue;
        }
        const kind = decodeInteger(reader, 0);
        const fields = decodeInteger(reader, 0);
        const hasName = fields & 0b0001;
        const scope = (hasName ? [line, column, 0, 0, kind, decodeInteger(reader, 0)] : [line, column, 0, 0, kind]);
        let vars = EMPTY;
        if (hasMoreVlq(reader, length)) {
            vars = [];
            do {
                const varsIndex = decodeInteger(reader, 0);
                vars.push(varsIndex);
            } while (hasMoreVlq(reader, length));
        }
        scope.vars = vars;
        scopes.push(scope);
        stack.push(scope);
    }
    return scopes;
}
function encodeOriginalScopes(scopes) {
    const writer = new StringWriter();
    for (let i = 0; i < scopes.length;) {
        i = _encodeOriginalScopes(scopes, i, writer, [0]);
    }
    return writer.flush();
}
function _encodeOriginalScopes(scopes, index, writer, state) {
    const scope = scopes[index];
    const { 0: startLine, 1: startColumn, 2: endLine, 3: endColumn, 4: kind, vars } = scope;
    if (index > 0)
        writer.write(comma);
    state[0] = encodeInteger(writer, startLine, state[0]);
    encodeInteger(writer, startColumn, 0);
    encodeInteger(writer, kind, 0);
    const fields = scope.length === 6 ? 0b0001 : 0;
    encodeInteger(writer, fields, 0);
    if (scope.length === 6)
        encodeInteger(writer, scope[5], 0);
    for (const v of vars) {
        encodeInteger(writer, v, 0);
    }
    for (index++; index < scopes.length;) {
        const next = scopes[index];
        const { 0: l, 1: c } = next;
        if (l > endLine || (l === endLine && c >= endColumn)) {
            break;
        }
        index = _encodeOriginalScopes(scopes, index, writer, state);
    }
    writer.write(comma);
    state[0] = encodeInteger(writer, endLine, state[0]);
    encodeInteger(writer, endColumn, 0);
    return index;
}
function decodeGeneratedRanges(input) {
    const { length } = input;
    const reader = new StringReader(input);
    const ranges = [];
    const stack = [];
    let genLine = 0;
    let definitionSourcesIndex = 0;
    let definitionScopeIndex = 0;
    let callsiteSourcesIndex = 0;
    let callsiteLine = 0;
    let callsiteColumn = 0;
    let bindingLine = 0;
    let bindingColumn = 0;
    do {
        const semi = reader.indexOf(';');
        let genColumn = 0;
        for (; reader.pos < semi; reader.pos++) {
            genColumn = decodeInteger(reader, genColumn);
            if (!hasMoreVlq(reader, semi)) {
                const last = stack.pop();
                last[2] = genLine;
                last[3] = genColumn;
                continue;
            }
            const fields = decodeInteger(reader, 0);
            const hasDefinition = fields & 0b0001;
            const hasCallsite = fields & 0b0010;
            const hasScope = fields & 0b0100;
            let callsite = null;
            let bindings = EMPTY;
            let range;
            if (hasDefinition) {
                const defSourcesIndex = decodeInteger(reader, definitionSourcesIndex);
                definitionScopeIndex = decodeInteger(reader, definitionSourcesIndex === defSourcesIndex ? definitionScopeIndex : 0);
                definitionSourcesIndex = defSourcesIndex;
                range = [genLine, genColumn, 0, 0, defSourcesIndex, definitionScopeIndex];
            }
            else {
                range = [genLine, genColumn, 0, 0];
            }
            range.isScope = !!hasScope;
            if (hasCallsite) {
                const prevCsi = callsiteSourcesIndex;
                const prevLine = callsiteLine;
                callsiteSourcesIndex = decodeInteger(reader, callsiteSourcesIndex);
                const sameSource = prevCsi === callsiteSourcesIndex;
                callsiteLine = decodeInteger(reader, sameSource ? callsiteLine : 0);
                callsiteColumn = decodeInteger(reader, sameSource && prevLine === callsiteLine ? callsiteColumn : 0);
                callsite = [callsiteSourcesIndex, callsiteLine, callsiteColumn];
            }
            range.callsite = callsite;
            if (hasMoreVlq(reader, semi)) {
                bindings = [];
                do {
                    bindingLine = genLine;
                    bindingColumn = genColumn;
                    const expressionsCount = decodeInteger(reader, 0);
                    let expressionRanges;
                    if (expressionsCount < -1) {
                        expressionRanges = [[decodeInteger(reader, 0)]];
                        for (let i = -1; i > expressionsCount; i--) {
                            const prevBl = bindingLine;
                            bindingLine = decodeInteger(reader, bindingLine);
                            bindingColumn = decodeInteger(reader, bindingLine === prevBl ? bindingColumn : 0);
                            const expression = decodeInteger(reader, 0);
                            expressionRanges.push([expression, bindingLine, bindingColumn]);
                        }
                    }
                    else {
                        expressionRanges = [[expressionsCount]];
                    }
                    bindings.push(expressionRanges);
                } while (hasMoreVlq(reader, semi));
            }
            range.bindings = bindings;
            ranges.push(range);
            stack.push(range);
        }
        genLine++;
        reader.pos = semi + 1;
    } while (reader.pos < length);
    return ranges;
}
function encodeGeneratedRanges(ranges) {
    if (ranges.length === 0)
        return '';
    const writer = new StringWriter();
    for (let i = 0; i < ranges.length;) {
        i = _encodeGeneratedRanges(ranges, i, writer, [0, 0, 0, 0, 0, 0, 0]);
    }
    return writer.flush();
}
function _encodeGeneratedRanges(ranges, index, writer, state) {
    const range = ranges[index];
    const { 0: startLine, 1: startColumn, 2: endLine, 3: endColumn, isScope, callsite, bindings, } = range;
    if (state[0] < startLine) {
        catchupLine(writer, state[0], startLine);
        state[0] = startLine;
        state[1] = 0;
    }
    else if (index > 0) {
        writer.write(comma);
    }
    state[1] = encodeInteger(writer, range[1], state[1]);
    const fields = (range.length === 6 ? 0b0001 : 0) | (callsite ? 0b0010 : 0) | (isScope ? 0b0100 : 0);
    encodeInteger(writer, fields, 0);
    if (range.length === 6) {
        const { 4: sourcesIndex, 5: scopesIndex } = range;
        if (sourcesIndex !== state[2]) {
            state[3] = 0;
        }
        state[2] = encodeInteger(writer, sourcesIndex, state[2]);
        state[3] = encodeInteger(writer, scopesIndex, state[3]);
    }
    if (callsite) {
        const { 0: sourcesIndex, 1: callLine, 2: callColumn } = range.callsite;
        if (sourcesIndex !== state[4]) {
            state[5] = 0;
            state[6] = 0;
        }
        else if (callLine !== state[5]) {
            state[6] = 0;
        }
        state[4] = encodeInteger(writer, sourcesIndex, state[4]);
        state[5] = encodeInteger(writer, callLine, state[5]);
        state[6] = encodeInteger(writer, callColumn, state[6]);
    }
    if (bindings) {
        for (const binding of bindings) {
            if (binding.length > 1)
                encodeInteger(writer, -binding.length, 0);
            const expression = binding[0][0];
            encodeInteger(writer, expression, 0);
            let bindingStartLine = startLine;
            let bindingStartColumn = startColumn;
            for (let i = 1; i < binding.length; i++) {
                const expRange = binding[i];
                bindingStartLine = encodeInteger(writer, expRange[1], bindingStartLine);
                bindingStartColumn = encodeInteger(writer, expRange[2], bindingStartColumn);
                encodeInteger(writer, expRange[0], 0);
            }
        }
    }
    for (index++; index < ranges.length;) {
        const next = ranges[index];
        const { 0: l, 1: c } = next;
        if (l > endLine || (l === endLine && c >= endColumn)) {
            break;
        }
        index = _encodeGeneratedRanges(ranges, index, writer, state);
    }
    if (state[0] < endLine) {
        catchupLine(writer, state[0], endLine);
        state[0] = endLine;
        state[1] = 0;
    }
    else {
        writer.write(comma);
    }
    state[1] = encodeInteger(writer, endColumn, state[1]);
    return index;
}
function catchupLine(writer, lastLine, line) {
    do {
        writer.write(semicolon);
    } while (++lastLine < line);
}

function decode(mappings) {
    const { length } = mappings;
    const reader = new StringReader(mappings);
    const decoded = [];
    let genColumn = 0;
    let sourcesIndex = 0;
    let sourceLine = 0;
    let sourceColumn = 0;
    let namesIndex = 0;
    do {
        const semi = reader.indexOf(';');
        const line = [];
        let sorted = true;
        let lastCol = 0;
        genColumn = 0;
        while (reader.pos < semi) {
            let seg;
            genColumn = decodeInteger(reader, genColumn);
            if (genColumn < lastCol)
                sorted = false;
            lastCol = genColumn;
            if (hasMoreVlq(reader, semi)) {
                sourcesIndex = decodeInteger(reader, sourcesIndex);
                sourceLine = decodeInteger(reader, sourceLine);
                sourceColumn = decodeInteger(reader, sourceColumn);
                if (hasMoreVlq(reader, semi)) {
                    namesIndex = decodeInteger(reader, namesIndex);
                    seg = [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex];
                }
                else {
                    seg = [genColumn, sourcesIndex, sourceLine, sourceColumn];
                }
            }
            else {
                seg = [genColumn];
            }
            line.push(seg);
            reader.pos++;
        }
        if (!sorted)
            sort(line);
        decoded.push(line);
        reader.pos = semi + 1;
    } while (reader.pos <= length);
    return decoded;
}
function sort(line) {
    line.sort(sortComparator);
}
function sortComparator(a, b) {
    return a[0] - b[0];
}
function encode(decoded) {
    const writer = new StringWriter();
    let sourcesIndex = 0;
    let sourceLine = 0;
    let sourceColumn = 0;
    let namesIndex = 0;
    for (let i = 0; i < decoded.length; i++) {
        const line = decoded[i];
        if (i > 0)
            writer.write(semicolon);
        if (line.length === 0)
            continue;
        let genColumn = 0;
        for (let j = 0; j < line.length; j++) {
            const segment = line[j];
            if (j > 0)
                writer.write(comma);
            genColumn = encodeInteger(writer, segment[0], genColumn);
            if (segment.length === 1)
                continue;
            sourcesIndex = encodeInteger(writer, segment[1], sourcesIndex);
            sourceLine = encodeInteger(writer, segment[2], sourceLine);
            sourceColumn = encodeInteger(writer, segment[3], sourceColumn);
            if (segment.length === 4)
                continue;
            namesIndex = encodeInteger(writer, segment[4], namesIndex);
        }
    }
    return writer.flush();
}

export { decode, decodeGeneratedRanges, decodeOriginalScopes, encode, encodeGeneratedRanges, encodeOriginalScopes };
//# sourceMappingURL=sourcemap-codec.mjs.map