1describe("BufferedWriter", () => {
2 test("basics", () => {
3 const chunks: Uint8Array[] = [];
4 const w = new stream.BufferedWriter((d) => chunks.push(d), 16);
5
6 w.u8(1);
7 w.u16(258);
8 w.u32(0x04030201);
9 w.flush();
10
11 assert.equal(chunks.length, 1);
12 assert.deepEqual(chunks[0], new Uint8Array([1, 2, 1, 1, 2, 3, 4]));
13 });
14
15 test("auto-flush on large write", () => {
16 const chunks: Uint8Array[] = [];
17 const w = new stream.BufferedWriter((d) => chunks.push(d), 8);
18
19 w.u32(1);
20 assert.equal(w.written, 4);
21 const large = new Uint8Array(20).fill(0xff);
22 w.write(large);
23 assert.equal(w.written, 0);
24
25 assert.equal(chunks.length, 2);
26 assert.equal(chunks[0]!.length, 4);
27 assert.equal(chunks[1]!.length, 20);
28 });
29
30 test("transfer based flush", () => {
31 const chunks: Uint8Array[] = [];
32 const w = new stream.BufferedWriter((d) => chunks.push(d), 4);
33
34 w.u8(1);
35 w.u8(2);
36 w.u8(3);
37 w.u8(4);
38 w.flush();
39 w.u8(2);
40 w.u8(3);
41 w.u8(4);
42 w.u8(5);
43 w[Symbol.dispose]();
44
45 assert.equal(chunks.length, 2);
46 assert.deepEqual(chunks[0], new Uint8Array([1, 2, 3, 4]));
47 assert.deepEqual(chunks[1], new Uint8Array([2, 3, 4, 5]));
48 });
49
50 test("ensure more than total capacity", () => {
51 const chunks: Uint8Array[] = [];
52 const w = new stream.BufferedWriter((d) => chunks.push(d), 2);
53 assert.equal(w.size, 2);
54 w.u8(4);
55 w.ensureUnusedCapacity(8); // flushes [ 4 ]
56 w.write(new Uint8Array([4, 5, 5, 8, 8, 1, 2]));
57 assert.equal(w.written, 7);
58 assert.equal(w.size, 8);
59 w.u32(42);
60 w.flush();
61
62 assert.equal(chunks.length, 3);
63 assert.deepEqual(chunks[0], new Uint8Array([4]));
64 assert.deepEqual(chunks[1], new Uint8Array([4, 5, 5, 8, 8, 1, 2]));
65 assert.deepEqual(chunks[2], new Uint8Array([42, 0, 0, 0]));
66 });
67
68 test("varUint", () => {
69 const chunks: Uint8Array[] = [];
70 const w = new stream.BufferedWriter((d) => chunks.push(d));
71
72 w.varUint(0);
73 w.varUint(127);
74 w.varUint(128);
75 w.varUint(16383);
76 w.flush();
77
78 assert.deepEqual(chunks[0], new Uint8Array([0, 127, 128, 1, 255, 127]));
79 });
80
81 test("dispose", () => {
82 const chunks: Uint8Array[] = [];
83 {
84 using w = new stream.BufferedWriter((d) => chunks.push(d));
85 w.u8(42);
86 }
87 assert.equal(chunks.length, 1);
88 assert.equal(chunks[0]![0], 42);
89 });
90});
91
92describe("BufferedReader", () => {
93 test("basic read", async () => {
94 const [s, w] = stream.bufferedReadableStream();
95 w.u8(1);
96 w.u16(258);
97 w.flush();
98 w.u32(0x04030201);
99 w.flush();
100
101 using r = new stream.BufferedReader(s.getReader());
102 assert.equal(await r.u8(), 1);
103 assert.equal(await r.u16(), 258);
104 assert.equal(await r.u16(), 0x0201);
105 assert.equal(await r.u16(), 0x0403);
106 });
107
108 test("varUint", async () => {
109 const [s, w] = stream.bufferedReadableStream();
110 w.varUint(0);
111 w.varUint(127);
112 w.varUint(128);
113 w.varUint(16383);
114 w.varUint(1768210855277);
115 w.varUint(521);
116 w.close();
117
118 using r = new stream.BufferedReader(s.getReader());
119 assert.equal(await r.varUint(), 0);
120 assert.equal(await r.varUint(), 127);
121 assert.equal(await r.varUint(), 128);
122 assert.equal(await r.varUint(), 16383);
123 assert.equal(await r.varUint(), 1768210855277);
124 assert.equal(await r.varUint(), 521);
125 });
126
127 test("cross-chunk read", async () => {
128 const [s, w] = stream.bufferedReadableStream();
129 w.u8(1);
130 w.flush();
131 w.u8(2);
132 w.flush();
133
134 using r = new stream.BufferedReader(s.getReader());
135 assert.equal(await r.u16(), 0x0201);
136 });
137
138 test("readExactly", async () => {
139 const [s, w] = stream.bufferedReadableStream();
140 w.write(new Uint8Array([1, 2, 3, 4, 5]));
141 w.flush();
142
143 using r = new stream.BufferedReader(s.getReader());
144 const buf = await r.readExactly(3);
145 assert.deepEqual(buf, new Uint8Array([1, 2, 3]));
146 assert.equal(await r.u8(), 4);
147 });
148
149 test.todo("readExactly cutting chunks", async () => {
150 const [s, w] = stream.bufferedReadableStream();
151 w.write(new Uint8Array([1, 2, 3]));
152 w.flush();
153 w.write(new Uint8Array([4, 5, 6]));
154 w.flush();
155 w.write(new Uint8Array([7, 8, 9]));
156 w.flush();
157 w.write(new Uint8Array([10, 11, 12]));
158 w.flush();
159
160 using r = new stream.BufferedReader(s.getReader());
161 assert.deepEqual(await r.readExactly(4), new Uint8Array([1, 2, 3, 4]));
162 assert.deepEqual(await r.readExactly(4), new Uint8Array([5, 6, 7, 8]));
163 assert.deepEqual(await r.readExactly(4), new Uint8Array([9, 10, 11, 12]));
164 });
165
166 test("readUpTo", async () => {
167 const [s, w] = stream.bufferedReadableStream();
168 w.write(new Uint8Array([1, 2]));
169 w.close();
170
171 using r = new stream.BufferedReader(s.getReader());
172 const buf = await r.readUpTo(10);
173 assert.equal(buf.length, 2);
174 });
175
176 test("stringWithLength", async () => {
177 const [s, w] = stream.bufferedReadableStream();
178 w.stringWithLength("hello");
179 w.flush();
180
181 using r = new stream.BufferedReader(s.getReader());
182 assert.equal(await r.stringWithLength(), "hello");
183 });
184
185 test("some numeric types", async () => {
186 const [s, w] = stream.bufferedReadableStream();
187
188 w.i8(-1);
189 w.i16(-1);
190 w.i32(-1);
191 w.i64(-1n);
192 w.u32(4_000_000_000);
193 w.u64(0xffffffffffffffffn);
194 w.f16(1.5);
195 w.f32(1.5);
196 w.f64(1.5);
197 w.close();
198
199 using r = new stream.BufferedReader(s.getReader());
200 assert.equal(await r.i8(), -1);
201 assert.equal(await r.i16(), -1);
202 assert.equal(await r.i32(), -1);
203 assert.equal(await r.i64(), -1n);
204 assert.equal(await r.u32(), 4_000_000_000);
205 assert.equal(await r.u64(), 0xffffffffffffffffn);
206 assert.equal(await r.f16(), 1.5);
207 assert.equal(await r.f32(), 1.5);
208 assert.equal(await r.f64(), 1.5);
209 });
210
211 test("cancel", () => {
212 let cancelReason: unknown;
213 const s = new ReadableStream({
214 start() {},
215 cancel(reason) {
216 cancelReason = reason;
217 },
218 });
219
220 const r = new stream.BufferedReader(s.getReader());
221 const err = new Error("test cancel");
222 r.cancel(err);
223
224 assert.equal(cancelReason, err);
225 });
226});
227
228import { strict as assert } from "node:assert";
229import { describe, test } from "vitest";
230import * as stream from "./stream.ts";