import { assert } from "./util.ts";
function decode(value: string): string { return value.replace(/\\(.)/g, "$1");}
function isDelimiter(code: number): boolean { return code === 0x22 || code === 0x28 || code === 0x29 || code === 0x2C || code === 0x2F || code >= 0x3A && code <= 0x40 || code >= 0x5B && code <= 0x5D || code === 0x7B || code === 0x7D; }
function isExtended(code: number): boolean { return code >= 0x80 && code <= 0xFF;}
function isPrint(code: number): boolean { return code >= 0x20 && code <= 0x7E;}
function isTokenChar(code: number): boolean { return code === 0x21 || code >= 0x23 && code <= 0x27 || code === 0x2A || code === 0x2B || code === 0x2D || code === 0x2E || code >= 0x30 && code <= 0x39 || code >= 0x41 && code <= 0x5A || code >= 0x5E && code <= 0x7A || code === 0x7C || code === 0x7E; }
export function parse(value: string): Record<string, string>[] | undefined { let parameter: undefined | string; let start = -1; let end = -1; let isEscaping = false; let inQuotes = false; let mustUnescape = false;
let code; let forwarded: Record<string, string> = {}; const output: Record<string, string>[] = []; let i;
for (i = 0; i < value.length; i++) { code = value.charCodeAt(i);
if (parameter === undefined) { if (i !== 0 && start === -1 && (code === 0x20 || code === 0x09)) { continue; }
if (isTokenChar(code)) { if (start === -1) { start = i; } } else if (code === 0x3D && start !== -1) { parameter = value.slice(start, i).toLowerCase(); start = -1; } else { return undefined; } } else { if ( isEscaping && (code === 0x09 || isPrint(code) || isExtended(code)) ) { isEscaping = false; } else if (isTokenChar(code)) { if (end !== -1) { return undefined; } if (start === -1) { start = i; } } else if (isDelimiter(code) || isExtended(code)) { if (inQuotes) { if (code === 0x22) { inQuotes = false; end = i; } else if (code === 0x5C) { if (start === -1) { start = i; } isEscaping = mustUnescape = true; } else if (start === -1) { start = i; } } else if (code === 0x22 && value.charCodeAt(i - 1) === 0x3D) { inQuotes = true; } else if ( (code === 0x2C || code === 0x3B) && (start !== -1 || end !== -1) ) { assert(parameter, "Variable 'parameter' not defined."); if (start !== -1) { if (end === -1) { end = i; }
forwarded[parameter] = mustUnescape ? decode(value.slice(start, end)) : value.slice(start, end); } else { forwarded[parameter] = ""; }
if (code === 0x2C) { output.push(forwarded); forwarded = {}; }
parameter = undefined; start = end = -1; } else { return undefined; } } else if (code === 0x20 || code === 0x09) { if (end !== -1) { continue; }
if (inQuotes) { if (start === -1) { start = i; } } else if (start !== -1) { end = i; } else { return undefined; } } else { return undefined; } } }
if ( parameter === undefined || inQuotes || (start === -1 && end === -1) || code === 0x20 || code === 0x09 ) { return undefined; }
if (start !== -1) { if (end === -1) { end = i; } forwarded[parameter] = mustUnescape ? decode(value.slice(start, end)) : value.slice(start, end); } else { forwarded[parameter] = ""; }
output.push(forwarded); return output;}