it-split
Version:
Splits Uint8Arrays emitted by an (async) iterable by a delimiter
99 lines • 2.53 kB
JavaScript
/**
* @packageDocumentation
*
* Searches `Uint8Array`s emitted by an (async)iterable for a delimiter and yields chunks split by that delimiter.
*
* @example
*
* ```javascript
* import split from 'it-split'
*
* const encoder = new TextEncoder()
*
* // This can also be an iterator, generator, etc
* const values = [
* encoder.encode('hello\nwor'),
* encoder.encode('ld')
* ]
*
* const arr = all(split(values))
*
* console.info(arr) // [encoder.encode('hello'), encoder.encode('world')]
* ```
*
* You can also split by arbitrary delimiters:
*
* ```javascript
* const values = [
* Uint8Array.from([0, 1, 2, 3]),
* Uint8Array.from([0, 1, 2, 3]),
* Uint8Array.from([1, 1, 2])
* ]
* const delimiter = Uint8Array.from([1, 2])
*
* const arr = all(split(values, {
* delimiter
* }))
*
* console.info(arr) // [ Buffer.from([0]), Buffer.from([3, 0]), Buffer.from([3, 1]) ]
* ```
*
* Async sources must be awaited:
*
* ```javascript
* import split from 'it-split'
*
* const encoder = new TextEncoder()
*
* const values = async function * () {
* yield * [
* encoder.encode('hello\nwor'),
* encoder.encode('ld')
* ]
* }
*
* const arr = await all(split(values()))
*
* console.info(arr) // [encoder.encode('hello'), encoder.encode('world')]
* ```
*/
import { Uint8ArrayList } from 'uint8arraylist';
function isAsyncIterable(thing) {
return thing[Symbol.asyncIterator] != null;
}
function split(source, options = {}) {
const bl = new Uint8ArrayList();
const delimiter = options.delimiter ?? new TextEncoder().encode('\n');
if (isAsyncIterable(source)) {
return (async function* () {
for await (const buf of source) {
bl.append(buf);
yield* yieldUntilEnd(bl, delimiter);
}
yield* yieldUntilEnd(bl, delimiter);
if (bl.length > 0) {
yield bl.slice();
}
})();
}
return (function* () {
for (const buf of source) {
bl.append(buf);
yield* yieldUntilEnd(bl, delimiter);
}
yield* yieldUntilEnd(bl, delimiter);
if (bl.length > 0) {
yield bl.slice();
}
})();
}
function* yieldUntilEnd(bl, delimiter) {
let index = bl.indexOf(delimiter);
while (index !== -1) {
yield bl.slice(0, index);
bl.consume(index + delimiter.length);
index = bl.indexOf(delimiter);
}
}
export default split;
//# sourceMappingURL=index.js.map