@mjackson/multipart-parser
Version:
A fast, efficient parser for multipart streams in any JavaScript environment
68 lines (53 loc) • 1.94 kB
text/typescript
export interface SearchFunction {
(haystack: Uint8Array, start?: number): number;
}
export function createSearch(pattern: string): SearchFunction {
let needle = new TextEncoder().encode(pattern);
let search: SearchFunction;
if ('Buffer' in globalThis && !('Bun' in globalThis || 'Deno' in globalThis)) {
// Use the built-in Buffer.indexOf method on Node.js for better perf.
search = (haystack, start = 0) => Buffer.prototype.indexOf.call(haystack, needle, start);
} else {
let needleEnd = needle.length - 1;
let skipTable = new Uint8Array(256).fill(needle.length);
for (let i = 0; i < needleEnd; ++i) {
skipTable[needle[i]] = needleEnd - i;
}
search = (haystack, start = 0) => {
let haystackLength = haystack.length;
let i = start + needleEnd;
while (i < haystackLength) {
for (let j = needleEnd, k = i; j >= 0 && haystack[k] === needle[j]; --j, --k) {
if (j === 0) return k;
}
i += skipTable[haystack[i]];
}
return -1;
};
}
return search;
}
export interface PartialTailSearchFunction {
(haystack: Uint8Array): number;
}
export function createPartialTailSearch(pattern: string): PartialTailSearchFunction {
let needle = new TextEncoder().encode(pattern);
let byteIndexes: Record<number, number[]> = {};
for (let i = 0; i < needle.length; ++i) {
let byte = needle[i];
if (byteIndexes[byte] === undefined) byteIndexes[byte] = [];
byteIndexes[byte].push(i);
}
return function (haystack: Uint8Array): number {
let haystackEnd = haystack.length - 1;
if (haystack[haystackEnd] in byteIndexes) {
let indexes = byteIndexes[haystack[haystackEnd]];
for (let i = indexes.length - 1; i >= 0; --i) {
for (let j = indexes[i], k = haystackEnd; j >= 0 && haystack[k] === needle[j]; --j, --k) {
if (j === 0) return k;
}
}
}
return -1;
};
}