import { concat } from "../bytes/mod.ts";
const CHAR_SPACE = " ".charCodeAt(0);
const CHAR_TAB = "\t".charCodeAt(0);
const CHAR_COLON = ":".charCodeAt(0);
const WHITESPACES = [CHAR_SPACE, CHAR_TAB];
const decoder = new TextDecoder();
const invalidHeaderCharRegex = /[^\t\x20-\x7e\x80-\xff]/g;
function str(buf) {
    return !buf ? "" : decoder.decode(buf);
}
export class TextProtoReader {
    r;
    constructor(r) {
        this.r = r;
    }
    async readLine() {
        const s = await this.readLineSlice();
        return s === null ? null : str(s);
    }
    async readMIMEHeader() {
        const m = new Headers();
        let line;
        let buf = await this.r.peek(1);
        if (buf === null) {
            return null;
        }
        else if (WHITESPACES.includes(buf[0])) {
            line = (await this.readLineSlice());
        }
        buf = await this.r.peek(1);
        if (buf === null) {
            throw new Deno.errors.UnexpectedEof();
        }
        else if (WHITESPACES.includes(buf[0])) {
            throw new Deno.errors.InvalidData(`malformed MIME header initial line: ${str(line)}`);
        }
        while (true) {
            const kv = await this.readLineSlice();
            if (kv === null)
                throw new Deno.errors.UnexpectedEof();
            if (kv.byteLength === 0)
                return m;
            let i = kv.indexOf(CHAR_COLON);
            if (i < 0) {
                throw new Deno.errors.InvalidData(`malformed MIME header line: ${str(kv)}`);
            }
            const key = str(kv.subarray(0, i));
            if (key == "") {
                continue;
            }
            i++;
            while (i < kv.byteLength &&
                (WHITESPACES.includes(kv[i]))) {
                i++;
            }
            const value = str(kv.subarray(i)).replace(invalidHeaderCharRegex, encodeURI);
            try {
                m.append(key, value);
            }
            catch {
            }
        }
    }
    async readLineSlice() {
        let line = new Uint8Array(0);
        let r = null;
        do {
            r = await this.r.readLine();
            if (r !== null && this.skipSpace(r.line) !== 0) {
                line = concat(line, r.line);
            }
        } while (r !== null && r.more);
        return r === null ? null : line;
    }
    skipSpace(l) {
        let n = 0;
        for (const val of l) {
            if (!WHITESPACES.includes(val)) {
                n++;
            }
        }
        return n;
    }
}
//# sourceMappingURL=data:application/json;base64,[encoded data, 10444 characters]