@yume-chan/stream-extra 0.0.18 → 0.0.20
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 +27 -0
- package/CHANGELOG.md +16 -1
- package/README.md +1 -1
- package/esm/buffered-transform.d.ts +10 -10
- package/esm/buffered-transform.d.ts.map +1 -1
- package/esm/buffered-transform.js +56 -55
- package/esm/buffered-transform.js.map +1 -1
- package/esm/buffered.d.ts +24 -27
- package/esm/buffered.d.ts.map +1 -1
- package/esm/buffered.js +132 -123
- package/esm/buffered.js.map +1 -1
- package/esm/consumable.d.ts +52 -0
- package/esm/consumable.d.ts.map +1 -0
- package/esm/consumable.js +178 -0
- package/esm/consumable.js.map +1 -0
- package/esm/decode-utf8.d.ts +4 -4
- package/esm/decode-utf8.js +11 -11
- package/esm/distribution.d.ts +21 -0
- package/esm/distribution.d.ts.map +1 -0
- package/esm/distribution.js +99 -0
- package/esm/distribution.js.map +1 -0
- package/esm/duplex.d.ts +44 -47
- package/esm/duplex.d.ts.map +1 -1
- package/esm/duplex.js +92 -92
- package/esm/duplex.js.map +1 -1
- package/esm/gather-string.d.ts +6 -6
- package/esm/gather-string.d.ts.map +1 -1
- package/esm/gather-string.js +15 -13
- package/esm/gather-string.js.map +1 -1
- package/esm/index.d.ts +16 -15
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +16 -15
- package/esm/index.js.map +1 -1
- package/esm/inspect.d.ts +4 -4
- package/esm/inspect.js +11 -11
- package/esm/pipe-from.d.ts +12 -11
- package/esm/pipe-from.d.ts.map +1 -1
- package/esm/pipe-from.js +23 -25
- package/esm/pipe-from.js.map +1 -1
- package/esm/push-readable.d.ts +19 -18
- package/esm/push-readable.d.ts.map +1 -1
- package/esm/push-readable.js +66 -61
- package/esm/push-readable.js.map +1 -1
- package/esm/split-string.d.ts +4 -4
- package/esm/split-string.d.ts.map +1 -1
- package/esm/split-string.js +24 -24
- package/esm/split-string.js.map +1 -1
- package/esm/stream.d.ts +25 -24
- package/esm/stream.d.ts.map +1 -1
- package/esm/stream.js +26 -26
- package/esm/stream.js.map +1 -1
- package/esm/struct-deserialize.d.ts +6 -6
- package/esm/struct-deserialize.d.ts.map +1 -1
- package/esm/struct-deserialize.js +8 -8
- package/esm/struct-serialize.d.ts +5 -5
- package/esm/struct-serialize.js +10 -10
- package/esm/wrap-readable.d.ts +21 -20
- package/esm/wrap-readable.d.ts.map +1 -1
- package/esm/wrap-readable.js +56 -56
- package/esm/wrap-readable.js.map +1 -1
- package/esm/wrap-writable.d.ts +14 -12
- package/esm/wrap-writable.d.ts.map +1 -1
- package/esm/wrap-writable.js +62 -52
- package/esm/wrap-writable.js.map +1 -1
- package/package.json +9 -8
- package/src/buffered-transform.ts +15 -22
- package/src/buffered.ts +41 -33
- package/src/consumable.ts +281 -0
- package/src/distribution.ts +113 -0
- package/src/duplex.ts +35 -34
- package/src/gather-string.ts +6 -4
- package/src/index.ts +16 -15
- package/src/inspect.ts +1 -1
- package/src/pipe-from.ts +8 -6
- package/src/push-readable.ts +12 -12
- package/src/split-string.ts +5 -2
- package/src/stream.ts +1 -1
- package/src/struct-deserialize.ts +1 -1
- package/src/wrap-readable.ts +9 -9
- package/src/wrap-writable.ts +21 -9
- package/tsconfig.build.json +6 -1
- package/tsconfig.build.tsbuildinfo +1 -1
- package/esm/chunk.d.ts +0 -5
- package/esm/chunk.d.ts.map +0 -1
- package/esm/chunk.js +0 -15
- package/esm/chunk.js.map +0 -1
- package/esm/trace.d.ts +0 -16
- package/esm/trace.d.ts.map +0 -1
- package/esm/trace.js +0 -131
- package/esm/trace.js.map +0 -1
- package/src/chunk.ts +0 -15
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
+
import { ReadableStream, TransformStream, WritableStream } from "./stream.js";
|
|
3
|
+
// `createTask` allows browser DevTools to track the call stack across async boundaries.
|
|
4
|
+
const { console } = globalThis;
|
|
5
|
+
const createTask = console.createTask?.bind(console) ??
|
|
6
|
+
(() => ({
|
|
7
|
+
run(callback) {
|
|
8
|
+
return callback();
|
|
9
|
+
},
|
|
10
|
+
}));
|
|
11
|
+
export class Consumable {
|
|
12
|
+
#task;
|
|
13
|
+
#resolver;
|
|
14
|
+
value;
|
|
15
|
+
consumed;
|
|
16
|
+
constructor(value) {
|
|
17
|
+
this.#task = createTask("Consumable");
|
|
18
|
+
this.value = value;
|
|
19
|
+
this.#resolver = new PromiseResolver();
|
|
20
|
+
this.consumed = this.#resolver.promise;
|
|
21
|
+
}
|
|
22
|
+
consume() {
|
|
23
|
+
this.#resolver.resolve();
|
|
24
|
+
}
|
|
25
|
+
error(error) {
|
|
26
|
+
this.#resolver.reject(error);
|
|
27
|
+
}
|
|
28
|
+
async tryConsume(callback) {
|
|
29
|
+
try {
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/await-thenable
|
|
31
|
+
const result = await this.#task.run(() => callback(this.value));
|
|
32
|
+
this.consume();
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
this.#resolver.reject(e);
|
|
37
|
+
throw e;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function enqueue(controller, chunk) {
|
|
42
|
+
const output = new Consumable(chunk);
|
|
43
|
+
controller.enqueue(output);
|
|
44
|
+
await output.consumed;
|
|
45
|
+
}
|
|
46
|
+
export class WrapConsumableStream extends TransformStream {
|
|
47
|
+
constructor() {
|
|
48
|
+
super({
|
|
49
|
+
async transform(chunk, controller) {
|
|
50
|
+
await enqueue(controller, chunk);
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export class UnwrapConsumableStream extends TransformStream {
|
|
56
|
+
constructor() {
|
|
57
|
+
super({
|
|
58
|
+
transform(chunk, controller) {
|
|
59
|
+
controller.enqueue(chunk.value);
|
|
60
|
+
chunk.consume();
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export class ConsumableReadableStream extends ReadableStream {
|
|
66
|
+
constructor(source, strategy) {
|
|
67
|
+
let wrappedController;
|
|
68
|
+
let wrappedStrategy;
|
|
69
|
+
if (strategy) {
|
|
70
|
+
wrappedStrategy = {};
|
|
71
|
+
if ("highWaterMark" in strategy) {
|
|
72
|
+
wrappedStrategy.highWaterMark = strategy.highWaterMark;
|
|
73
|
+
}
|
|
74
|
+
if ("size" in strategy) {
|
|
75
|
+
wrappedStrategy.size = (chunk) => {
|
|
76
|
+
return strategy.size(chunk.value);
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
super({
|
|
81
|
+
async start(controller) {
|
|
82
|
+
wrappedController = {
|
|
83
|
+
async enqueue(chunk) {
|
|
84
|
+
await enqueue(controller, chunk);
|
|
85
|
+
},
|
|
86
|
+
close() {
|
|
87
|
+
controller.close();
|
|
88
|
+
},
|
|
89
|
+
error(reason) {
|
|
90
|
+
controller.error(reason);
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
await source.start?.(wrappedController);
|
|
94
|
+
},
|
|
95
|
+
async pull() {
|
|
96
|
+
await source.pull?.(wrappedController);
|
|
97
|
+
},
|
|
98
|
+
async cancel(reason) {
|
|
99
|
+
await source.cancel?.(reason);
|
|
100
|
+
},
|
|
101
|
+
}, wrappedStrategy);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
export class ConsumableWritableStream extends WritableStream {
|
|
105
|
+
static async write(writer, value) {
|
|
106
|
+
const consumable = new Consumable(value);
|
|
107
|
+
await writer.write(consumable);
|
|
108
|
+
await consumable.consumed;
|
|
109
|
+
}
|
|
110
|
+
constructor(sink, strategy) {
|
|
111
|
+
let wrappedStrategy;
|
|
112
|
+
if (strategy) {
|
|
113
|
+
wrappedStrategy = {};
|
|
114
|
+
if ("highWaterMark" in strategy) {
|
|
115
|
+
wrappedStrategy.highWaterMark = strategy.highWaterMark;
|
|
116
|
+
}
|
|
117
|
+
if ("size" in strategy) {
|
|
118
|
+
wrappedStrategy.size = (chunk) => {
|
|
119
|
+
return strategy.size(chunk.value);
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
super({
|
|
124
|
+
start() {
|
|
125
|
+
return sink.start?.();
|
|
126
|
+
},
|
|
127
|
+
async write(chunk) {
|
|
128
|
+
await chunk.tryConsume((value) => sink.write?.(value));
|
|
129
|
+
chunk.consume();
|
|
130
|
+
},
|
|
131
|
+
abort(reason) {
|
|
132
|
+
return sink.abort?.(reason);
|
|
133
|
+
},
|
|
134
|
+
close() {
|
|
135
|
+
return sink.close?.();
|
|
136
|
+
},
|
|
137
|
+
}, wrappedStrategy);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
export class ConsumableTransformStream extends TransformStream {
|
|
141
|
+
constructor(transformer) {
|
|
142
|
+
let wrappedController;
|
|
143
|
+
super({
|
|
144
|
+
async start(controller) {
|
|
145
|
+
wrappedController = {
|
|
146
|
+
async enqueue(chunk) {
|
|
147
|
+
await enqueue(controller, chunk);
|
|
148
|
+
},
|
|
149
|
+
close() {
|
|
150
|
+
controller.terminate();
|
|
151
|
+
},
|
|
152
|
+
error(reason) {
|
|
153
|
+
controller.error(reason);
|
|
154
|
+
},
|
|
155
|
+
};
|
|
156
|
+
await transformer.start?.(wrappedController);
|
|
157
|
+
},
|
|
158
|
+
async transform(chunk) {
|
|
159
|
+
await chunk.tryConsume((value) => transformer.transform?.(value, wrappedController));
|
|
160
|
+
chunk.consume();
|
|
161
|
+
},
|
|
162
|
+
async flush() {
|
|
163
|
+
await transformer.flush?.(wrappedController);
|
|
164
|
+
},
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
export class ConsumableInspectStream extends TransformStream {
|
|
169
|
+
constructor(callback) {
|
|
170
|
+
super({
|
|
171
|
+
transform(chunk, controller) {
|
|
172
|
+
callback(chunk.value);
|
|
173
|
+
controller.enqueue(chunk);
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=consumable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consumable.js","sourceRoot":"","sources":["../src/consumable.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAGnD,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAc9E,wFAAwF;AACxF,MAAM,EAAE,OAAO,EAAE,GAAG,UAAwC,CAAC;AAC7D,MAAM,UAAU,GACZ,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC;IACjC,CAAC,GAAG,EAAE,CAAC,CAAC;QACJ,GAAG,CAAC,QAAQ;YACR,OAAO,QAAQ,EAAE,CAAC;QACtB,CAAC;KACJ,CAAC,CAAC,CAAC;AAER,MAAM,OAAO,UAAU;IACV,KAAK,CAAO;IACZ,SAAS,CAAwB;IAE1B,KAAK,CAAI;IACT,QAAQ,CAAgB;IAExC,YAAmB,KAAQ;QACvB,IAAI,CAAC,KAAK,GAAG,UAAU,CAAC,YAAY,CAAC,CAAC;QACtC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,SAAS,GAAG,IAAI,eAAe,EAAQ,CAAC;QAC7C,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;IAC3C,CAAC;IAEM,OAAO;QACV,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,CAAC;IAC7B,CAAC;IAEM,KAAK,CAAC,KAAU;QACnB,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;IAEM,KAAK,CAAC,UAAU,CAAI,QAAyB;QAChD,IAAI;YACA,6DAA6D;YAC7D,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YAChE,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,OAAO,MAAM,CAAC;SACjB;QAAC,OAAO,CAAC,EAAE;YACR,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACzB,MAAM,CAAC,CAAC;SACX;IACL,CAAC;CACJ;AAED,KAAK,UAAU,OAAO,CAClB,UAAuD,EACvD,KAAQ;IAER,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IACrC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3B,MAAM,MAAM,CAAC,QAAQ,CAAC;AAC1B,CAAC;AAED,MAAM,OAAO,oBAAwB,SAAQ,eAAiC;IAC1E;QACI,KAAK,CAAC;YACF,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,UAAU;gBAC7B,MAAM,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YACrC,CAAC;SACJ,CAAC,CAAC;IACP,CAAC;CACJ;AAED,MAAM,OAAO,sBAA0B,SAAQ,eAG9C;IACG;QACI,KAAK,CAAC;YACF,SAAS,CAAC,KAAK,EAAE,UAAU;gBACvB,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBAChC,KAAK,CAAC,OAAO,EAAE,CAAC;YACpB,CAAC;SACJ,CAAC,CAAC;IACP,CAAC;CACJ;AAkBD,MAAM,OAAO,wBAA4B,SAAQ,cAA6B;IAC1E,YACI,MAAyC,EACzC,QAA6B;QAE7B,IAAI,iBAEW,CAAC;QAEhB,IAAI,eAA2D,CAAC;QAChE,IAAI,QAAQ,EAAE;YACV,eAAe,GAAG,EAAE,CAAC;YACrB,IAAI,eAAe,IAAI,QAAQ,EAAE;gBAC7B,eAAe,CAAC,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC;aAC1D;YACD,IAAI,MAAM,IAAI,QAAQ,EAAE;gBACpB,eAAe,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,EAAE;oBAC7B,OAAO,QAAQ,CAAC,IAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBACvC,CAAC,CAAC;aACL;SACJ;QAED,KAAK,CACD;YACI,KAAK,CAAC,KAAK,CAAC,UAAU;gBAClB,iBAAiB,GAAG;oBAChB,KAAK,CAAC,OAAO,CAAC,KAAK;wBACf,MAAM,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;oBACrC,CAAC;oBACD,KAAK;wBACD,UAAU,CAAC,KAAK,EAAE,CAAC;oBACvB,CAAC;oBACD,KAAK,CAAC,MAAM;wBACR,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;oBAC7B,CAAC;iBACJ,CAAC;gBAEF,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,iBAAiB,CAAC,CAAC;YAC5C,CAAC;YACD,KAAK,CAAC,IAAI;gBACN,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC,iBAAkB,CAAC,CAAC;YAC5C,CAAC;YACD,KAAK,CAAC,MAAM,CAAC,MAAM;gBACf,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;YAClC,CAAC;SACJ,EACD,eAAe,CAClB,CAAC;IACN,CAAC;CACJ;AASD,MAAM,OAAO,wBAA4B,SAAQ,cAA6B;IACnE,MAAM,CAAC,KAAK,CAAC,KAAK,CACrB,MAAkD,EAClD,KAAQ;QAER,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;QACzC,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC/B,MAAM,UAAU,CAAC,QAAQ,CAAC;IAC9B,CAAC;IAED,YACI,IAAqC,EACrC,QAA6B;QAE7B,IAAI,eAA2D,CAAC;QAChE,IAAI,QAAQ,EAAE;YACV,eAAe,GAAG,EAAE,CAAC;YACrB,IAAI,eAAe,IAAI,QAAQ,EAAE;gBAC7B,eAAe,CAAC,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC;aAC1D;YACD,IAAI,MAAM,IAAI,QAAQ,EAAE;gBACpB,eAAe,CAAC,IAAI,GAAG,CAAC,KAAK,EAAE,EAAE;oBAC7B,OAAO,QAAQ,CAAC,IAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBACvC,CAAC,CAAC;aACL;SACJ;QAED,KAAK,CACD;YACI,KAAK;gBACD,OAAO,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YAC1B,CAAC;YACD,KAAK,CAAC,KAAK,CAAC,KAAK;gBACb,MAAM,KAAK,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;gBACvD,KAAK,CAAC,OAAO,EAAE,CAAC;YACpB,CAAC;YACD,KAAK,CAAC,MAAM;gBACR,OAAO,IAAI,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC;YAChC,CAAC;YACD,KAAK;gBACD,OAAO,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YAC1B,CAAC;SACJ,EACD,eAAe,CAClB,CAAC;IACN,CAAC;CACJ;AAeD,MAAM,OAAO,yBAAgC,SAAQ,eAGpD;IACG,YAAmB,WAAwC;QACvD,IAAI,iBAEW,CAAC;QAEhB,KAAK,CAAC;YACF,KAAK,CAAC,KAAK,CAAC,UAAU;gBAClB,iBAAiB,GAAG;oBAChB,KAAK,CAAC,OAAO,CAAC,KAAK;wBACf,MAAM,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;oBACrC,CAAC;oBACD,KAAK;wBACD,UAAU,CAAC,SAAS,EAAE,CAAC;oBAC3B,CAAC;oBACD,KAAK,CAAC,MAAM;wBACR,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;oBAC7B,CAAC;iBACJ,CAAC;gBAEF,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC,iBAAiB,CAAC,CAAC;YACjD,CAAC;YACD,KAAK,CAAC,SAAS,CAAC,KAAK;gBACjB,MAAM,KAAK,CAAC,UAAU,CAAC,CAAC,KAAK,EAAE,EAAE,CAC7B,WAAW,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,iBAAkB,CAAC,CACrD,CAAC;gBACF,KAAK,CAAC,OAAO,EAAE,CAAC;YACpB,CAAC;YACD,KAAK,CAAC,KAAK;gBACP,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC,iBAAkB,CAAC,CAAC;YAClD,CAAC;SACJ,CAAC,CAAC;IACP,CAAC;CACJ;AAED,MAAM,OAAO,uBAA2B,SAAQ,eAG/C;IACG,YAAmB,QAA4B;QAC3C,KAAK,CAAC;YACF,SAAS,CAAC,KAAK,EAAE,UAAU;gBACvB,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;gBACtB,UAAU,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC9B,CAAC;SACJ,CAAC,CAAC;IACP,CAAC;CACJ"}
|
package/esm/decode-utf8.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { TransformStream } from "./stream.js";
|
|
2
|
-
export declare class DecodeUtf8Stream extends TransformStream<Uint8Array, string> {
|
|
3
|
-
constructor();
|
|
4
|
-
}
|
|
1
|
+
import { TransformStream } from "./stream.js";
|
|
2
|
+
export declare class DecodeUtf8Stream extends TransformStream<Uint8Array, string> {
|
|
3
|
+
constructor();
|
|
4
|
+
}
|
|
5
5
|
//# sourceMappingURL=decode-utf8.d.ts.map
|
package/esm/decode-utf8.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { decodeUtf8 } from "@yume-chan/struct";
|
|
2
|
-
import { TransformStream } from "./stream.js";
|
|
3
|
-
export class DecodeUtf8Stream extends TransformStream {
|
|
4
|
-
constructor() {
|
|
5
|
-
super({
|
|
6
|
-
transform(chunk, controller) {
|
|
7
|
-
controller.enqueue(decodeUtf8(chunk));
|
|
8
|
-
},
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
}
|
|
1
|
+
import { decodeUtf8 } from "@yume-chan/struct";
|
|
2
|
+
import { TransformStream } from "./stream.js";
|
|
3
|
+
export class DecodeUtf8Stream extends TransformStream {
|
|
4
|
+
constructor() {
|
|
5
|
+
super({
|
|
6
|
+
transform(chunk, controller) {
|
|
7
|
+
controller.enqueue(decodeUtf8(chunk));
|
|
8
|
+
},
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
12
|
//# sourceMappingURL=decode-utf8.js.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ConsumableTransformStream } from "./consumable.js";
|
|
2
|
+
/**
|
|
3
|
+
* Splits or combines buffers to specified size.
|
|
4
|
+
*/
|
|
5
|
+
export declare class BufferCombiner {
|
|
6
|
+
#private;
|
|
7
|
+
constructor(size: number);
|
|
8
|
+
/**
|
|
9
|
+
* Pushes data to the combiner.
|
|
10
|
+
* @param data The input data to be split or combined.
|
|
11
|
+
* @returns
|
|
12
|
+
* A generator that yields buffers of specified size.
|
|
13
|
+
* It may yield the same buffer multiple times, consume the data before calling `next`.
|
|
14
|
+
*/
|
|
15
|
+
push(data: Uint8Array): Generator<Uint8Array, void, void>;
|
|
16
|
+
flush(): Uint8Array | undefined;
|
|
17
|
+
}
|
|
18
|
+
export declare class DistributionStream extends ConsumableTransformStream<Uint8Array, Uint8Array> {
|
|
19
|
+
constructor(size: number, combine?: boolean);
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=distribution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"distribution.d.ts","sourceRoot":"","sources":["../src/distribution.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC;AAE5D;;GAEG;AACH,qBAAa,cAAc;;gBAMJ,IAAI,EAAE,MAAM;IAO/B;;;;;;OAMG;IACK,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,CAAC,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC;IA0C1D,KAAK,IAAI,UAAU,GAAG,SAAS;CAUzC;AAED,qBAAa,kBAAmB,SAAQ,yBAAyB,CAC7D,UAAU,EACV,UAAU,CACb;gBACsB,IAAI,EAAE,MAAM,EAAE,OAAO,UAAQ;CA6BnD"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { ConsumableTransformStream } from "./consumable.js";
|
|
2
|
+
/**
|
|
3
|
+
* Splits or combines buffers to specified size.
|
|
4
|
+
*/
|
|
5
|
+
export class BufferCombiner {
|
|
6
|
+
#capacity;
|
|
7
|
+
#buffer;
|
|
8
|
+
#offset;
|
|
9
|
+
#available;
|
|
10
|
+
constructor(size) {
|
|
11
|
+
this.#capacity = size;
|
|
12
|
+
this.#buffer = new Uint8Array(size);
|
|
13
|
+
this.#offset = 0;
|
|
14
|
+
this.#available = size;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Pushes data to the combiner.
|
|
18
|
+
* @param data The input data to be split or combined.
|
|
19
|
+
* @returns
|
|
20
|
+
* A generator that yields buffers of specified size.
|
|
21
|
+
* It may yield the same buffer multiple times, consume the data before calling `next`.
|
|
22
|
+
*/
|
|
23
|
+
*push(data) {
|
|
24
|
+
let offset = 0;
|
|
25
|
+
let available = data.byteLength;
|
|
26
|
+
if (this.#offset !== 0) {
|
|
27
|
+
if (available >= this.#available) {
|
|
28
|
+
this.#buffer.set(data.subarray(0, this.#available), this.#offset);
|
|
29
|
+
offset += this.#available;
|
|
30
|
+
available -= this.#available;
|
|
31
|
+
yield this.#buffer;
|
|
32
|
+
this.#offset = 0;
|
|
33
|
+
this.#available = this.#capacity;
|
|
34
|
+
if (available === 0) {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
this.#buffer.set(data, this.#offset);
|
|
40
|
+
this.#offset += available;
|
|
41
|
+
this.#available -= available;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
while (available >= this.#capacity) {
|
|
46
|
+
const end = offset + this.#capacity;
|
|
47
|
+
yield data.subarray(offset, end);
|
|
48
|
+
offset = end;
|
|
49
|
+
available -= this.#capacity;
|
|
50
|
+
}
|
|
51
|
+
if (available > 0) {
|
|
52
|
+
this.#buffer.set(data.subarray(offset), this.#offset);
|
|
53
|
+
this.#offset += available;
|
|
54
|
+
this.#available -= available;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
flush() {
|
|
58
|
+
if (this.#offset === 0) {
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
const output = this.#buffer.subarray(0, this.#offset);
|
|
62
|
+
this.#offset = 0;
|
|
63
|
+
this.#available = this.#capacity;
|
|
64
|
+
return output;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
export class DistributionStream extends ConsumableTransformStream {
|
|
68
|
+
constructor(size, combine = false) {
|
|
69
|
+
const combiner = combine ? new BufferCombiner(size) : undefined;
|
|
70
|
+
super({
|
|
71
|
+
async transform(chunk, controller) {
|
|
72
|
+
if (combiner) {
|
|
73
|
+
for (const buffer of combiner.push(chunk)) {
|
|
74
|
+
await controller.enqueue(buffer);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
let offset = 0;
|
|
79
|
+
let available = chunk.byteLength;
|
|
80
|
+
while (available > 0) {
|
|
81
|
+
const end = offset + size;
|
|
82
|
+
await controller.enqueue(chunk.subarray(offset, end));
|
|
83
|
+
offset = end;
|
|
84
|
+
available -= size;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
async flush(controller) {
|
|
89
|
+
if (combiner) {
|
|
90
|
+
const data = combiner.flush();
|
|
91
|
+
if (data) {
|
|
92
|
+
await controller.enqueue(data);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=distribution.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"distribution.js","sourceRoot":"","sources":["../src/distribution.ts"],"names":[],"mappings":"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"}
|
package/esm/duplex.d.ts
CHANGED
|
@@ -1,48 +1,45 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
*
|
|
8
|
-
* or `
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
*
|
|
21
|
-
* or `
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
private
|
|
37
|
-
|
|
38
|
-
get
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
close(): Promise<void>;
|
|
46
|
-
dispose(): Promise<void>;
|
|
47
|
-
}
|
|
1
|
+
import type { ValueOrPromise } from "@yume-chan/struct";
|
|
2
|
+
import type { ReadableStream } from "./stream.js";
|
|
3
|
+
import { WritableStream } from "./stream.js";
|
|
4
|
+
import { WrapReadableStream } from "./wrap-readable.js";
|
|
5
|
+
export interface DuplexStreamFactoryOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Callback when any `ReadableStream` is cancelled (the user doesn't need any more data),
|
|
8
|
+
* or `WritableStream` is ended (the user won't produce any more data),
|
|
9
|
+
* or `DuplexStreamFactory#close` is called.
|
|
10
|
+
*
|
|
11
|
+
* Usually you want to let the other peer know that the duplex stream should be closed.
|
|
12
|
+
*
|
|
13
|
+
* `dispose` will automatically be called after `close` completes,
|
|
14
|
+
* but if you want to wait another peer for a close confirmation and call
|
|
15
|
+
* `DuplexStreamFactory#dispose` yourself, you can return `false`
|
|
16
|
+
* (or a `Promise` that resolves to `false`) to disable the automatic call.
|
|
17
|
+
*/
|
|
18
|
+
close?: (() => ValueOrPromise<boolean | void>) | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* Callback when any `ReadableStream` is closed (the other peer doesn't produce any more data),
|
|
21
|
+
* or `WritableStream` is aborted (the other peer can't receive any more data),
|
|
22
|
+
* or `DuplexStreamFactory#abort` is called.
|
|
23
|
+
*
|
|
24
|
+
* Usually indicates the other peer has closed the duplex stream. You can clean up
|
|
25
|
+
* any resources you have allocated now.
|
|
26
|
+
*/
|
|
27
|
+
dispose?: (() => void | Promise<void>) | undefined;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A factory for creating a duplex stream.
|
|
31
|
+
*
|
|
32
|
+
* It can create multiple `ReadableStream`s and `WritableStream`s,
|
|
33
|
+
* when any of them is closed, all other streams will be closed as well.
|
|
34
|
+
*/
|
|
35
|
+
export declare class DuplexStreamFactory<R, W> {
|
|
36
|
+
#private;
|
|
37
|
+
get writableClosed(): boolean;
|
|
38
|
+
get closed(): Promise<void>;
|
|
39
|
+
constructor(options?: DuplexStreamFactoryOptions);
|
|
40
|
+
wrapReadable(readable: ReadableStream<R>): WrapReadableStream<R>;
|
|
41
|
+
createWritable(stream: WritableStream<W>): WritableStream<W>;
|
|
42
|
+
close(): Promise<void>;
|
|
43
|
+
dispose(): Promise<void>;
|
|
44
|
+
}
|
|
48
45
|
//# sourceMappingURL=duplex.d.ts.map
|
package/esm/duplex.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"duplex.d.ts","sourceRoot":"","sources":["../src/duplex.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"duplex.d.ts","sourceRoot":"","sources":["../src/duplex.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAExD,OAAO,KAAK,EACR,cAAc,EAGjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAMxD,MAAM,WAAW,0BAA0B;IACvC;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,EAAE,CAAC,MAAM,cAAc,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;IAE3D;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;CACtD;AAED;;;;;GAKG;AACH,qBAAa,mBAAmB,CAAC,CAAC,EAAE,CAAC;;IAKjC,IAAW,cAAc,YAExB;IAGD,IAAW,MAAM,kBAEhB;gBAIkB,OAAO,CAAC,EAAE,0BAA0B;IAIhD,YAAY,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,kBAAkB,CAAC,CAAC,CAAC;IAiBhE,cAAc,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC;IAsBtD,KAAK;IAkBL,OAAO;CAcvB"}
|
package/esm/duplex.js
CHANGED
|
@@ -1,93 +1,93 @@
|
|
|
1
|
-
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
-
import { WritableStream
|
|
3
|
-
import { WrapReadableStream } from "./wrap-readable.js";
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
*
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
await
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
async dispose() {
|
|
80
|
-
this
|
|
81
|
-
this.
|
|
82
|
-
for (const controller of this
|
|
83
|
-
try {
|
|
84
|
-
controller.close();
|
|
85
|
-
}
|
|
86
|
-
catch
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
await this
|
|
91
|
-
}
|
|
92
|
-
}
|
|
1
|
+
import { PromiseResolver } from "@yume-chan/async";
|
|
2
|
+
import { WritableStream } from "./stream.js";
|
|
3
|
+
import { WrapReadableStream } from "./wrap-readable.js";
|
|
4
|
+
const NOOP = () => {
|
|
5
|
+
// no-op
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* A factory for creating a duplex stream.
|
|
9
|
+
*
|
|
10
|
+
* It can create multiple `ReadableStream`s and `WritableStream`s,
|
|
11
|
+
* when any of them is closed, all other streams will be closed as well.
|
|
12
|
+
*/
|
|
13
|
+
export class DuplexStreamFactory {
|
|
14
|
+
#readableControllers = [];
|
|
15
|
+
#writers = [];
|
|
16
|
+
#writableClosed = false;
|
|
17
|
+
get writableClosed() {
|
|
18
|
+
return this.#writableClosed;
|
|
19
|
+
}
|
|
20
|
+
#closed = new PromiseResolver();
|
|
21
|
+
get closed() {
|
|
22
|
+
return this.#closed.promise;
|
|
23
|
+
}
|
|
24
|
+
#options;
|
|
25
|
+
constructor(options) {
|
|
26
|
+
this.#options = options ?? {};
|
|
27
|
+
}
|
|
28
|
+
wrapReadable(readable) {
|
|
29
|
+
return new WrapReadableStream({
|
|
30
|
+
start: (controller) => {
|
|
31
|
+
this.#readableControllers.push(controller);
|
|
32
|
+
return readable;
|
|
33
|
+
},
|
|
34
|
+
cancel: async () => {
|
|
35
|
+
// cancel means the local peer wants to close the connection.
|
|
36
|
+
await this.close();
|
|
37
|
+
},
|
|
38
|
+
close: async () => {
|
|
39
|
+
// stream end means the remote peer closed the connection first.
|
|
40
|
+
await this.dispose();
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
createWritable(stream) {
|
|
45
|
+
const writer = stream.getWriter();
|
|
46
|
+
this.#writers.push(writer);
|
|
47
|
+
// `WritableStream` has no way to tell if the remote peer has closed the connection.
|
|
48
|
+
// So it only triggers `close`.
|
|
49
|
+
return new WritableStream({
|
|
50
|
+
write: async (chunk) => {
|
|
51
|
+
await writer.write(chunk);
|
|
52
|
+
},
|
|
53
|
+
abort: async (reason) => {
|
|
54
|
+
await writer.abort(reason);
|
|
55
|
+
await this.close();
|
|
56
|
+
},
|
|
57
|
+
close: async () => {
|
|
58
|
+
// NOOP: the writer is already closed
|
|
59
|
+
await writer.close().catch(NOOP);
|
|
60
|
+
await this.close();
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
async close() {
|
|
65
|
+
if (this.#writableClosed) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
this.#writableClosed = true;
|
|
69
|
+
// Call `close` first, so it can still write data to `WritableStream`s.
|
|
70
|
+
if ((await this.#options.close?.()) !== false) {
|
|
71
|
+
// `close` can return `false` to disable automatic `dispose`.
|
|
72
|
+
await this.dispose();
|
|
73
|
+
}
|
|
74
|
+
for (const writer of this.#writers) {
|
|
75
|
+
// NOOP: the writer is already closed
|
|
76
|
+
writer.close().catch(NOOP);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
async dispose() {
|
|
80
|
+
this.#writableClosed = true;
|
|
81
|
+
this.#closed.resolve();
|
|
82
|
+
for (const controller of this.#readableControllers) {
|
|
83
|
+
try {
|
|
84
|
+
controller.close();
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// ignore
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
await this.#options.dispose?.();
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
93
|
//# sourceMappingURL=duplex.js.map
|