@yume-chan/stream-extra 0.0.20 → 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +12 -0
- package/CHANGELOG.md +8 -1
- package/esm/buffered-transform.d.ts.map +1 -1
- package/esm/buffered-transform.js.map +1 -1
- package/esm/buffered.d.ts +0 -2
- package/esm/buffered.d.ts.map +1 -1
- package/esm/buffered.js +6 -6
- package/esm/buffered.js.map +1 -1
- package/esm/concat.d.ts +35 -0
- package/esm/concat.d.ts.map +1 -0
- package/esm/concat.js +128 -0
- package/esm/concat.js.map +1 -0
- package/esm/consumable.d.ts.map +1 -1
- package/esm/consumable.js.map +1 -1
- package/esm/distribution.d.ts.map +1 -1
- package/esm/distribution.js.map +1 -1
- package/esm/duplex.d.ts.map +1 -1
- package/esm/duplex.js.map +1 -1
- package/esm/index.d.ts +1 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -1
- package/esm/index.js.map +1 -1
- package/esm/split-string.d.ts.map +1 -1
- package/esm/split-string.js.map +1 -1
- package/esm/stream.js +0 -14
- package/esm/stream.js.map +1 -1
- package/esm/struct-deserialize.d.ts.map +1 -1
- package/esm/struct-deserialize.js.map +1 -1
- package/esm/wrap-readable.d.ts.map +1 -1
- package/esm/wrap-readable.js.map +1 -1
- package/esm/wrap-writable.d.ts.map +1 -1
- package/esm/wrap-writable.js.map +1 -1
- package/package.json +8 -8
- package/src/buffered-transform.ts +4 -4
- package/src/buffered.ts +11 -11
- package/src/concat.ts +160 -0
- package/src/consumable.ts +27 -26
- package/src/decode-utf8.ts +1 -1
- package/src/distribution.ts +5 -5
- package/src/duplex.ts +7 -7
- package/src/index.ts +1 -1
- package/src/pipe-from.ts +1 -1
- package/src/push-readable.ts +5 -5
- package/src/split-string.ts +2 -2
- package/src/stream.ts +0 -13
- package/src/struct-deserialize.ts +2 -2
- package/src/struct-serialize.ts +1 -1
- package/src/wrap-readable.ts +6 -6
- package/src/wrap-writable.ts +5 -5
- package/tsconfig.build.tsbuildinfo +1 -1
- package/esm/gather-string.d.ts +0 -7
- package/esm/gather-string.d.ts.map +0 -1
- package/esm/gather-string.js +0 -16
- package/esm/gather-string.js.map +0 -1
- package/src/gather-string.ts +0 -17
package/src/buffered.ts
CHANGED
|
@@ -14,19 +14,19 @@ export class BufferedReadableStream implements AsyncExactReadable {
|
|
|
14
14
|
#bufferedLength = 0;
|
|
15
15
|
|
|
16
16
|
#position = 0;
|
|
17
|
-
|
|
17
|
+
get position() {
|
|
18
18
|
return this.#position;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
protected readonly stream: ReadableStream<Uint8Array>;
|
|
22
22
|
protected readonly reader: ReadableStreamDefaultReader<Uint8Array>;
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
constructor(stream: ReadableStream<Uint8Array>) {
|
|
25
25
|
this.stream = stream;
|
|
26
26
|
this.reader = stream.getReader();
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
async #readSource() {
|
|
30
30
|
const { done, value } = await this.reader.read();
|
|
31
31
|
if (done) {
|
|
32
32
|
throw new ExactReadableEndedError();
|
|
@@ -35,7 +35,7 @@ export class BufferedReadableStream implements AsyncExactReadable {
|
|
|
35
35
|
return value;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
async #readAsync(length: number, initial?: Uint8Array) {
|
|
39
39
|
let result: Uint8Array;
|
|
40
40
|
let index: number;
|
|
41
41
|
|
|
@@ -45,7 +45,7 @@ export class BufferedReadableStream implements AsyncExactReadable {
|
|
|
45
45
|
index = initial.byteLength;
|
|
46
46
|
length -= initial.byteLength;
|
|
47
47
|
} else {
|
|
48
|
-
const array = await this
|
|
48
|
+
const array = await this.#readSource();
|
|
49
49
|
if (array.byteLength === length) {
|
|
50
50
|
return array;
|
|
51
51
|
}
|
|
@@ -64,7 +64,7 @@ export class BufferedReadableStream implements AsyncExactReadable {
|
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
while (length > 0) {
|
|
67
|
-
const array = await this
|
|
67
|
+
const array = await this.#readSource();
|
|
68
68
|
if (array.byteLength === length) {
|
|
69
69
|
result.set(array, index);
|
|
70
70
|
return result;
|
|
@@ -91,7 +91,7 @@ export class BufferedReadableStream implements AsyncExactReadable {
|
|
|
91
91
|
* @param length
|
|
92
92
|
* @returns
|
|
93
93
|
*/
|
|
94
|
-
|
|
94
|
+
readExactly(length: number): Uint8Array | Promise<Uint8Array> {
|
|
95
95
|
// PERF: Add a synchronous path for reading from internal buffer
|
|
96
96
|
if (this.#buffered) {
|
|
97
97
|
const array = this.#buffered;
|
|
@@ -107,10 +107,10 @@ export class BufferedReadableStream implements AsyncExactReadable {
|
|
|
107
107
|
this.#buffered = undefined;
|
|
108
108
|
this.#bufferedLength = 0;
|
|
109
109
|
this.#bufferedOffset = 0;
|
|
110
|
-
return this
|
|
110
|
+
return this.#readAsync(length, array.subarray(offset));
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
return this
|
|
113
|
+
return this.#readAsync(length);
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
/**
|
|
@@ -118,7 +118,7 @@ export class BufferedReadableStream implements AsyncExactReadable {
|
|
|
118
118
|
* all data from the wrapped stream.
|
|
119
119
|
* @returns A `ReadableStream`
|
|
120
120
|
*/
|
|
121
|
-
|
|
121
|
+
release(): ReadableStream<Uint8Array> {
|
|
122
122
|
if (this.#bufferedLength > 0) {
|
|
123
123
|
return new PushReadableStream<Uint8Array>(async (controller) => {
|
|
124
124
|
// Put the remaining data back to the stream
|
|
@@ -147,7 +147,7 @@ export class BufferedReadableStream implements AsyncExactReadable {
|
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
-
|
|
150
|
+
cancel(reason?: unknown) {
|
|
151
151
|
return this.reader.cancel(reason);
|
|
152
152
|
}
|
|
153
153
|
}
|
package/src/concat.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
+
|
|
3
|
+
import type { ReadableStreamDefaultController } from "./stream.js";
|
|
4
|
+
import { ReadableStream, WritableStream } from "./stream.js";
|
|
5
|
+
|
|
6
|
+
export interface ConcatStringReadableStream
|
|
7
|
+
extends ReadableStream<string>,
|
|
8
|
+
Promise<string> {}
|
|
9
|
+
|
|
10
|
+
// `TransformStream` only calls its `source.flush` method when its `readable` is being read.
|
|
11
|
+
// If the user want to use the `Promise` interface, the `flush` method will never be called,
|
|
12
|
+
// so the `PromiseResolver` will never be resolved.
|
|
13
|
+
// Thus we need to implement our own `TransformStream` using a `WritableStream` and a `ReadableStream`.
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* A `TransformStream` that concatenates strings.
|
|
17
|
+
*
|
|
18
|
+
* Its `readable` is also a `Promise<string>`, so it's possible to `await` it to get the result.
|
|
19
|
+
*
|
|
20
|
+
* ```ts
|
|
21
|
+
* const result: string = await readable.pipeThrough(new ConcatStringStream());
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export class ConcatStringStream {
|
|
25
|
+
// PERF: rope (concat strings) is faster than `[].join('')`
|
|
26
|
+
#result = "";
|
|
27
|
+
|
|
28
|
+
#resolver = new PromiseResolver<string>();
|
|
29
|
+
|
|
30
|
+
#writable = new WritableStream<string>({
|
|
31
|
+
write: (chunk) => {
|
|
32
|
+
this.#result += chunk;
|
|
33
|
+
},
|
|
34
|
+
close: () => {
|
|
35
|
+
this.#resolver.resolve(this.#result);
|
|
36
|
+
this.#readableController.enqueue(this.#result);
|
|
37
|
+
this.#readableController.close();
|
|
38
|
+
},
|
|
39
|
+
abort: (reason) => {
|
|
40
|
+
this.#resolver.reject(reason);
|
|
41
|
+
this.#readableController.error(reason);
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
get writable(): WritableStream<string> {
|
|
45
|
+
return this.#writable;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
#readableController!: ReadableStreamDefaultController<string>;
|
|
49
|
+
#readable = new ReadableStream<string>({
|
|
50
|
+
start: (controller) => {
|
|
51
|
+
this.#readableController = controller;
|
|
52
|
+
},
|
|
53
|
+
}) as ConcatStringReadableStream;
|
|
54
|
+
get readable(): ConcatStringReadableStream {
|
|
55
|
+
return this.#readable;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
constructor() {
|
|
59
|
+
void Object.defineProperties(this.#readable, {
|
|
60
|
+
then: {
|
|
61
|
+
get: () =>
|
|
62
|
+
this.#resolver.promise.then.bind(this.#resolver.promise),
|
|
63
|
+
},
|
|
64
|
+
catch: {
|
|
65
|
+
get: () =>
|
|
66
|
+
this.#resolver.promise.catch.bind(this.#resolver.promise),
|
|
67
|
+
},
|
|
68
|
+
finally: {
|
|
69
|
+
get: () =>
|
|
70
|
+
this.#resolver.promise.finally.bind(this.#resolver.promise),
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface ConcatBufferReadableStream
|
|
77
|
+
extends ReadableStream<Uint8Array>,
|
|
78
|
+
Promise<Uint8Array> {}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* A `TransformStream` that concatenates `Uint8Array`s.
|
|
82
|
+
*
|
|
83
|
+
* If you want to decode the result as string,
|
|
84
|
+
* prefer `.pipeThrough(new DecodeUtf8Stream()).pipeThrough(new ConcatStringStream())`,
|
|
85
|
+
* than `.pipeThough(new ConcatBufferStream()).pipeThrough(new DecodeUtf8Stream())`,
|
|
86
|
+
* because concatenating strings is faster than concatenating `Uint8Array`s.
|
|
87
|
+
*/
|
|
88
|
+
export class ConcatBufferStream {
|
|
89
|
+
#segments: Uint8Array[] = [];
|
|
90
|
+
|
|
91
|
+
#resolver = new PromiseResolver<Uint8Array>();
|
|
92
|
+
|
|
93
|
+
#writable = new WritableStream<Uint8Array>({
|
|
94
|
+
write: (chunk) => {
|
|
95
|
+
this.#segments.push(chunk);
|
|
96
|
+
},
|
|
97
|
+
close: () => {
|
|
98
|
+
let result: Uint8Array;
|
|
99
|
+
let offset = 0;
|
|
100
|
+
switch (this.#segments.length) {
|
|
101
|
+
case 0:
|
|
102
|
+
result = new Uint8Array(0);
|
|
103
|
+
break;
|
|
104
|
+
case 1:
|
|
105
|
+
result = this.#segments[0]!;
|
|
106
|
+
break;
|
|
107
|
+
default:
|
|
108
|
+
result = new Uint8Array(
|
|
109
|
+
this.#segments.reduce(
|
|
110
|
+
(prev, item) => prev + item.length,
|
|
111
|
+
0,
|
|
112
|
+
),
|
|
113
|
+
);
|
|
114
|
+
for (const segment of this.#segments) {
|
|
115
|
+
result.set(segment, offset);
|
|
116
|
+
offset += segment.length;
|
|
117
|
+
}
|
|
118
|
+
break;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
this.#resolver.resolve(result);
|
|
122
|
+
this.#readableController.enqueue(result);
|
|
123
|
+
this.#readableController.close();
|
|
124
|
+
},
|
|
125
|
+
abort: (reason) => {
|
|
126
|
+
this.#resolver.reject(reason);
|
|
127
|
+
this.#readableController.error(reason);
|
|
128
|
+
},
|
|
129
|
+
});
|
|
130
|
+
get writable(): WritableStream<Uint8Array> {
|
|
131
|
+
return this.#writable;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
#readableController!: ReadableStreamDefaultController<Uint8Array>;
|
|
135
|
+
#readable = new ReadableStream<Uint8Array>({
|
|
136
|
+
start: (controller) => {
|
|
137
|
+
this.#readableController = controller;
|
|
138
|
+
},
|
|
139
|
+
}) as ConcatBufferReadableStream;
|
|
140
|
+
get readable(): ConcatBufferReadableStream {
|
|
141
|
+
return this.#readable;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
constructor() {
|
|
145
|
+
void Object.defineProperties(this.#readable, {
|
|
146
|
+
then: {
|
|
147
|
+
get: () =>
|
|
148
|
+
this.#resolver.promise.then.bind(this.#resolver.promise),
|
|
149
|
+
},
|
|
150
|
+
catch: {
|
|
151
|
+
get: () =>
|
|
152
|
+
this.#resolver.promise.catch.bind(this.#resolver.promise),
|
|
153
|
+
},
|
|
154
|
+
finally: {
|
|
155
|
+
get: () =>
|
|
156
|
+
this.#resolver.promise.finally.bind(this.#resolver.promise),
|
|
157
|
+
},
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
package/src/consumable.ts
CHANGED
|
@@ -29,25 +29,25 @@ export class Consumable<T> {
|
|
|
29
29
|
readonly #task: Task;
|
|
30
30
|
readonly #resolver: PromiseResolver<void>;
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
readonly value: T;
|
|
33
|
+
readonly consumed: Promise<void>;
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
constructor(value: T) {
|
|
36
36
|
this.#task = createTask("Consumable");
|
|
37
37
|
this.value = value;
|
|
38
38
|
this.#resolver = new PromiseResolver<void>();
|
|
39
39
|
this.consumed = this.#resolver.promise;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
consume() {
|
|
43
43
|
this.#resolver.resolve();
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
error(error: any) {
|
|
47
47
|
this.#resolver.reject(error);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
async tryConsume<U>(callback: (value: T) => U) {
|
|
51
51
|
try {
|
|
52
52
|
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
53
53
|
const result = await this.#task.run(() => callback(this.value));
|
|
@@ -62,7 +62,7 @@ export class Consumable<T> {
|
|
|
62
62
|
|
|
63
63
|
async function enqueue<T>(
|
|
64
64
|
controller: { enqueue: (chunk: Consumable<T>) => void },
|
|
65
|
-
chunk: T
|
|
65
|
+
chunk: T,
|
|
66
66
|
) {
|
|
67
67
|
const output = new Consumable(chunk);
|
|
68
68
|
controller.enqueue(output);
|
|
@@ -70,7 +70,7 @@ async function enqueue<T>(
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
export class WrapConsumableStream<T> extends TransformStream<T, Consumable<T>> {
|
|
73
|
-
|
|
73
|
+
constructor() {
|
|
74
74
|
super({
|
|
75
75
|
async transform(chunk, controller) {
|
|
76
76
|
await enqueue(controller, chunk);
|
|
@@ -83,7 +83,7 @@ export class UnwrapConsumableStream<T> extends TransformStream<
|
|
|
83
83
|
Consumable<T>,
|
|
84
84
|
T
|
|
85
85
|
> {
|
|
86
|
-
|
|
86
|
+
constructor() {
|
|
87
87
|
super({
|
|
88
88
|
transform(chunk, controller) {
|
|
89
89
|
controller.enqueue(chunk.value);
|
|
@@ -101,18 +101,18 @@ export interface ConsumableReadableStreamController<T> {
|
|
|
101
101
|
|
|
102
102
|
export interface ConsumableReadableStreamSource<T> {
|
|
103
103
|
start?(
|
|
104
|
-
controller: ConsumableReadableStreamController<T
|
|
104
|
+
controller: ConsumableReadableStreamController<T>,
|
|
105
105
|
): void | PromiseLike<void>;
|
|
106
106
|
pull?(
|
|
107
|
-
controller: ConsumableReadableStreamController<T
|
|
107
|
+
controller: ConsumableReadableStreamController<T>,
|
|
108
108
|
): void | PromiseLike<void>;
|
|
109
109
|
cancel?(reason: any): void | PromiseLike<void>;
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
export class ConsumableReadableStream<T> extends ReadableStream<Consumable<T>> {
|
|
113
|
-
|
|
113
|
+
constructor(
|
|
114
114
|
source: ConsumableReadableStreamSource<T>,
|
|
115
|
-
strategy?: QueuingStrategy<T
|
|
115
|
+
strategy?: QueuingStrategy<T>,
|
|
116
116
|
) {
|
|
117
117
|
let wrappedController:
|
|
118
118
|
| ConsumableReadableStreamController<T>
|
|
@@ -155,7 +155,7 @@ export class ConsumableReadableStream<T> extends ReadableStream<Consumable<T>> {
|
|
|
155
155
|
await source.cancel?.(reason);
|
|
156
156
|
},
|
|
157
157
|
},
|
|
158
|
-
wrappedStrategy
|
|
158
|
+
wrappedStrategy,
|
|
159
159
|
);
|
|
160
160
|
}
|
|
161
161
|
}
|
|
@@ -168,18 +168,18 @@ export interface ConsumableWritableStreamSink<T> {
|
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
export class ConsumableWritableStream<T> extends WritableStream<Consumable<T>> {
|
|
171
|
-
|
|
171
|
+
static async write<T>(
|
|
172
172
|
writer: WritableStreamDefaultWriter<Consumable<T>>,
|
|
173
|
-
value: T
|
|
173
|
+
value: T,
|
|
174
174
|
) {
|
|
175
175
|
const consumable = new Consumable(value);
|
|
176
176
|
await writer.write(consumable);
|
|
177
177
|
await consumable.consumed;
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
|
|
180
|
+
constructor(
|
|
181
181
|
sink: ConsumableWritableStreamSink<T>,
|
|
182
|
-
strategy?: QueuingStrategy<T
|
|
182
|
+
strategy?: QueuingStrategy<T>,
|
|
183
183
|
) {
|
|
184
184
|
let wrappedStrategy: QueuingStrategy<Consumable<T>> | undefined;
|
|
185
185
|
if (strategy) {
|
|
@@ -210,21 +210,21 @@ export class ConsumableWritableStream<T> extends WritableStream<Consumable<T>> {
|
|
|
210
210
|
return sink.close?.();
|
|
211
211
|
},
|
|
212
212
|
},
|
|
213
|
-
wrappedStrategy
|
|
213
|
+
wrappedStrategy,
|
|
214
214
|
);
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
217
|
|
|
218
218
|
export interface ConsumableTransformer<I, O> {
|
|
219
219
|
start?(
|
|
220
|
-
controller: ConsumableReadableStreamController<O
|
|
220
|
+
controller: ConsumableReadableStreamController<O>,
|
|
221
221
|
): void | PromiseLike<void>;
|
|
222
222
|
transform?(
|
|
223
223
|
chunk: I,
|
|
224
|
-
controller: ConsumableReadableStreamController<O
|
|
224
|
+
controller: ConsumableReadableStreamController<O>,
|
|
225
225
|
): void | PromiseLike<void>;
|
|
226
226
|
flush?(
|
|
227
|
-
controller: ConsumableReadableStreamController<O
|
|
227
|
+
controller: ConsumableReadableStreamController<O>,
|
|
228
228
|
): void | PromiseLike<void>;
|
|
229
229
|
}
|
|
230
230
|
|
|
@@ -232,7 +232,7 @@ export class ConsumableTransformStream<I, O> extends TransformStream<
|
|
|
232
232
|
Consumable<I>,
|
|
233
233
|
Consumable<O>
|
|
234
234
|
> {
|
|
235
|
-
|
|
235
|
+
constructor(transformer: ConsumableTransformer<I, O>) {
|
|
236
236
|
let wrappedController:
|
|
237
237
|
| ConsumableReadableStreamController<O>
|
|
238
238
|
| undefined;
|
|
@@ -254,8 +254,9 @@ export class ConsumableTransformStream<I, O> extends TransformStream<
|
|
|
254
254
|
await transformer.start?.(wrappedController);
|
|
255
255
|
},
|
|
256
256
|
async transform(chunk) {
|
|
257
|
-
await chunk.tryConsume(
|
|
258
|
-
|
|
257
|
+
await chunk.tryConsume(
|
|
258
|
+
(value) =>
|
|
259
|
+
transformer.transform?.(value, wrappedController!),
|
|
259
260
|
);
|
|
260
261
|
chunk.consume();
|
|
261
262
|
},
|
|
@@ -270,7 +271,7 @@ export class ConsumableInspectStream<T> extends TransformStream<
|
|
|
270
271
|
Consumable<T>,
|
|
271
272
|
Consumable<T>
|
|
272
273
|
> {
|
|
273
|
-
|
|
274
|
+
constructor(callback: (value: T) => void) {
|
|
274
275
|
super({
|
|
275
276
|
transform(chunk, controller) {
|
|
276
277
|
callback(chunk.value);
|
package/src/decode-utf8.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { decodeUtf8 } from "@yume-chan/struct";
|
|
|
3
3
|
import { TransformStream } from "./stream.js";
|
|
4
4
|
|
|
5
5
|
export class DecodeUtf8Stream extends TransformStream<Uint8Array, string> {
|
|
6
|
-
|
|
6
|
+
constructor() {
|
|
7
7
|
super({
|
|
8
8
|
transform(chunk, controller) {
|
|
9
9
|
controller.enqueue(decodeUtf8(chunk));
|
package/src/distribution.ts
CHANGED
|
@@ -9,7 +9,7 @@ export class BufferCombiner {
|
|
|
9
9
|
#offset: number;
|
|
10
10
|
#available: number;
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
constructor(size: number) {
|
|
13
13
|
this.#capacity = size;
|
|
14
14
|
this.#buffer = new Uint8Array(size);
|
|
15
15
|
this.#offset = 0;
|
|
@@ -23,7 +23,7 @@ export class BufferCombiner {
|
|
|
23
23
|
* A generator that yields buffers of specified size.
|
|
24
24
|
* It may yield the same buffer multiple times, consume the data before calling `next`.
|
|
25
25
|
*/
|
|
26
|
-
|
|
26
|
+
*push(data: Uint8Array): Generator<Uint8Array, void, void> {
|
|
27
27
|
let offset = 0;
|
|
28
28
|
let available = data.byteLength;
|
|
29
29
|
|
|
@@ -31,7 +31,7 @@ export class BufferCombiner {
|
|
|
31
31
|
if (available >= this.#available) {
|
|
32
32
|
this.#buffer.set(
|
|
33
33
|
data.subarray(0, this.#available),
|
|
34
|
-
this.#offset
|
|
34
|
+
this.#offset,
|
|
35
35
|
);
|
|
36
36
|
offset += this.#available;
|
|
37
37
|
available -= this.#available;
|
|
@@ -65,7 +65,7 @@ export class BufferCombiner {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
flush(): Uint8Array | undefined {
|
|
69
69
|
if (this.#offset === 0) {
|
|
70
70
|
return undefined;
|
|
71
71
|
}
|
|
@@ -81,7 +81,7 @@ export class DistributionStream extends ConsumableTransformStream<
|
|
|
81
81
|
Uint8Array,
|
|
82
82
|
Uint8Array
|
|
83
83
|
> {
|
|
84
|
-
|
|
84
|
+
constructor(size: number, combine = false) {
|
|
85
85
|
const combiner = combine ? new BufferCombiner(size) : undefined;
|
|
86
86
|
super({
|
|
87
87
|
async transform(chunk, controller) {
|
package/src/duplex.ts
CHANGED
|
@@ -50,22 +50,22 @@ export class DuplexStreamFactory<R, W> {
|
|
|
50
50
|
#writers: WritableStreamDefaultWriter<W>[] = [];
|
|
51
51
|
|
|
52
52
|
#writableClosed = false;
|
|
53
|
-
|
|
53
|
+
get writableClosed() {
|
|
54
54
|
return this.#writableClosed;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
#closed = new PromiseResolver<void>();
|
|
58
|
-
|
|
58
|
+
get closed() {
|
|
59
59
|
return this.#closed.promise;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
readonly #options: DuplexStreamFactoryOptions;
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
constructor(options?: DuplexStreamFactoryOptions) {
|
|
65
65
|
this.#options = options ?? {};
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
wrapReadable(readable: ReadableStream<R>): WrapReadableStream<R> {
|
|
69
69
|
return new WrapReadableStream<R>({
|
|
70
70
|
start: (controller) => {
|
|
71
71
|
this.#readableControllers.push(controller);
|
|
@@ -82,7 +82,7 @@ export class DuplexStreamFactory<R, W> {
|
|
|
82
82
|
});
|
|
83
83
|
}
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
createWritable(stream: WritableStream<W>): WritableStream<W> {
|
|
86
86
|
const writer = stream.getWriter();
|
|
87
87
|
this.#writers.push(writer);
|
|
88
88
|
|
|
@@ -104,7 +104,7 @@ export class DuplexStreamFactory<R, W> {
|
|
|
104
104
|
});
|
|
105
105
|
}
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
async close() {
|
|
108
108
|
if (this.#writableClosed) {
|
|
109
109
|
return;
|
|
110
110
|
}
|
|
@@ -122,7 +122,7 @@ export class DuplexStreamFactory<R, W> {
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
|
|
125
|
+
async dispose() {
|
|
126
126
|
this.#writableClosed = true;
|
|
127
127
|
this.#closed.resolve();
|
|
128
128
|
|
package/src/index.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export * from "./buffered-transform.js";
|
|
2
2
|
export * from "./buffered.js";
|
|
3
|
+
export * from "./concat.js";
|
|
3
4
|
export * from "./consumable.js";
|
|
4
5
|
export * from "./decode-utf8.js";
|
|
5
6
|
export * from "./distribution.js";
|
|
6
7
|
export * from "./duplex.js";
|
|
7
|
-
export * from "./gather-string.js";
|
|
8
8
|
export * from "./inspect.js";
|
|
9
9
|
export * from "./pipe-from.js";
|
|
10
10
|
export * from "./push-readable.js";
|
package/src/pipe-from.ts
CHANGED
|
@@ -12,7 +12,7 @@ import { WritableStream } from "./stream.js";
|
|
|
12
12
|
*/
|
|
13
13
|
export function pipeFrom<W, T>(
|
|
14
14
|
writable: WritableStream<W>,
|
|
15
|
-
pair: ReadableWritablePair<W, T
|
|
15
|
+
pair: ReadableWritablePair<W, T>,
|
|
16
16
|
) {
|
|
17
17
|
const writer = pair.writable.getWriter();
|
|
18
18
|
const pipe = pair.readable.pipeTo(writable);
|
package/src/push-readable.ts
CHANGED
|
@@ -14,7 +14,7 @@ export interface PushReadableStreamController<T> {
|
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export type PushReadableStreamSource<T> = (
|
|
17
|
-
controller: PushReadableStreamController<T
|
|
17
|
+
controller: PushReadableStreamController<T>,
|
|
18
18
|
) => void | Promise<void>;
|
|
19
19
|
|
|
20
20
|
export class PushReadableStream<T> extends ReadableStream<T> {
|
|
@@ -25,9 +25,9 @@ export class PushReadableStream<T> extends ReadableStream<T> {
|
|
|
25
25
|
* when the `Promise` is resolved, and be errored when the `Promise` is rejected.
|
|
26
26
|
* @param strategy
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
constructor(
|
|
29
29
|
source: PushReadableStreamSource<T>,
|
|
30
|
-
strategy?: QueuingStrategy<T
|
|
30
|
+
strategy?: QueuingStrategy<T>,
|
|
31
31
|
) {
|
|
32
32
|
let waterMarkLow: PromiseResolver<void> | undefined;
|
|
33
33
|
const abortController = new AbortController();
|
|
@@ -79,7 +79,7 @@ export class PushReadableStream<T> extends ReadableStream<T> {
|
|
|
79
79
|
},
|
|
80
80
|
(e) => {
|
|
81
81
|
controller.error(e);
|
|
82
|
-
}
|
|
82
|
+
},
|
|
83
83
|
);
|
|
84
84
|
}
|
|
85
85
|
},
|
|
@@ -91,7 +91,7 @@ export class PushReadableStream<T> extends ReadableStream<T> {
|
|
|
91
91
|
waterMarkLow?.reject(reason);
|
|
92
92
|
},
|
|
93
93
|
},
|
|
94
|
-
strategy
|
|
94
|
+
strategy,
|
|
95
95
|
);
|
|
96
96
|
}
|
|
97
97
|
}
|
package/src/split-string.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { TransformStream } from "./stream.js";
|
|
|
2
2
|
|
|
3
3
|
function* split(
|
|
4
4
|
input: string,
|
|
5
|
-
separator: string
|
|
5
|
+
separator: string,
|
|
6
6
|
): Generator<string, void, void> {
|
|
7
7
|
let start = 0;
|
|
8
8
|
|
|
@@ -20,7 +20,7 @@ function* split(
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export class SplitStringStream extends TransformStream<string, string> {
|
|
23
|
-
|
|
23
|
+
constructor(separator: string) {
|
|
24
24
|
super({
|
|
25
25
|
transform(chunk, controller) {
|
|
26
26
|
for (const part of split(chunk, separator)) {
|
package/src/stream.ts
CHANGED
|
@@ -45,20 +45,7 @@ export type TransformStream<I = any, O = any> = TransformStreamPolyfill<I, O>;
|
|
|
45
45
|
export let TransformStream = TransformStreamPolyfill;
|
|
46
46
|
|
|
47
47
|
if (GLOBAL.ReadableStream && GLOBAL.WritableStream && GLOBAL.TransformStream) {
|
|
48
|
-
// Use browser native implementation
|
|
49
48
|
ReadableStream = GLOBAL.ReadableStream;
|
|
50
49
|
WritableStream = GLOBAL.WritableStream;
|
|
51
50
|
TransformStream = GLOBAL.TransformStream;
|
|
52
|
-
} else {
|
|
53
|
-
// TODO: enable loading Node.js stream implementation when bundler supports Top Level Await
|
|
54
|
-
// try {
|
|
55
|
-
// // Use Node.js native implementation
|
|
56
|
-
// const MODULE_NAME = "node:stream/web";
|
|
57
|
-
// const StreamWeb = (await import(MODULE_NAME)) as GlobalExtension;
|
|
58
|
-
// ReadableStream = StreamWeb.ReadableStream;
|
|
59
|
-
// WritableStream = StreamWeb.WritableStream;
|
|
60
|
-
// TransformStream = StreamWeb.TransformStream;
|
|
61
|
-
// } catch {
|
|
62
|
-
// // ignore
|
|
63
|
-
// }
|
|
64
51
|
}
|
|
@@ -4,9 +4,9 @@ import type { StructValueType } from "@yume-chan/struct";
|
|
|
4
4
|
import { BufferedTransformStream } from "./buffered-transform.js";
|
|
5
5
|
|
|
6
6
|
export class StructDeserializeStream<
|
|
7
|
-
T extends Struct<any, any, any, any
|
|
7
|
+
T extends Struct<any, any, any, any>,
|
|
8
8
|
> extends BufferedTransformStream<StructValueType<T>> {
|
|
9
|
-
|
|
9
|
+
constructor(struct: T) {
|
|
10
10
|
super((stream) => {
|
|
11
11
|
return struct.deserialize(stream);
|
|
12
12
|
});
|
package/src/struct-serialize.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type Struct from "@yume-chan/struct";
|
|
|
3
3
|
import { TransformStream } from "./stream.js";
|
|
4
4
|
|
|
5
5
|
export class StructSerializeStream<
|
|
6
|
-
T extends Struct<any, any, any, any
|
|
6
|
+
T extends Struct<any, any, any, any>,
|
|
7
7
|
> extends TransformStream<T["TInit"], Uint8Array> {
|
|
8
8
|
constructor(struct: T) {
|
|
9
9
|
super({
|