structured-headers
Version:
Implementation of Structured Field Values for HTTP (RFC9651, RFC8941)
1 lines • 32.8 kB
Source Map (JSON)
{"version":3,"sources":["../src/index.ts","../src/util.ts","../src/token.ts","../src/displaystring.ts","../src/serializer.ts","../src/parser.ts"],"sourcesContent":["export * from './serializer.js';\nexport * from './parser.js';\nexport * from './types.js';\nexport * from './util.js';\nexport { Token } from './token.js';\nexport { DisplayString } from './displaystring.js';\n","import { Item, InnerList } from './types.js';\n\nconst asciiRe = /^[\\x20-\\x7E]*$/;\nconst tokenRe = /^[a-zA-Z*][:/!#$%&'*+\\-.^_`|~A-Za-z0-9]*$/;\nconst keyRe = /^[a-z*][*\\-_.a-z0-9]*$/;\n\nexport function isAscii(str: string): boolean {\n\n return asciiRe.test(str);\n\n}\n\nexport function isValidTokenStr(str: string): boolean {\n\n return tokenRe.test(str);\n\n}\n\nexport function isValidKeyStr(str: string): boolean {\n\n return keyRe.test(str);\n\n}\n\n\nexport function isInnerList(input: Item | InnerList): input is InnerList {\n\n return Array.isArray(input[0]);\n\n}\n\nexport function arrayBufferToBase64(ab: ArrayBuffer): string {\n\n // Create a Uint8Array to read the ArrayBuffer as bytes\n const bytes = new Uint8Array(ab);\n let binary = '';\n\n // Convert each byte to a character\n for (const byte of bytes) {\n binary += String.fromCharCode(byte);\n }\n\n // Encode the binary string as Base64\n return btoa(binary);\n}\n\nexport function base64ToArrayBuffer(b64: string): ArrayBuffer {\n\n // Decode the base64 string into a binary string\n const binaryString = atob(b64);\n\n // Create a new ArrayBuffer with the same length as the binary string\n const len = binaryString.length;\n const bytes = new Uint8Array(len);\n\n // Convert each character to its corresponding byte\n for (let i = 0; i < len; i++) {\n bytes[i] = binaryString.charCodeAt(i);\n }\n\n // Return the ArrayBuffer\n return bytes.buffer;\n\n}\n","import { isValidTokenStr } from './util.js';\n\nexport class Token {\n\n private value: string;\n constructor(value: string) {\n\n if (!isValidTokenStr(value)) {\n throw new TypeError('Invalid character in Token string. Tokens must start with *, A-Z and the rest of the string may only contain a-z, A-Z, 0-9, :/!#$%&\\'*+-.^_`|~');\n }\n this.value = value;\n\n }\n\n toString(): string {\n\n return this.value;\n\n }\n\n}\n","export class DisplayString {\n\n private value: string;\n constructor(value: string) {\n\n this.value = value;\n\n }\n\n toString(): string {\n\n return this.value;\n\n }\n\n}\n","import {\n BareItem,\n Dictionary,\n DictionaryObject,\n InnerList,\n Item,\n List,\n Parameters,\n} from './types.js';\n\nimport { Token } from './token.js';\n\nimport { isAscii, isInnerList, isValidKeyStr, arrayBufferToBase64 } from './util.js';\nimport { DisplayString } from './displaystring.js';\n\nexport class SerializeError extends Error {}\n\nexport function serializeList(input: List): string {\n\n return input.map(value => {\n\n if (isInnerList(value)) {\n return serializeInnerList(value);\n } else {\n return serializeItem(value);\n }\n\n }).join(', ');\n\n}\n\nexport function serializeDictionary(input: Dictionary | DictionaryObject): string {\n\n const entries: Iterable<[string, BareItem|Item|InnerList]> = input instanceof Map ? input.entries() : Object.entries(input);\n\n return Array.from(entries).map(([key, entry]) => {\n\n const keyStr = serializeKey(key);\n\n if (Array.isArray(entry)) {\n if (entry[0]===true) {\n return keyStr + serializeParameters(entry[1]);\n } else {\n if (isInnerList(entry)) {\n return keyStr + '=' + serializeInnerList(entry);\n } else {\n return keyStr + '=' + serializeItem(entry);\n }\n }\n } else {\n if (entry===true) {\n return keyStr;\n } else {\n return keyStr + '=' + serializeBareItem(entry);\n }\n }\n\n }).join(', ');\n\n}\n\n/**\n * Serialize a Structured Fields Item.\n *\n * An Item is a standalone value like a string, number of date, followed by\n * an optional set of parameters.\n *\n * You can either pass the value in the first argument and parameters in the second, or pass both as a tuple. The later exists for symmetry with parseItem.\n */\nexport function serializeItem(input: Item): string;\nexport function serializeItem(input: BareItem, params?: Parameters): string;\nexport function serializeItem(input: Item|BareItem, params?: Parameters): string {\n\n if (Array.isArray(input)) {\n return serializeBareItem(input[0]) + serializeParameters(input[1]);\n } else {\n return serializeBareItem(input) + (params?serializeParameters(params):'');\n }\n\n}\n\nexport function serializeInnerList(input: InnerList): string {\n\n return `(${input[0].map(value => serializeItem(value)).join(' ')})${serializeParameters(input[1])}`;\n\n}\n\n\nexport function serializeBareItem(input: BareItem): string {\n if (typeof input === 'number') {\n if (Number.isInteger(input)) {\n return serializeInteger(input);\n }\n return serializeDecimal(input);\n }\n if (typeof input === 'string') {\n return serializeString(input);\n }\n if (input instanceof Token) {\n return serializeToken(input);\n }\n if (input instanceof ArrayBuffer) {\n return serializeByteSequence(input);\n }\n if (input instanceof DisplayString) {\n return serializeDisplayString(input);\n }\n if (input instanceof Date) {\n return serializeDate(input);\n }\n if (typeof input === 'boolean') {\n return serializeBoolean(input);\n }\n throw new SerializeError(`Cannot serialize values of type ${typeof input}`);\n}\n\nexport function serializeInteger(input: number): string {\n\n if (input < -999_999_999_999_999 || input > 999_999_999_999_999) {\n throw new SerializeError('Structured headers can only encode integers in the range range of -999,999,999,999,999 to 999,999,999,999,999 inclusive');\n }\n return input.toString();\n}\n\nexport function serializeDecimal(input: number): string {\n const out = input.toFixed(3).replace(/0+$/,'');\n const signifantDigits = out.split('.')[0].replace('-','').length;\n\n if (signifantDigits > 12) {\n throw new SerializeError('Fractional numbers are not allowed to have more than 12 significant digits before the decimal point');\n }\n return out;\n}\n\nexport function serializeString(input: string): string {\n if (!isAscii(input)) {\n throw new SerializeError('Only ASCII strings may be serialized');\n }\n return `\"${input.replace(/(\"|\\\\)/g, (v) => '\\\\' + v)}\"`;\n}\n\nexport function serializeDisplayString(input: DisplayString): string {\n let out = '%\"';\n const textEncoder = new TextEncoder();\n for (const char of textEncoder.encode(input.toString())) {\n if (\n char === 0x25 // %\n || char === 0x22 // \"\n || char <= 0x1f\n || char >= 0x7f\n ) {\n out += '%' + char.toString(16);\n } else {\n out += String.fromCharCode(char);\n }\n }\n return out + '\"';\n}\n\nexport function serializeBoolean(input: boolean): string {\n return input ? '?1' : '?0';\n}\n\nexport function serializeByteSequence(input: ArrayBuffer): string {\n return `:${arrayBufferToBase64(input)}:`;\n}\n\nexport function serializeToken(input: Token): string {\n return input.toString();\n}\n\nexport function serializeDate(input: Date): string {\n return '@' + Math.floor(input.getTime()/1000);\n}\n\nexport function serializeParameters(input: Parameters): string {\n\n return Array.from(input).map(([key, value]) => {\n\n let out = ';' + serializeKey(key);\n if (value!==true) {\n out+='=' + serializeBareItem(value);\n }\n return out;\n\n }).join('');\n\n}\n\nexport function serializeKey(input: string): string {\n\n if (!isValidKeyStr(input)) {\n throw new SerializeError('Keys in dictionaries must only contain lowercase letter, numbers, _-*. and must start with a letter or *');\n }\n return input;\n\n}\n","import {\n Dictionary,\n List,\n Item,\n BareItem,\n Parameters,\n InnerList,\n} from './types.js';\n\nimport { Token } from './token.js';\n\nimport { isAscii, base64ToArrayBuffer } from './util.js';\nimport { DisplayString } from './displaystring.js';\n\nexport function parseDictionary(input: string): Dictionary {\n\n const parser = new Parser(input);\n return parser.parseDictionary();\n\n}\n\nexport function parseList(input: string): List {\n\n const parser = new Parser(input);\n return parser.parseList();\n\n}\n\nexport function parseItem(input: string): Item {\n\n const parser = new Parser(input);\n return parser.parseItem();\n\n}\n\nexport class ParseError extends Error {\n\n constructor(position: number, message:string) {\n\n super(`Parse error: ${message} at offset ${position}`);\n\n }\n\n}\n\nexport default class Parser {\n\n input: string;\n pos: number;\n\n constructor(input: string) {\n this.input = input;\n this.pos = 0;\n }\n\n parseDictionary(): Dictionary {\n\n this.skipWS();\n const dictionary = new Map();\n while(!this.eof()) {\n\n const thisKey = this.parseKey();\n let member;\n if (this.lookChar()==='=') {\n this.pos++;\n member = this.parseItemOrInnerList();\n } else {\n member = [true, this.parseParameters()];\n }\n dictionary.set(thisKey, member);\n this.skipOWS();\n if (this.eof()) {\n return dictionary;\n }\n this.expectChar(',');\n this.pos++;\n this.skipOWS();\n if (this.eof()) {\n throw new ParseError(this.pos, 'Dictionary contained a trailing comma');\n }\n }\n return dictionary;\n\n }\n\n parseList(): List {\n\n this.skipWS();\n const members: List = [];\n while(!this.eof()) {\n members.push(\n this.parseItemOrInnerList()\n );\n this.skipOWS();\n if (this.eof()) {\n return members;\n }\n this.expectChar(',');\n this.pos++;\n this.skipOWS();\n if (this.eof()) {\n throw new ParseError(this.pos, 'A list may not end with a trailing comma');\n }\n }\n\n return members;\n\n }\n\n parseItem(standaloneItem: boolean = true): Item {\n\n if (standaloneItem) this.skipWS();\n\n const result: Item = [\n this.parseBareItem(),\n this.parseParameters()\n ];\n\n if (standaloneItem) this.checkTrail();\n return result;\n\n }\n\n private parseItemOrInnerList(): Item|InnerList {\n\n if (this.lookChar()==='(') {\n return this.parseInnerList();\n } else {\n return this.parseItem(false);\n }\n\n }\n\n private parseInnerList(): InnerList {\n\n this.expectChar('(');\n this.pos++;\n\n const innerList: Item[] = [];\n\n while(!this.eof()) {\n this.skipWS();\n if (this.lookChar() === ')') {\n this.pos++;\n return [\n innerList,\n this.parseParameters()\n ];\n }\n\n innerList.push(this.parseItem(false));\n\n const nextChar = this.lookChar();\n if (nextChar!==' ' && nextChar !== ')') {\n throw new ParseError(this.pos, 'Expected a whitespace or ) after every item in an inner list');\n }\n }\n\n\n throw new ParseError(this.pos, 'Could not find end of inner list');\n\n }\n\n private parseBareItem(): BareItem {\n\n const char = this.lookChar();\n if (char === undefined) {\n throw new ParseError(this.pos, 'Unexpected end of string');\n }\n if (char.match(/^[-0-9]/)) {\n return this.parseIntegerOrDecimal();\n }\n if (char === '\"') {\n return this.parseString();\n }\n if (char.match(/^[A-Za-z*]/)) {\n return this.parseToken();\n }\n if (char === ':' ) {\n return this.parseByteSequence();\n }\n if (char === '?') {\n return this.parseBoolean();\n }\n if (char === '@') {\n return this.parseDate();\n }\n if (char === '%') {\n return this.parseDisplayString();\n }\n throw new ParseError(this.pos, 'Unexpected input');\n\n }\n\n private parseParameters(): Parameters {\n\n const parameters = new Map();\n while(!this.eof()) {\n const char = this.lookChar();\n if (char!==';') {\n break;\n }\n this.pos++;\n this.skipWS();\n const key = this.parseKey();\n let value: BareItem = true;\n if (this.lookChar() === '=') {\n this.pos++;\n value = this.parseBareItem();\n }\n parameters.set(key, value);\n }\n\n return parameters;\n\n }\n\n private parseIntegerOrDecimal(): number {\n\n let type: 'integer' | 'decimal' = 'integer';\n let sign = 1;\n let inputNumber = '';\n if (this.lookChar()==='-') {\n sign = -1;\n this.pos++;\n }\n\n // The spec wants this check but it's unreachable code.\n //if (this.eof()) {\n // throw new ParseError(this.pos, 'Empty integer');\n //}\n\n if (!isDigit(this.lookChar())) {\n throw new ParseError(this.pos, 'Expected a digit (0-9)');\n }\n\n while(!this.eof()) {\n const char = this.getChar();\n if (isDigit(char)) {\n inputNumber+=char;\n } else if (type === 'integer' && char === '.') {\n if (inputNumber.length>12) {\n throw new ParseError(this.pos, 'Exceeded maximum decimal length');\n }\n inputNumber+='.';\n type = 'decimal';\n } else {\n // We need to 'prepend' the character, so it's just a rewind\n this.pos--;\n break;\n }\n\n if (type === 'integer' && inputNumber.length>15) {\n throw new ParseError(this.pos, 'Exceeded maximum integer length');\n }\n if (type === 'decimal' && inputNumber.length>16) {\n throw new ParseError(this.pos, 'Exceeded maximum decimal length');\n }\n }\n\n if (type === 'integer') {\n return parseInt(inputNumber, 10) * sign;\n } else {\n if (inputNumber.endsWith('.')) {\n throw new ParseError(this.pos, 'Decimal cannot end on a period');\n }\n if (inputNumber.split('.')[1].length>3) {\n throw new ParseError(this.pos, 'Number of digits after the decimal point cannot exceed 3');\n }\n return parseFloat(inputNumber) * sign;\n }\n\n }\n\n private parseString(): string {\n\n let outputString = '';\n this.expectChar('\"');\n this.pos++;\n\n while(!this.eof()) {\n const char = this.getChar();\n if (char==='\\\\') {\n if (this.eof()) {\n throw new ParseError(this.pos, 'Unexpected end of input');\n }\n const nextChar = this.getChar();\n if (nextChar!=='\\\\' && nextChar !== '\"') {\n throw new ParseError(this.pos, 'A backslash must be followed by another backslash or double quote');\n }\n outputString+=nextChar;\n } else if (char === '\"') {\n return outputString;\n } else if (!isAscii(char)) {\n throw new ParseError(this.pos, 'Strings must be in the ASCII range');\n } else {\n outputString += char;\n }\n\n }\n throw new ParseError(this.pos, 'Unexpected end of input');\n\n }\n\n private parseDisplayString(): DisplayString {\n\n const chars = this.getChars(2);\n if (chars !== '%\"') {\n throw new ParseError(this.pos, 'Unexpected character. Display strings should start with %=');\n }\n\n const result:number[] = [];\n\n while (!this.eof()) {\n\n const char = this.getChar();\n if (char.charCodeAt(0) <= 0x1F || (char.charCodeAt(0) >= 0x7F && char.charCodeAt(0) <= 0xFF)) {\n throw new ParseError(this.pos, 'Invalid char found in DisplayString. Did you forget to escape?');\n }\n\n if (char==='%') {\n const hexChars = this.getChars(2);\n if (/^[0-9a-f]{2}$/.test(hexChars)) {\n result.push(parseInt(hexChars, 16));\n } else {\n throw new ParseError(this.pos, `Unexpected sequence after % in DispalyString: \"${hexChars}\". Note that hexidecimals must be lowercase`);\n }\n continue;\n }\n if (char==='\"') {\n const textDecoder = new TextDecoder('utf-8', {\n fatal: true\n });\n try {\n return new DisplayString(\n textDecoder.decode(new Uint8Array(result))\n );\n } catch {\n throw new ParseError(this.pos, 'Fatal error decoding UTF-8 sequence in Display String');\n }\n }\n result.push(char.charCodeAt(0));\n }\n throw new ParseError(this.pos, 'Unexpected end of input');\n\n }\n\n private parseToken(): Token {\n\n // The specification wants this check, but it's an unreachable code block.\n // if (!/^[A-Za-z*]/.test(this.lookChar())) {\n // throw new ParseError(this.pos, 'A token must begin with an asterisk or letter (A-Z, a-z)');\n //}\n\n let outputString = '';\n\n while(!this.eof()) {\n const char = this.lookChar();\n if (char===undefined || !/^[:/!#$%&'*+\\-.^_`|~A-Za-z0-9]$/.test(char)) {\n return new Token(outputString);\n }\n outputString += this.getChar();\n }\n\n return new Token(outputString);\n\n }\n\n private parseByteSequence(): ArrayBuffer {\n\n this.expectChar(':');\n this.pos++;\n const endPos = this.input.indexOf(':', this.pos);\n if (endPos === -1) {\n throw new ParseError(this.pos, 'Could not find a closing \":\" character to mark end of Byte Sequence');\n }\n const b64Content = this.input.substring(this.pos, endPos);\n this.pos += b64Content.length+1;\n\n if (!/^[A-Za-z0-9+/=]*$/.test(b64Content)) {\n throw new ParseError(this.pos, 'ByteSequence does not contain a valid base64 string');\n }\n\n try {\n return base64ToArrayBuffer(b64Content);\n } catch {\n throw new ParseError(this.pos, 'ByteSequence does not contain a valid base64 string');\n }\n\n }\n\n private parseBoolean(): boolean {\n\n this.expectChar('?');\n this.pos++;\n\n const char = this.getChar();\n if (char === '1') {\n return true;\n }\n if (char === '0') {\n return false;\n }\n throw new ParseError(this.pos, 'Unexpected character. Expected a \"1\" or a \"0\"');\n\n }\n\n private parseDate(): Date {\n\n this.expectChar('@');\n this.pos++;\n let sign = 1;\n let inputNumber = '';\n if (this.lookChar()==='-') {\n sign = -1;\n this.pos++;\n }\n\n if (!isDigit(this.lookChar())) {\n throw new ParseError(this.pos, 'Expected a digit (0-9)');\n }\n\n while(!this.eof()) {\n const char = this.getChar();\n if (isDigit(char)) {\n inputNumber+=char;\n } else {\n throw new ParseError(this.pos, 'Expected a digit (0-9), whitespace or EOL');\n }\n }\n\n return new Date(parseInt(inputNumber,10)*sign*1000);\n\n }\n\n private parseKey(): string {\n\n if (!this.lookChar()?.match(/^[a-z*]/)) {\n throw new ParseError(this.pos, 'A key must begin with an asterisk or letter (a-z)');\n }\n\n let outputString = '';\n\n while(!this.eof()) {\n const char = this.lookChar();\n if (char===undefined || !/^[a-z0-9_\\-.*]$/.test(char)) {\n return outputString;\n }\n outputString += this.getChar();\n }\n\n return outputString;\n\n }\n\n /**\n * Looks at the next character without advancing the cursor.\n *\n * Returns undefined if we were at the end of the string.\n */\n private lookChar():string|undefined {\n\n return this.input[this.pos];\n\n }\n\n /**\n * Checks if the next character is 'char', and fail otherwise.\n */\n private expectChar(char: string): void {\n\n if (this.lookChar()!==char) {\n throw new ParseError(this.pos, `Expected ${char}`);\n }\n\n }\n\n private getChar(): string {\n\n return this.input[this.pos++];\n\n }\n private getChars(count: number): string {\n\n const result = this.input.substr(\n this.pos,\n count\n );\n this.pos += count;\n return result;\n\n }\n private eof():boolean {\n\n return this.pos>=this.input.length;\n\n }\n // Advances the pointer to skip all whitespace.\n private skipOWS(): void {\n\n while (true) {\n const c = this.input.substr(this.pos, 1);\n if (c === ' ' || c === '\\t') {\n this.pos++;\n } else {\n break;\n }\n }\n\n }\n // Advances the pointer to skip all spaces\n private skipWS(): void {\n\n while(this.lookChar()===' ') {\n this.pos++;\n }\n\n }\n\n // At the end of parsing, we need to make sure there are no bytes after the\n // header except whitespace.\n private checkTrail(): void {\n\n this.skipWS();\n if (!this.eof()) {\n throw new ParseError(this.pos, 'Unexpected characters at end of input');\n }\n\n }\n\n}\n\nconst isDigitRegex = /^[0-9]$/;\nfunction isDigit(char: string|undefined): boolean {\n\n if (char===undefined) return false;\n return isDigitRegex.test(char);\n\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,IAAM,UAAU;AAChB,IAAM,UAAU;AAChB,IAAM,QAAQ;AAEP,SAAS,QAAQ,KAAsB;AAE5C,SAAO,QAAQ,KAAK,GAAG;AAEzB;AAEO,SAAS,gBAAgB,KAAsB;AAEpD,SAAO,QAAQ,KAAK,GAAG;AAEzB;AAEO,SAAS,cAAc,KAAsB;AAElD,SAAO,MAAM,KAAK,GAAG;AAEvB;AAGO,SAAS,YAAY,OAA6C;AAEvE,SAAO,MAAM,QAAQ,MAAM,CAAC,CAAC;AAE/B;AAEO,SAAS,oBAAoB,IAAyB;AAG3D,QAAM,QAAQ,IAAI,WAAW,EAAE;AAC/B,MAAI,SAAS;AAGb,aAAW,QAAQ,OAAO;AACxB,cAAU,OAAO,aAAa,IAAI;AAAA,EACpC;AAGA,SAAO,KAAK,MAAM;AACpB;AAEO,SAAS,oBAAoB,KAA0B;AAG5D,QAAM,eAAe,KAAK,GAAG;AAG7B,QAAM,MAAM,aAAa;AACzB,QAAM,QAAQ,IAAI,WAAW,GAAG;AAGhC,WAAS,IAAI,GAAG,IAAI,KAAK,KAAK;AAC5B,UAAM,CAAC,IAAI,aAAa,WAAW,CAAC;AAAA,EACtC;AAGA,SAAO,MAAM;AAEf;;;AC7DO,IAAM,QAAN,MAAY;AAAA,EAGjB,YAAY,OAAe;AAEzB,QAAI,CAAC,gBAAgB,KAAK,GAAG;AAC3B,YAAM,IAAI,UAAU,+IAAgJ;AAAA,IACtK;AACA,SAAK,QAAQ;AAAA,EAEf;AAAA,EAEA,WAAmB;AAEjB,WAAO,KAAK;AAAA,EAEd;AAEF;;;ACpBO,IAAM,gBAAN,MAAoB;AAAA,EAGzB,YAAY,OAAe;AAEzB,SAAK,QAAQ;AAAA,EAEf;AAAA,EAEA,WAAmB;AAEjB,WAAO,KAAK;AAAA,EAEd;AAEF;;;ACAO,IAAM,iBAAN,cAA6B,MAAM;AAAC;AAEpC,SAAS,cAAc,OAAqB;AAEjD,SAAO,MAAM,IAAI,WAAS;AAExB,QAAI,YAAY,KAAK,GAAG;AACtB,aAAO,mBAAmB,KAAK;AAAA,IACjC,OAAO;AACL,aAAO,cAAc,KAAK;AAAA,IAC5B;AAAA,EAEF,CAAC,EAAE,KAAK,IAAI;AAEd;AAEO,SAAS,oBAAoB,OAA8C;AAEhF,QAAM,UAAuD,iBAAiB,MAAM,MAAM,QAAQ,IAAI,OAAO,QAAQ,KAAK;AAE1H,SAAO,MAAM,KAAK,OAAO,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;AAE/C,UAAM,SAAS,aAAa,GAAG;AAE/B,QAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,UAAI,MAAM,CAAC,MAAI,MAAM;AACnB,eAAO,SAAS,oBAAoB,MAAM,CAAC,CAAC;AAAA,MAC9C,OAAO;AACL,YAAI,YAAY,KAAK,GAAG;AACtB,iBAAO,SAAS,MAAM,mBAAmB,KAAK;AAAA,QAChD,OAAO;AACL,iBAAO,SAAS,MAAM,cAAc,KAAK;AAAA,QAC3C;AAAA,MACF;AAAA,IACF,OAAO;AACL,UAAI,UAAQ,MAAM;AAChB,eAAO;AAAA,MACT,OAAO;AACL,eAAO,SAAS,MAAM,kBAAkB,KAAK;AAAA,MAC/C;AAAA,IACF;AAAA,EAEF,CAAC,EAAE,KAAK,IAAI;AAEd;AAYO,SAAS,cAAc,OAAsB,QAA6B;AAE/E,MAAI,MAAM,QAAQ,KAAK,GAAG;AACxB,WAAO,kBAAkB,MAAM,CAAC,CAAC,IAAI,oBAAoB,MAAM,CAAC,CAAC;AAAA,EACnE,OAAO;AACL,WAAO,kBAAkB,KAAK,KAAK,SAAO,oBAAoB,MAAM,IAAE;AAAA,EACxE;AAEF;AAEO,SAAS,mBAAmB,OAA0B;AAE3D,SAAO,IAAI,MAAM,CAAC,EAAE,IAAI,WAAS,cAAc,KAAK,CAAC,EAAE,KAAK,GAAG,CAAC,IAAI,oBAAoB,MAAM,CAAC,CAAC,CAAC;AAEnG;AAGO,SAAS,kBAAkB,OAAyB;AACzD,MAAI,OAAO,UAAU,UAAU;AAC7B,QAAI,OAAO,UAAU,KAAK,GAAG;AAC3B,aAAO,iBAAiB,KAAK;AAAA,IAC/B;AACA,WAAO,iBAAiB,KAAK;AAAA,EAC/B;AACA,MAAI,OAAO,UAAU,UAAU;AAC7B,WAAO,gBAAgB,KAAK;AAAA,EAC9B;AACA,MAAI,iBAAiB,OAAO;AAC1B,WAAO,eAAe,KAAK;AAAA,EAC7B;AACA,MAAI,iBAAiB,aAAa;AAChC,WAAO,sBAAsB,KAAK;AAAA,EACpC;AACA,MAAI,iBAAiB,eAAe;AAClC,WAAO,uBAAuB,KAAK;AAAA,EACrC;AACA,MAAI,iBAAiB,MAAM;AACzB,WAAO,cAAc,KAAK;AAAA,EAC5B;AACA,MAAI,OAAO,UAAU,WAAW;AAC9B,WAAO,iBAAiB,KAAK;AAAA,EAC/B;AACA,QAAM,IAAI,eAAe,mCAAmC,OAAO,KAAK,EAAE;AAC5E;AAEO,SAAS,iBAAiB,OAAuB;AAEtD,MAAI,QAAQ,oBAAwB,QAAQ,iBAAqB;AAC/D,UAAM,IAAI,eAAe,yHAAyH;AAAA,EACpJ;AACA,SAAO,MAAM,SAAS;AACxB;AAEO,SAAS,iBAAiB,OAAuB;AACtD,QAAM,MAAM,MAAM,QAAQ,CAAC,EAAE,QAAQ,OAAM,EAAE;AAC7C,QAAM,kBAAkB,IAAI,MAAM,GAAG,EAAE,CAAC,EAAE,QAAQ,KAAI,EAAE,EAAE;AAE1D,MAAI,kBAAkB,IAAI;AACxB,UAAM,IAAI,eAAe,qGAAqG;AAAA,EAChI;AACA,SAAO;AACT;AAEO,SAAS,gBAAgB,OAAuB;AACrD,MAAI,CAAC,QAAQ,KAAK,GAAG;AACnB,UAAM,IAAI,eAAe,sCAAsC;AAAA,EACjE;AACA,SAAO,IAAI,MAAM,QAAQ,WAAW,CAAC,MAAM,OAAO,CAAC,CAAC;AACtD;AAEO,SAAS,uBAAuB,OAA8B;AACnE,MAAI,MAAM;AACV,QAAM,cAAc,IAAI,YAAY;AACpC,aAAW,QAAQ,YAAY,OAAO,MAAM,SAAS,CAAC,GAAG;AACvD,QACE,SAAS,MACN,SAAS,MACT,QAAQ,MACR,QAAQ,KACX;AACA,aAAO,MAAM,KAAK,SAAS,EAAE;AAAA,IAC/B,OAAO;AACL,aAAO,OAAO,aAAa,IAAI;AAAA,IACjC;AAAA,EACF;AACA,SAAO,MAAM;AACf;AAEO,SAAS,iBAAiB,OAAwB;AACvD,SAAO,QAAQ,OAAO;AACxB;AAEO,SAAS,sBAAsB,OAA4B;AAChE,SAAO,IAAI,oBAAoB,KAAK,CAAC;AACvC;AAEO,SAAS,eAAe,OAAsB;AACnD,SAAO,MAAM,SAAS;AACxB;AAEO,SAAS,cAAc,OAAqB;AACjD,SAAO,MAAM,KAAK,MAAM,MAAM,QAAQ,IAAE,GAAI;AAC9C;AAEO,SAAS,oBAAoB,OAA2B;AAE7D,SAAO,MAAM,KAAK,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;AAE7C,QAAI,MAAM,MAAM,aAAa,GAAG;AAChC,QAAI,UAAQ,MAAM;AAChB,aAAK,MAAM,kBAAkB,KAAK;AAAA,IACpC;AACA,WAAO;AAAA,EAET,CAAC,EAAE,KAAK,EAAE;AAEZ;AAEO,SAAS,aAAa,OAAuB;AAElD,MAAI,CAAC,cAAc,KAAK,GAAG;AACzB,UAAM,IAAI,eAAe,0GAA0G;AAAA,EACrI;AACA,SAAO;AAET;;;ACtLO,SAAS,gBAAgB,OAA2B;AAEzD,QAAM,SAAS,IAAI,OAAO,KAAK;AAC/B,SAAO,OAAO,gBAAgB;AAEhC;AAEO,SAAS,UAAU,OAAqB;AAE7C,QAAM,SAAS,IAAI,OAAO,KAAK;AAC/B,SAAO,OAAO,UAAU;AAE1B;AAEO,SAAS,UAAU,OAAqB;AAE7C,QAAM,SAAS,IAAI,OAAO,KAAK;AAC/B,SAAO,OAAO,UAAU;AAE1B;AAEO,IAAM,aAAN,cAAyB,MAAM;AAAA,EAEpC,YAAY,UAAkB,SAAgB;AAE5C,UAAM,gBAAgB,OAAO,cAAc,QAAQ,EAAE;AAAA,EAEvD;AAEF;AAEA,IAAqB,SAArB,MAA4B;AAAA,EAK1B,YAAY,OAAe;AACzB,SAAK,QAAQ;AACb,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,kBAA8B;AAE5B,SAAK,OAAO;AACZ,UAAM,aAAa,oBAAI,IAAI;AAC3B,WAAM,CAAC,KAAK,IAAI,GAAG;AAEjB,YAAM,UAAU,KAAK,SAAS;AAC9B,UAAI;AACJ,UAAI,KAAK,SAAS,MAAI,KAAK;AACzB,aAAK;AACL,iBAAS,KAAK,qBAAqB;AAAA,MACrC,OAAO;AACL,iBAAS,CAAC,MAAM,KAAK,gBAAgB,CAAC;AAAA,MACxC;AACA,iBAAW,IAAI,SAAS,MAAM;AAC9B,WAAK,QAAQ;AACb,UAAI,KAAK,IAAI,GAAG;AACd,eAAO;AAAA,MACT;AACA,WAAK,WAAW,GAAG;AACnB,WAAK;AACL,WAAK,QAAQ;AACb,UAAI,KAAK,IAAI,GAAG;AACd,cAAM,IAAI,WAAW,KAAK,KAAK,uCAAuC;AAAA,MACxE;AAAA,IACF;AACA,WAAO;AAAA,EAET;AAAA,EAEA,YAAkB;AAEhB,SAAK,OAAO;AACZ,UAAM,UAAgB,CAAC;AACvB,WAAM,CAAC,KAAK,IAAI,GAAG;AACjB,cAAQ;AAAA,QACN,KAAK,qBAAqB;AAAA,MAC5B;AACA,WAAK,QAAQ;AACb,UAAI,KAAK,IAAI,GAAG;AACd,eAAO;AAAA,MACT;AACA,WAAK,WAAW,GAAG;AACnB,WAAK;AACL,WAAK,QAAQ;AACb,UAAI,KAAK,IAAI,GAAG;AACd,cAAM,IAAI,WAAW,KAAK,KAAK,0CAA0C;AAAA,MAC3E;AAAA,IACF;AAEA,WAAO;AAAA,EAET;AAAA,EAEA,UAAU,iBAA0B,MAAY;AAE9C,QAAI,eAAgB,MAAK,OAAO;AAEhC,UAAM,SAAe;AAAA,MACnB,KAAK,cAAc;AAAA,MACnB,KAAK,gBAAgB;AAAA,IACvB;AAEA,QAAI,eAAgB,MAAK,WAAW;AACpC,WAAO;AAAA,EAET;AAAA,EAEQ,uBAAuC;AAE7C,QAAI,KAAK,SAAS,MAAI,KAAK;AACzB,aAAO,KAAK,eAAe;AAAA,IAC7B,OAAO;AACL,aAAO,KAAK,UAAU,KAAK;AAAA,IAC7B;AAAA,EAEF;AAAA,EAEQ,iBAA4B;AAElC,SAAK,WAAW,GAAG;AACnB,SAAK;AAEL,UAAM,YAAoB,CAAC;AAE3B,WAAM,CAAC,KAAK,IAAI,GAAG;AACjB,WAAK,OAAO;AACZ,UAAI,KAAK,SAAS,MAAM,KAAK;AAC3B,aAAK;AACL,eAAO;AAAA,UACL;AAAA,UACA,KAAK,gBAAgB;AAAA,QACvB;AAAA,MACF;AAEA,gBAAU,KAAK,KAAK,UAAU,KAAK,CAAC;AAEpC,YAAM,WAAW,KAAK,SAAS;AAC/B,UAAI,aAAW,OAAO,aAAa,KAAK;AACtC,cAAM,IAAI,WAAW,KAAK,KAAK,8DAA8D;AAAA,MAC/F;AAAA,IACF;AAGA,UAAM,IAAI,WAAW,KAAK,KAAK,kCAAkC;AAAA,EAEnE;AAAA,EAEQ,gBAA0B;AAEhC,UAAM,OAAO,KAAK,SAAS;AAC3B,QAAI,SAAS,QAAW;AACtB,YAAM,IAAI,WAAW,KAAK,KAAK,0BAA0B;AAAA,IAC3D;AACA,QAAI,KAAK,MAAM,SAAS,GAAG;AACzB,aAAO,KAAK,sBAAsB;AAAA,IACpC;AACA,QAAI,SAAS,KAAK;AAChB,aAAO,KAAK,YAAY;AAAA,IAC1B;AACA,QAAI,KAAK,MAAM,YAAY,GAAG;AAC5B,aAAO,KAAK,WAAW;AAAA,IACzB;AACA,QAAI,SAAS,KAAM;AACjB,aAAO,KAAK,kBAAkB;AAAA,IAChC;AACA,QAAI,SAAS,KAAK;AAChB,aAAO,KAAK,aAAa;AAAA,IAC3B;AACA,QAAI,SAAS,KAAK;AAChB,aAAO,KAAK,UAAU;AAAA,IACxB;AACA,QAAI,SAAS,KAAK;AAChB,aAAO,KAAK,mBAAmB;AAAA,IACjC;AACA,UAAM,IAAI,WAAW,KAAK,KAAK,kBAAkB;AAAA,EAEnD;AAAA,EAEQ,kBAA8B;AAEpC,UAAM,aAAa,oBAAI,IAAI;AAC3B,WAAM,CAAC,KAAK,IAAI,GAAG;AACjB,YAAM,OAAO,KAAK,SAAS;AAC3B,UAAI,SAAO,KAAK;AACd;AAAA,MACF;AACA,WAAK;AACL,WAAK,OAAO;AACZ,YAAM,MAAM,KAAK,SAAS;AAC1B,UAAI,QAAkB;AACtB,UAAI,KAAK,SAAS,MAAM,KAAK;AAC3B,aAAK;AACL,gBAAQ,KAAK,cAAc;AAAA,MAC7B;AACA,iBAAW,IAAI,KAAK,KAAK;AAAA,IAC3B;AAEA,WAAO;AAAA,EAET;AAAA,EAEQ,wBAAgC;AAEtC,QAAI,OAA8B;AAClC,QAAI,OAAO;AACX,QAAI,cAAc;AAClB,QAAI,KAAK,SAAS,MAAI,KAAK;AACzB,aAAO;AACP,WAAK;AAAA,IACP;AAOA,QAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,GAAG;AAC7B,YAAM,IAAI,WAAW,KAAK,KAAK,wBAAwB;AAAA,IACzD;AAEA,WAAM,CAAC,KAAK,IAAI,GAAG;AACjB,YAAM,OAAO,KAAK,QAAQ;AAC1B,UAAI,QAAQ,IAAI,GAAG;AACjB,uBAAa;AAAA,MACf,WAAW,SAAS,aAAa,SAAS,KAAK;AAC7C,YAAI,YAAY,SAAO,IAAI;AACzB,gBAAM,IAAI,WAAW,KAAK,KAAK,iCAAiC;AAAA,QAClE;AACA,uBAAa;AACb,eAAO;AAAA,MACT,OAAO;AAEL,aAAK;AACL;AAAA,MACF;AAEA,UAAI,SAAS,aAAa,YAAY,SAAO,IAAI;AAC/C,cAAM,IAAI,WAAW,KAAK,KAAK,iCAAiC;AAAA,MAClE;AACA,UAAI,SAAS,aAAa,YAAY,SAAO,IAAI;AAC/C,cAAM,IAAI,WAAW,KAAK,KAAK,iCAAiC;AAAA,MAClE;AAAA,IACF;AAEA,QAAI,SAAS,WAAW;AACtB,aAAO,SAAS,aAAa,EAAE,IAAI;AAAA,IACrC,OAAO;AACL,UAAI,YAAY,SAAS,GAAG,GAAG;AAC7B,cAAM,IAAI,WAAW,KAAK,KAAK,gCAAgC;AAAA,MACjE;AACA,UAAI,YAAY,MAAM,GAAG,EAAE,CAAC,EAAE,SAAO,GAAG;AACtC,cAAM,IAAI,WAAW,KAAK,KAAK,0DAA0D;AAAA,MAC3F;AACA,aAAO,WAAW,WAAW,IAAI;AAAA,IACnC;AAAA,EAEF;AAAA,EAEQ,cAAsB;AAE5B,QAAI,eAAe;AACnB,SAAK,WAAW,GAAG;AACnB,SAAK;AAEL,WAAM,CAAC,KAAK,IAAI,GAAG;AACjB,YAAM,OAAO,KAAK,QAAQ;AAC1B,UAAI,SAAO,MAAM;AACf,YAAI,KAAK,IAAI,GAAG;AACd,gBAAM,IAAI,WAAW,KAAK,KAAK,yBAAyB;AAAA,QAC1D;AACA,cAAM,WAAW,KAAK,QAAQ;AAC9B,YAAI,aAAW,QAAQ,aAAa,KAAK;AACvC,gBAAM,IAAI,WAAW,KAAK,KAAK,mEAAmE;AAAA,QACpG;AACA,wBAAc;AAAA,MAChB,WAAW,SAAS,KAAK;AACvB,eAAO;AAAA,MACT,WAAW,CAAC,QAAQ,IAAI,GAAG;AACzB,cAAM,IAAI,WAAW,KAAK,KAAK,oCAAoC;AAAA,MACrE,OAAO;AACL,wBAAgB;AAAA,MAClB;AAAA,IAEF;AACA,UAAM,IAAI,WAAW,KAAK,KAAK,yBAAyB;AAAA,EAE1D;AAAA,EAEQ,qBAAoC;AAE1C,UAAM,QAAQ,KAAK,SAAS,CAAC;AAC7B,QAAI,UAAU,MAAM;AAClB,YAAM,IAAI,WAAW,KAAK,KAAK,4DAA4D;AAAA,IAC7F;AAEA,UAAM,SAAkB,CAAC;AAEzB,WAAO,CAAC,KAAK,IAAI,GAAG;AAElB,YAAM,OAAO,KAAK,QAAQ;AAC1B,UAAI,KAAK,WAAW,CAAC,KAAK,MAAS,KAAK,WAAW,CAAC,KAAK,OAAQ,KAAK,WAAW,CAAC,KAAK,KAAO;AAC5F,cAAM,IAAI,WAAW,KAAK,KAAK,gEAAgE;AAAA,MACjG;AAEA,UAAI,SAAO,KAAK;AACd,cAAM,WAAW,KAAK,SAAS,CAAC;AAChC,YAAI,gBAAgB,KAAK,QAAQ,GAAG;AAClC,iBAAO,KAAK,SAAS,UAAU,EAAE,CAAC;AAAA,QACpC,OAAO;AACL,gBAAM,IAAI,WAAW,KAAK,KAAK,kDAAkD,QAAQ,6CAA6C;AAAA,QACxI;AACA;AAAA,MACF;AACA,UAAI,SAAO,KAAK;AACd,cAAM,cAAc,IAAI,YAAY,SAAS;AAAA,UAC3C,OAAO;AAAA,QACT,CAAC;AACD,YAAI;AACF,iBAAO,IAAI;AAAA,YACT,YAAY,OAAO,IAAI,WAAW,MAAM,CAAC;AAAA,UAC3C;AAAA,QACF,QAAQ;AACN,gBAAM,IAAI,WAAW,KAAK,KAAK,uDAAuD;AAAA,QACxF;AAAA,MACF;AACA,aAAO,KAAK,KAAK,WAAW,CAAC,CAAC;AAAA,IAChC;AACA,UAAM,IAAI,WAAW,KAAK,KAAK,yBAAyB;AAAA,EAE1D;AAAA,EAEQ,aAAoB;AAO1B,QAAI,eAAe;AAEnB,WAAM,CAAC,KAAK,IAAI,GAAG;AACjB,YAAM,OAAO,KAAK,SAAS;AAC3B,UAAI,SAAO,UAAa,CAAC,kCAAkC,KAAK,IAAI,GAAG;AACrE,eAAO,IAAI,MAAM,YAAY;AAAA,MAC/B;AACA,sBAAgB,KAAK,QAAQ;AAAA,IAC/B;AAEA,WAAO,IAAI,MAAM,YAAY;AAAA,EAE/B;AAAA,EAEQ,oBAAiC;AAEvC,SAAK,WAAW,GAAG;AACnB,SAAK;AACL,UAAM,SAAS,KAAK,MAAM,QAAQ,KAAK,KAAK,GAAG;AAC/C,QAAI,WAAW,IAAI;AACjB,YAAM,IAAI,WAAW,KAAK,KAAK,qEAAqE;AAAA,IACtG;AACA,UAAM,aAAa,KAAK,MAAM,UAAU,KAAK,KAAK,MAAM;AACxD,SAAK,OAAO,WAAW,SAAO;AAE9B,QAAI,CAAC,oBAAoB,KAAK,UAAU,GAAG;AACzC,YAAM,IAAI,WAAW,KAAK,KAAK,qDAAqD;AAAA,IACtF;AAEA,QAAI;AACF,aAAO,oBAAoB,UAAU;AAAA,IACvC,QAAQ;AACN,YAAM,IAAI,WAAW,KAAK,KAAK,qDAAqD;AAAA,IACtF;AAAA,EAEF;AAAA,EAEQ,eAAwB;AAE9B,SAAK,WAAW,GAAG;AACnB,SAAK;AAEL,UAAM,OAAO,KAAK,QAAQ;AAC1B,QAAI,SAAS,KAAK;AAChB,aAAO;AAAA,IACT;AACA,QAAI,SAAS,KAAK;AAChB,aAAO;AAAA,IACT;AACA,UAAM,IAAI,WAAW,KAAK,KAAK,+CAA+C;AAAA,EAEhF;AAAA,EAEQ,YAAkB;AAExB,SAAK,WAAW,GAAG;AACnB,SAAK;AACL,QAAI,OAAO;AACX,QAAI,cAAc;AAClB,QAAI,KAAK,SAAS,MAAI,KAAK;AACzB,aAAO;AACP,WAAK;AAAA,IACP;AAEA,QAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,GAAG;AAC7B,YAAM,IAAI,WAAW,KAAK,KAAK,wBAAwB;AAAA,IACzD;AAEA,WAAM,CAAC,KAAK,IAAI,GAAG;AACjB,YAAM,OAAO,KAAK,QAAQ;AAC1B,UAAI,QAAQ,IAAI,GAAG;AACjB,uBAAa;AAAA,MACf,OAAO;AACL,cAAM,IAAI,WAAW,KAAK,KAAK,2CAA2C;AAAA,MAC5E;AAAA,IACF;AAEA,WAAO,IAAI,KAAK,SAAS,aAAY,EAAE,IAAE,OAAK,GAAI;AAAA,EAEpD;AAAA,EAEQ,WAAmB;AAEzB,QAAI,CAAC,KAAK,SAAS,GAAG,MAAM,SAAS,GAAG;AACtC,YAAM,IAAI,WAAW,KAAK,KAAK,mDAAmD;AAAA,IACpF;AAEA,QAAI,eAAe;AAEnB,WAAM,CAAC,KAAK,IAAI,GAAG;AACjB,YAAM,OAAO,KAAK,SAAS;AAC3B,UAAI,SAAO,UAAa,CAAC,kBAAkB,KAAK,IAAI,GAAG;AACrD,eAAO;AAAA,MACT;AACA,sBAAgB,KAAK,QAAQ;AAAA,IAC/B;AAEA,WAAO;AAAA,EAET;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,WAA4B;AAElC,WAAO,KAAK,MAAM,KAAK,GAAG;AAAA,EAE5B;AAAA;AAAA;AAAA;AAAA,EAKQ,WAAW,MAAoB;AAErC,QAAI,KAAK,SAAS,MAAI,MAAM;AAC1B,YAAM,IAAI,WAAW,KAAK,KAAK,YAAY,IAAI,EAAE;AAAA,IACnD;AAAA,EAEF;AAAA,EAEQ,UAAkB;AAExB,WAAO,KAAK,MAAM,KAAK,KAAK;AAAA,EAE9B;AAAA,EACQ,SAAS,OAAuB;AAEtC,UAAM,SAAS,KAAK,MAAM;AAAA,MACxB,KAAK;AAAA,MACL;AAAA,IACF;AACA,SAAK,OAAO;AACZ,WAAO;AAAA,EAET;AAAA,EACQ,MAAc;AAEpB,WAAO,KAAK,OAAK,KAAK,MAAM;AAAA,EAE9B;AAAA;AAAA,EAEQ,UAAgB;AAEtB,WAAO,MAAM;AACX,YAAM,IAAI,KAAK,MAAM,OAAO,KAAK,KAAK,CAAC;AACvC,UAAI,MAAM,OAAO,MAAM,KAAM;AAC3B,aAAK;AAAA,MACP,OAAO;AACL;AAAA,MACF;AAAA,IACF;AAAA,EAEF;AAAA;AAAA,EAEQ,SAAe;AAErB,WAAM,KAAK,SAAS,MAAI,KAAK;AAC3B,WAAK;AAAA,IACP;AAAA,EAEF;AAAA;AAAA;AAAA,EAIQ,aAAmB;AAEzB,SAAK,OAAO;AACZ,QAAI,CAAC,KAAK,IAAI,GAAG;AACf,YAAM,IAAI,WAAW,KAAK,KAAK,uCAAuC;AAAA,IACxE;AAAA,EAEF;AAEF;AAEA,IAAM,eAAe;AACrB,SAAS,QAAQ,MAAiC;AAEhD,MAAI,SAAO,OAAW,QAAO;AAC7B,SAAO,aAAa,KAAK,IAAI;AAE/B;","names":[]}