toiljs 0.0.15 → 0.0.16

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.
Files changed (217) hide show
  1. package/.babelrc +13 -13
  2. package/.gitattributes +2 -2
  3. package/.github/ISSUE_TEMPLATE/bug_report.md +38 -38
  4. package/.github/ISSUE_TEMPLATE/bug_report.yml +90 -90
  5. package/.github/ISSUE_TEMPLATE/config.yml +8 -8
  6. package/.github/ISSUE_TEMPLATE/feature_request.md +20 -20
  7. package/.github/PULL_REQUEST_TEMPLATE.md +43 -43
  8. package/.github/changelog-config.json +45 -45
  9. package/.github/dependabot.yml +27 -27
  10. package/.github/workflows/ci.yml +191 -191
  11. package/.prettierrc.json +11 -11
  12. package/.vscode/settings.json +9 -9
  13. package/CHANGELOG.md +5 -5
  14. package/LICENSE +187 -187
  15. package/README.md +339 -315
  16. package/as-pect.asconfig.json +34 -34
  17. package/as-pect.config.js +65 -65
  18. package/assets/logo.svg +36 -36
  19. package/build/backend/.tsbuildinfo +1 -1
  20. package/build/cli/.tsbuildinfo +1 -1
  21. package/build/cli/index.js +0 -0
  22. package/build/client/.tsbuildinfo +1 -1
  23. package/build/client/dev/devtools.d.ts +6 -0
  24. package/build/client/dev/devtools.js +442 -0
  25. package/build/client/dev/error-overlay.d.ts +9 -0
  26. package/build/client/dev/error-overlay.js +19 -4
  27. package/build/client/navigation/prefetch.d.ts +1 -0
  28. package/build/client/navigation/prefetch.js +35 -0
  29. package/build/client/routing/Router.js +1 -1
  30. package/build/client/routing/hooks.js +6 -2
  31. package/build/client/routing/loader.d.ts +23 -0
  32. package/build/client/routing/loader.js +53 -7
  33. package/build/client/routing/mount.js +4 -3
  34. package/build/compiler/.tsbuildinfo +1 -1
  35. package/build/compiler/config.d.ts +16 -0
  36. package/build/compiler/config.js +7 -0
  37. package/build/compiler/docs.js +16 -16
  38. package/build/compiler/index.d.ts +2 -2
  39. package/build/compiler/index.js +1 -1
  40. package/build/compiler/plugin.js +156 -0
  41. package/build/compiler/prerender.d.ts +1 -0
  42. package/build/compiler/prerender.js +1 -1
  43. package/build/compiler/seo.d.ts +1 -1
  44. package/build/compiler/seo.js +5 -4
  45. package/build/compiler/ssg.js +32 -1
  46. package/build/io/.tsbuildinfo +1 -1
  47. package/build/logger/.tsbuildinfo +1 -1
  48. package/build/shared/.tsbuildinfo +1 -1
  49. package/eslint.config.js +48 -48
  50. package/examples/basic/client/404.tsx +11 -11
  51. package/examples/basic/client/components/.gitkeep +1 -1
  52. package/examples/basic/client/global-error.tsx +13 -13
  53. package/examples/basic/client/layout.tsx +25 -25
  54. package/examples/basic/client/public/images/.gitkeep +1 -1
  55. package/examples/basic/client/public/images/logo.svg +36 -36
  56. package/examples/basic/client/public/robots.txt +2 -2
  57. package/examples/basic/client/routes/docs/[...slug].tsx +12 -12
  58. package/examples/basic/client/routes/features/error/error.tsx +16 -16
  59. package/examples/basic/client/routes/features/template/b.tsx +14 -14
  60. package/examples/basic/client/routes/files/[[...slug]].tsx +21 -21
  61. package/examples/basic/client/routes/gallery/layout.tsx +13 -13
  62. package/examples/basic/client/routes/io.tsx +24 -24
  63. package/examples/basic/client/routes/loader-demo/loading.tsx +13 -13
  64. package/examples/basic/client/routes/search.tsx +61 -61
  65. package/examples/basic/client/toil.tsx +5 -5
  66. package/package.json +155 -148
  67. package/presets/eslint.js +88 -88
  68. package/presets/no-uint8array-tostring.js +200 -200
  69. package/presets/prettier.json +18 -18
  70. package/presets/tsconfig.json +37 -37
  71. package/src/backend/index.ts +160 -160
  72. package/src/cli/proc.ts +50 -50
  73. package/src/cli/updates.ts +69 -69
  74. package/src/cli/validate.ts +31 -31
  75. package/src/client/channel/channel.ts +146 -146
  76. package/src/client/components/Form.tsx +65 -65
  77. package/src/client/components/Script.tsx +113 -113
  78. package/src/client/components/Slot.tsx +21 -21
  79. package/src/client/dev/devtools.tsx +973 -0
  80. package/src/client/dev/error-overlay.tsx +30 -4
  81. package/src/client/head/head.ts +167 -167
  82. package/src/client/head/metadata.ts +112 -112
  83. package/src/client/index.ts +89 -89
  84. package/src/client/navigation/NavLink.tsx +86 -86
  85. package/src/client/navigation/navigation.ts +235 -235
  86. package/src/client/navigation/prefetch.ts +169 -130
  87. package/src/client/navigation/scroll.ts +53 -53
  88. package/src/client/routing/Router.tsx +8 -2
  89. package/src/client/routing/action.ts +122 -122
  90. package/src/client/routing/error-boundary.tsx +43 -43
  91. package/src/client/routing/hooks.ts +21 -6
  92. package/src/client/routing/loader.ts +325 -235
  93. package/src/client/routing/match.ts +47 -47
  94. package/src/client/routing/mount.tsx +54 -52
  95. package/src/client/routing/params-context.ts +10 -10
  96. package/src/client/routing/slot-context.ts +7 -7
  97. package/src/client/search/search.ts +189 -189
  98. package/src/client/search/use-page-search.ts +73 -73
  99. package/src/client/types.ts +73 -73
  100. package/src/compiler/config.ts +219 -182
  101. package/src/compiler/docs.ts +228 -228
  102. package/src/compiler/generate.ts +394 -394
  103. package/src/compiler/index.ts +64 -57
  104. package/src/compiler/pages.ts +70 -70
  105. package/src/compiler/plugin.ts +170 -2
  106. package/src/compiler/prerender.ts +156 -156
  107. package/src/compiler/seo.ts +397 -390
  108. package/src/compiler/ssg.ts +162 -126
  109. package/src/io/BinaryReader.ts +340 -340
  110. package/src/io/BinaryWriter.ts +385 -385
  111. package/src/io/FastMap.ts +127 -127
  112. package/src/io/index.ts +11 -11
  113. package/src/io/lengths.ts +14 -14
  114. package/src/io/types.ts +18 -18
  115. package/src/logger/index.ts +22 -22
  116. package/src/server/index.ts +10 -10
  117. package/src/server/main.ts +13 -13
  118. package/src/server/tsconfig.json +4 -4
  119. package/src/shared/index.ts +10 -10
  120. package/std/client/index.d.ts +15 -15
  121. package/std/client/package.json +3 -3
  122. package/test/assembly/example.spec.ts +7 -7
  123. package/test/channel.test.ts +21 -21
  124. package/test/dom/Link.test.tsx +47 -47
  125. package/test/dom/NavLink.test.tsx +37 -37
  126. package/test/dom/error-overlay.test.tsx +44 -44
  127. package/test/dom/loader.test.tsx +121 -121
  128. package/test/dom/navigation.test.ts +59 -59
  129. package/test/dom/revalidate.test.tsx +38 -38
  130. package/test/dom/route-head.test.tsx +78 -78
  131. package/test/dom/router-loading.test.tsx +44 -44
  132. package/test/dom/scroll.test.ts +56 -56
  133. package/test/dom/use-metadata.test.tsx +58 -58
  134. package/test/io.test.ts +93 -93
  135. package/test/navlink.test.ts +28 -28
  136. package/test/placeholder.test.ts +9 -9
  137. package/test/routes.test.ts +76 -76
  138. package/test/seo.test.ts +175 -164
  139. package/test/slot-layouts.test.ts +69 -69
  140. package/test/ssg.test.ts +36 -36
  141. package/test/update.test.ts +44 -44
  142. package/test/validate.test.ts +42 -42
  143. package/toil-routes.d.ts +7 -0
  144. package/toilconfig.json +30 -30
  145. package/tsconfig.backend.json +13 -13
  146. package/tsconfig.base.json +35 -35
  147. package/tsconfig.cli.json +13 -13
  148. package/tsconfig.client.json +14 -14
  149. package/tsconfig.compiler.json +13 -13
  150. package/tsconfig.io.json +12 -12
  151. package/tsconfig.json +22 -22
  152. package/tsconfig.logger.json +12 -12
  153. package/tsconfig.server.json +10 -10
  154. package/tsconfig.shared.json +12 -12
  155. package/vitest.config.ts +26 -26
  156. package/.idea/codeStyles/Project.xml +0 -54
  157. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  158. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  159. package/.idea/modules.xml +0 -8
  160. package/.idea/prettier.xml +0 -7
  161. package/.idea/toiljs.iml +0 -8
  162. package/.idea/vcs.xml +0 -6
  163. package/.toil/entry.tsx +0 -9
  164. package/.toil/index.html +0 -12
  165. package/.toil/routes.ts +0 -9
  166. package/build/cli/configure.d.ts +0 -16
  167. package/build/cli/configure.js +0 -272
  168. package/build/cli/create.d.ts +0 -16
  169. package/build/cli/create.js +0 -420
  170. package/build/cli/diagnostics.d.ts +0 -55
  171. package/build/cli/diagnostics.js +0 -333
  172. package/build/cli/doctor.d.ts +0 -6
  173. package/build/cli/doctor.js +0 -249
  174. package/build/cli/features.d.ts +0 -25
  175. package/build/cli/features.js +0 -107
  176. package/build/cli/index.d.ts +0 -2
  177. package/build/cli/proc.d.ts +0 -6
  178. package/build/cli/proc.js +0 -31
  179. package/build/cli/ui.d.ts +0 -9
  180. package/build/cli/ui.js +0 -75
  181. package/build/cli/update.d.ts +0 -7
  182. package/build/cli/update.js +0 -117
  183. package/build/cli/updates.d.ts +0 -10
  184. package/build/cli/updates.js +0 -45
  185. package/build/cli/validate.d.ts +0 -4
  186. package/build/cli/validate.js +0 -19
  187. package/build/client/Link.d.ts +0 -8
  188. package/build/client/Link.js +0 -44
  189. package/build/client/NavLink.d.ts +0 -14
  190. package/build/client/NavLink.js +0 -37
  191. package/build/client/Router.d.ts +0 -7
  192. package/build/client/Router.js +0 -55
  193. package/build/client/channel.d.ts +0 -23
  194. package/build/client/channel.js +0 -94
  195. package/build/client/error-boundary.d.ts +0 -16
  196. package/build/client/error-boundary.js +0 -19
  197. package/build/client/head.d.ts +0 -26
  198. package/build/client/head.js +0 -87
  199. package/build/client/hooks.d.ts +0 -17
  200. package/build/client/hooks.js +0 -48
  201. package/build/client/lazy.d.ts +0 -16
  202. package/build/client/lazy.js +0 -53
  203. package/build/client/match.d.ts +0 -2
  204. package/build/client/match.js +0 -32
  205. package/build/client/mount.d.ts +0 -2
  206. package/build/client/mount.js +0 -13
  207. package/build/client/navigation.d.ts +0 -13
  208. package/build/client/navigation.js +0 -97
  209. package/build/client/params-context.d.ts +0 -2
  210. package/build/client/params-context.js +0 -2
  211. package/build/client/prefetch.d.ts +0 -11
  212. package/build/client/prefetch.js +0 -100
  213. package/build/client/runtime.d.ts +0 -31
  214. package/build/client/runtime.js +0 -112
  215. package/build/client/scroll.d.ts +0 -8
  216. package/build/client/scroll.js +0 -36
  217. package/toil-env.d.ts +0 -16
@@ -1,385 +1,385 @@
1
- import {
2
- I128_BYTE_LENGTH,
3
- I16_BYTE_LENGTH,
4
- I32_BYTE_LENGTH,
5
- I64_BYTE_LENGTH,
6
- I8_BYTE_LENGTH,
7
- U128_BYTE_LENGTH,
8
- U16_BYTE_LENGTH,
9
- U256_BYTE_LENGTH,
10
- U32_BYTE_LENGTH,
11
- U64_BYTE_LENGTH,
12
- U8_BYTE_LENGTH,
13
- } from './lengths.js';
14
- import type { i16, i32, i64, i8, Selector, u16, u32, u64, u8 } from './types.js';
15
- import { BinaryReader } from './BinaryReader.js';
16
-
17
- /** Encodes a non-negative bigint into a big-endian byte array of exactly `length` bytes. */
18
- function bigIntToBytes(value: bigint, length: number = U256_BYTE_LENGTH): Uint8Array {
19
- if (value < 0n) {
20
- throw new RangeError('Value cannot be negative');
21
- }
22
-
23
- const hex = value.toString(16).padStart(length * 2, '0');
24
- if (hex.length > length * 2) {
25
- throw new RangeError(`Value exceeds ${length}-byte range`);
26
- }
27
-
28
- const out = new Uint8Array(length);
29
- for (let i = 0; i < length; i++) {
30
- out[i] = parseInt(hex.substring(i * 2, i * 2 + 2), 16);
31
- }
32
-
33
- return out;
34
- }
35
-
36
- export class BinaryWriter implements Disposable {
37
- private currentOffset: u32 = 0;
38
- private buffer: DataView;
39
-
40
- constructor(length: number = 0) {
41
- this.buffer = this.getDefaultBuffer(length);
42
- }
43
-
44
- public static estimateArrayOfBufferLength(values: Uint8Array[]): u32 {
45
- if (values.length > 65535) throw new Error('Array size is too large');
46
- let totalLength: u32 = U16_BYTE_LENGTH;
47
-
48
- for (let i = 0; i < values.length; i++) {
49
- totalLength += U32_BYTE_LENGTH + (values[i] as Uint8Array).length;
50
- }
51
-
52
- return totalLength;
53
- }
54
-
55
- public writeU8(value: u8): void {
56
- if (value > 255) throw new Error('u8 value is too large.');
57
-
58
- this.allocSafe(U8_BYTE_LENGTH);
59
- this.buffer.setUint8(this.currentOffset++, value);
60
- }
61
-
62
- public writeU16(value: u16, be: boolean = true): void {
63
- if (value > 65535) throw new Error('u16 value is too large.');
64
-
65
- this.allocSafe(U16_BYTE_LENGTH);
66
- this.buffer.setUint16(this.currentOffset, value, !be);
67
- this.currentOffset += 2;
68
- }
69
-
70
- public writeU32(value: u32, be: boolean = true): void {
71
- if (value > 4294967295) throw new Error('u32 value is too large.');
72
-
73
- this.allocSafe(U32_BYTE_LENGTH);
74
- this.buffer.setUint32(this.currentOffset, value, !be);
75
- this.currentOffset += 4;
76
- }
77
-
78
- public writeU64(value: u64, be: boolean = true): void {
79
- if (value > 18446744073709551615n) throw new Error('u64 value is too large.');
80
-
81
- this.allocSafe(U64_BYTE_LENGTH);
82
- this.buffer.setBigUint64(this.currentOffset, value, !be);
83
- this.currentOffset += 8;
84
- }
85
-
86
- /** Writes a signed 8-bit integer. */
87
- public writeI8(value: i8): void {
88
- if (value < -128 || value > 127) throw new Error('i8 value is out of range.');
89
-
90
- this.allocSafe(I8_BYTE_LENGTH);
91
- this.buffer.setInt8(this.currentOffset, value);
92
- this.currentOffset += I8_BYTE_LENGTH;
93
- }
94
-
95
- /** Writes a signed 16-bit integer. By default big-endian (be = true). */
96
- public writeI16(value: i16, be: boolean = true): void {
97
- if (value < -32768 || value > 32767) throw new Error('i16 value is out of range.');
98
-
99
- this.allocSafe(I16_BYTE_LENGTH);
100
- this.buffer.setInt16(this.currentOffset, value, !be);
101
- this.currentOffset += I16_BYTE_LENGTH;
102
- }
103
-
104
- /** Writes a signed 32-bit integer. By default big-endian (be = true). */
105
- public writeI32(value: i32, be: boolean = true): void {
106
- if (value < -2147483648 || value > 2147483647)
107
- throw new Error('i32 value is out of range.');
108
-
109
- this.allocSafe(I32_BYTE_LENGTH);
110
- this.buffer.setInt32(this.currentOffset, value, !be);
111
- this.currentOffset += I32_BYTE_LENGTH;
112
- }
113
-
114
- /** Writes a signed 64-bit integer. By default big-endian (be = true). */
115
- public writeI64(value: i64, be: boolean = true): void {
116
- if (value < -9223372036854775808n || value > 9223372036854775807n) {
117
- throw new Error('i64 value is out of range.');
118
- }
119
-
120
- this.allocSafe(I64_BYTE_LENGTH);
121
- this.buffer.setBigInt64(this.currentOffset, value, !be);
122
- this.currentOffset += I64_BYTE_LENGTH;
123
- }
124
-
125
- public writeSelector(value: Selector): void {
126
- this.writeU32(value, true);
127
- }
128
-
129
- public writeBoolean(value: boolean): void {
130
- this.writeU8(value ? 1 : 0);
131
- }
132
-
133
- public writeI128(bigIntValue: bigint, be: boolean = true): void {
134
- if (
135
- bigIntValue > 170141183460469231731687303715884105727n ||
136
- bigIntValue < -170141183460469231731687303715884105728n
137
- ) {
138
- throw new Error('i128 value is too large.');
139
- }
140
-
141
- this.allocSafe(I128_BYTE_LENGTH);
142
-
143
- const bytes = bigIntToBytes(bigIntValue, I128_BYTE_LENGTH);
144
- if (bytes.byteLength !== I128_BYTE_LENGTH) {
145
- throw new Error(`Invalid i128 value: ${bigIntValue}`);
146
- }
147
-
148
- if (be) {
149
- for (let i = 0; i < bytes.byteLength; i++) {
150
- this.writeU8(bytes[i] as number);
151
- }
152
- } else {
153
- for (let i = bytes.byteLength - 1; i >= 0; i--) {
154
- this.writeU8(bytes[i] as number);
155
- }
156
- }
157
- }
158
-
159
- public writeU256(bigIntValue: bigint, be: boolean = true): void {
160
- if (
161
- bigIntValue >
162
- 115792089237316195423570985008687907853269984665640564039457584007913129639935n ||
163
- bigIntValue < 0n
164
- ) {
165
- throw new Error('u256 value is too large or negative.');
166
- }
167
-
168
- this.allocSafe(U256_BYTE_LENGTH);
169
-
170
- const bytes = bigIntToBytes(bigIntValue);
171
- if (bytes.byteLength !== U256_BYTE_LENGTH) {
172
- throw new Error(`Invalid u256 value: ${bigIntValue}`);
173
- }
174
-
175
- if (be) {
176
- for (let i = 0; i < bytes.byteLength; i++) {
177
- this.writeU8(bytes[i] as number);
178
- }
179
- } else {
180
- for (let i = bytes.byteLength - 1; i >= 0; i--) {
181
- this.writeU8(bytes[i] as number);
182
- }
183
- }
184
- }
185
-
186
- public writeU128(bigIntValue: bigint, be: boolean = true): void {
187
- if (bigIntValue > 340282366920938463463374607431768211455n || bigIntValue < 0n) {
188
- throw new Error('u128 value is too large or negative.');
189
- }
190
-
191
- this.allocSafe(U128_BYTE_LENGTH);
192
-
193
- const bytes = bigIntToBytes(bigIntValue, U128_BYTE_LENGTH);
194
- if (bytes.byteLength !== U128_BYTE_LENGTH) {
195
- throw new Error(`Invalid u128 value: ${bigIntValue}`);
196
- }
197
-
198
- if (be) {
199
- for (let i = 0; i < bytes.byteLength; i++) {
200
- this.writeU8(bytes[i] as number);
201
- }
202
- } else {
203
- for (let i = bytes.byteLength - 1; i >= 0; i--) {
204
- this.writeU8(bytes[i] as number);
205
- }
206
- }
207
- }
208
-
209
- public writeBytes(value: Uint8Array): void {
210
- this.allocSafe(value.byteLength);
211
-
212
- for (let i = 0; i < value.byteLength; i++) {
213
- this.writeU8(value[i] as number);
214
- }
215
- }
216
-
217
- public writeString(value: string): void {
218
- const encoder = new TextEncoder();
219
- const bytes = encoder.encode(value);
220
-
221
- this.allocSafe(bytes.length);
222
- this.writeBytes(bytes);
223
- }
224
-
225
- public writeStringWithLength(value: string): void {
226
- const encoder = new TextEncoder();
227
- const bytes = encoder.encode(value);
228
-
229
- this.allocSafe(U32_BYTE_LENGTH + bytes.length);
230
- this.writeU32(bytes.length);
231
- this.writeBytes(bytes);
232
- }
233
-
234
- public getBuffer(clear: boolean = true): Uint8Array {
235
- const buf = new Uint8Array(this.buffer.byteLength);
236
- for (let i: u32 = 0; i < this.buffer.byteLength; i++) {
237
- buf[i] = this.buffer.getUint8(i);
238
- }
239
-
240
- if (clear) this.clear();
241
-
242
- return buf;
243
- }
244
-
245
- public reset(): void {
246
- this.currentOffset = 0;
247
- this.buffer = this.getDefaultBuffer(4);
248
- }
249
-
250
- public toBytesReader(): BinaryReader {
251
- return new BinaryReader(this.getBuffer());
252
- }
253
-
254
- public getOffset(): u32 {
255
- return this.currentOffset;
256
- }
257
-
258
- public setOffset(offset: u32): void {
259
- this.currentOffset = offset;
260
- }
261
-
262
- public clear(): void {
263
- this.currentOffset = 0;
264
- this.buffer = this.getDefaultBuffer();
265
- }
266
-
267
- public [Symbol.dispose](): void {
268
- this.clear();
269
- }
270
-
271
- public allocSafe(size: u32): void {
272
- if (this.currentOffset + size > this.buffer.byteLength) {
273
- this.resize(size);
274
- }
275
- }
276
-
277
- public writeBytesWithLength(value: Uint8Array): void {
278
- this.writeU32(value.length);
279
- this.writeBytes(value);
280
- }
281
-
282
- public writeArrayOfBuffer(values: Uint8Array[], be: boolean = true): void {
283
- const totalLength = BinaryWriter.estimateArrayOfBufferLength(values);
284
-
285
- this.allocSafe(totalLength);
286
- this.writeU16(values.length, be);
287
-
288
- for (let i = 0; i < values.length; i++) {
289
- this.writeU32((values[i] as Uint8Array).length, be);
290
- this.writeBytes(values[i] as Uint8Array);
291
- }
292
- }
293
-
294
- public writeU32Array(value: u32[], be: boolean = true): void {
295
- if (value.length > 65535) throw new Error('Array size is too large');
296
-
297
- this.writeU16(value.length, be);
298
-
299
- for (let i = 0; i < value.length; i++) {
300
- this.writeU32(value[i] as u32, be);
301
- }
302
- }
303
-
304
- public writeU256Array(value: bigint[], be: boolean = true): void {
305
- if (value.length > 65535) throw new Error('Array size is too large');
306
-
307
- this.writeU16(value.length, be);
308
-
309
- for (let i = 0; i < value.length; i++) {
310
- this.writeU256(value[i] as bigint, be);
311
- }
312
- }
313
-
314
- public writeU128Array(value: bigint[], be: boolean = true): void {
315
- if (value.length > 65535) throw new Error('Array size is too large');
316
-
317
- this.writeU16(value.length, be);
318
- for (let i = 0; i < value.length; i++) {
319
- this.writeU128(value[i] as bigint, be);
320
- }
321
- }
322
-
323
- public writeStringArray(value: string[]): void {
324
- if (value.length > 65535) throw new Error('Array size is too large');
325
-
326
- this.writeU16(value.length);
327
-
328
- for (let i = 0; i < value.length; i++) {
329
- this.writeStringWithLength(value[i] as string);
330
- }
331
- }
332
-
333
- public writeU16Array(value: u16[], be: boolean = true): void {
334
- if (value.length > 65535) throw new Error('Array size is too large');
335
-
336
- this.writeU16(value.length, be);
337
-
338
- for (let i = 0; i < value.length; i++) {
339
- this.writeU16(value[i] as u16, be);
340
- }
341
- }
342
-
343
- public writeU8Array(value: u8[]): void {
344
- if (value.length > 65535) throw new Error('Array size is too large');
345
-
346
- this.writeU16(value.length);
347
-
348
- for (let i = 0; i < value.length; i++) {
349
- this.writeU8(value[i] as u8);
350
- }
351
- }
352
-
353
- public writeU64Array(value: bigint[], be: boolean = true): void {
354
- if (value.length > 65535) throw new Error('Array size is too large');
355
-
356
- this.writeU16(value.length, be);
357
-
358
- for (let i = 0; i < value.length; i++) {
359
- this.writeU64(value[i] as bigint, be);
360
- }
361
- }
362
-
363
- public writeBytesArray(value: Uint8Array[]): void {
364
- if (value.length > 65535) throw new Error('Array size is too large');
365
-
366
- this.writeU16(value.length);
367
-
368
- for (let i = 0; i < value.length; i++) {
369
- this.writeBytesWithLength(value[i] as Uint8Array);
370
- }
371
- }
372
-
373
- private resize(size: u32): void {
374
- const buf: Uint8Array = new Uint8Array(this.buffer.byteLength + size);
375
- for (let i: number = 0; i < this.buffer.byteLength; i++) {
376
- buf[i] = this.buffer.getUint8(i);
377
- }
378
-
379
- this.buffer = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
380
- }
381
-
382
- private getDefaultBuffer(length: number = 0): DataView {
383
- return new DataView(new ArrayBuffer(length));
384
- }
385
- }
1
+ import {
2
+ I128_BYTE_LENGTH,
3
+ I16_BYTE_LENGTH,
4
+ I32_BYTE_LENGTH,
5
+ I64_BYTE_LENGTH,
6
+ I8_BYTE_LENGTH,
7
+ U128_BYTE_LENGTH,
8
+ U16_BYTE_LENGTH,
9
+ U256_BYTE_LENGTH,
10
+ U32_BYTE_LENGTH,
11
+ U64_BYTE_LENGTH,
12
+ U8_BYTE_LENGTH,
13
+ } from './lengths.js';
14
+ import type { i16, i32, i64, i8, Selector, u16, u32, u64, u8 } from './types.js';
15
+ import { BinaryReader } from './BinaryReader.js';
16
+
17
+ /** Encodes a non-negative bigint into a big-endian byte array of exactly `length` bytes. */
18
+ function bigIntToBytes(value: bigint, length: number = U256_BYTE_LENGTH): Uint8Array {
19
+ if (value < 0n) {
20
+ throw new RangeError('Value cannot be negative');
21
+ }
22
+
23
+ const hex = value.toString(16).padStart(length * 2, '0');
24
+ if (hex.length > length * 2) {
25
+ throw new RangeError(`Value exceeds ${length}-byte range`);
26
+ }
27
+
28
+ const out = new Uint8Array(length);
29
+ for (let i = 0; i < length; i++) {
30
+ out[i] = parseInt(hex.substring(i * 2, i * 2 + 2), 16);
31
+ }
32
+
33
+ return out;
34
+ }
35
+
36
+ export class BinaryWriter implements Disposable {
37
+ private currentOffset: u32 = 0;
38
+ private buffer: DataView;
39
+
40
+ constructor(length: number = 0) {
41
+ this.buffer = this.getDefaultBuffer(length);
42
+ }
43
+
44
+ public static estimateArrayOfBufferLength(values: Uint8Array[]): u32 {
45
+ if (values.length > 65535) throw new Error('Array size is too large');
46
+ let totalLength: u32 = U16_BYTE_LENGTH;
47
+
48
+ for (let i = 0; i < values.length; i++) {
49
+ totalLength += U32_BYTE_LENGTH + (values[i] as Uint8Array).length;
50
+ }
51
+
52
+ return totalLength;
53
+ }
54
+
55
+ public writeU8(value: u8): void {
56
+ if (value > 255) throw new Error('u8 value is too large.');
57
+
58
+ this.allocSafe(U8_BYTE_LENGTH);
59
+ this.buffer.setUint8(this.currentOffset++, value);
60
+ }
61
+
62
+ public writeU16(value: u16, be: boolean = true): void {
63
+ if (value > 65535) throw new Error('u16 value is too large.');
64
+
65
+ this.allocSafe(U16_BYTE_LENGTH);
66
+ this.buffer.setUint16(this.currentOffset, value, !be);
67
+ this.currentOffset += 2;
68
+ }
69
+
70
+ public writeU32(value: u32, be: boolean = true): void {
71
+ if (value > 4294967295) throw new Error('u32 value is too large.');
72
+
73
+ this.allocSafe(U32_BYTE_LENGTH);
74
+ this.buffer.setUint32(this.currentOffset, value, !be);
75
+ this.currentOffset += 4;
76
+ }
77
+
78
+ public writeU64(value: u64, be: boolean = true): void {
79
+ if (value > 18446744073709551615n) throw new Error('u64 value is too large.');
80
+
81
+ this.allocSafe(U64_BYTE_LENGTH);
82
+ this.buffer.setBigUint64(this.currentOffset, value, !be);
83
+ this.currentOffset += 8;
84
+ }
85
+
86
+ /** Writes a signed 8-bit integer. */
87
+ public writeI8(value: i8): void {
88
+ if (value < -128 || value > 127) throw new Error('i8 value is out of range.');
89
+
90
+ this.allocSafe(I8_BYTE_LENGTH);
91
+ this.buffer.setInt8(this.currentOffset, value);
92
+ this.currentOffset += I8_BYTE_LENGTH;
93
+ }
94
+
95
+ /** Writes a signed 16-bit integer. By default big-endian (be = true). */
96
+ public writeI16(value: i16, be: boolean = true): void {
97
+ if (value < -32768 || value > 32767) throw new Error('i16 value is out of range.');
98
+
99
+ this.allocSafe(I16_BYTE_LENGTH);
100
+ this.buffer.setInt16(this.currentOffset, value, !be);
101
+ this.currentOffset += I16_BYTE_LENGTH;
102
+ }
103
+
104
+ /** Writes a signed 32-bit integer. By default big-endian (be = true). */
105
+ public writeI32(value: i32, be: boolean = true): void {
106
+ if (value < -2147483648 || value > 2147483647)
107
+ throw new Error('i32 value is out of range.');
108
+
109
+ this.allocSafe(I32_BYTE_LENGTH);
110
+ this.buffer.setInt32(this.currentOffset, value, !be);
111
+ this.currentOffset += I32_BYTE_LENGTH;
112
+ }
113
+
114
+ /** Writes a signed 64-bit integer. By default big-endian (be = true). */
115
+ public writeI64(value: i64, be: boolean = true): void {
116
+ if (value < -9223372036854775808n || value > 9223372036854775807n) {
117
+ throw new Error('i64 value is out of range.');
118
+ }
119
+
120
+ this.allocSafe(I64_BYTE_LENGTH);
121
+ this.buffer.setBigInt64(this.currentOffset, value, !be);
122
+ this.currentOffset += I64_BYTE_LENGTH;
123
+ }
124
+
125
+ public writeSelector(value: Selector): void {
126
+ this.writeU32(value, true);
127
+ }
128
+
129
+ public writeBoolean(value: boolean): void {
130
+ this.writeU8(value ? 1 : 0);
131
+ }
132
+
133
+ public writeI128(bigIntValue: bigint, be: boolean = true): void {
134
+ if (
135
+ bigIntValue > 170141183460469231731687303715884105727n ||
136
+ bigIntValue < -170141183460469231731687303715884105728n
137
+ ) {
138
+ throw new Error('i128 value is too large.');
139
+ }
140
+
141
+ this.allocSafe(I128_BYTE_LENGTH);
142
+
143
+ const bytes = bigIntToBytes(bigIntValue, I128_BYTE_LENGTH);
144
+ if (bytes.byteLength !== I128_BYTE_LENGTH) {
145
+ throw new Error(`Invalid i128 value: ${bigIntValue}`);
146
+ }
147
+
148
+ if (be) {
149
+ for (let i = 0; i < bytes.byteLength; i++) {
150
+ this.writeU8(bytes[i] as number);
151
+ }
152
+ } else {
153
+ for (let i = bytes.byteLength - 1; i >= 0; i--) {
154
+ this.writeU8(bytes[i] as number);
155
+ }
156
+ }
157
+ }
158
+
159
+ public writeU256(bigIntValue: bigint, be: boolean = true): void {
160
+ if (
161
+ bigIntValue >
162
+ 115792089237316195423570985008687907853269984665640564039457584007913129639935n ||
163
+ bigIntValue < 0n
164
+ ) {
165
+ throw new Error('u256 value is too large or negative.');
166
+ }
167
+
168
+ this.allocSafe(U256_BYTE_LENGTH);
169
+
170
+ const bytes = bigIntToBytes(bigIntValue);
171
+ if (bytes.byteLength !== U256_BYTE_LENGTH) {
172
+ throw new Error(`Invalid u256 value: ${bigIntValue}`);
173
+ }
174
+
175
+ if (be) {
176
+ for (let i = 0; i < bytes.byteLength; i++) {
177
+ this.writeU8(bytes[i] as number);
178
+ }
179
+ } else {
180
+ for (let i = bytes.byteLength - 1; i >= 0; i--) {
181
+ this.writeU8(bytes[i] as number);
182
+ }
183
+ }
184
+ }
185
+
186
+ public writeU128(bigIntValue: bigint, be: boolean = true): void {
187
+ if (bigIntValue > 340282366920938463463374607431768211455n || bigIntValue < 0n) {
188
+ throw new Error('u128 value is too large or negative.');
189
+ }
190
+
191
+ this.allocSafe(U128_BYTE_LENGTH);
192
+
193
+ const bytes = bigIntToBytes(bigIntValue, U128_BYTE_LENGTH);
194
+ if (bytes.byteLength !== U128_BYTE_LENGTH) {
195
+ throw new Error(`Invalid u128 value: ${bigIntValue}`);
196
+ }
197
+
198
+ if (be) {
199
+ for (let i = 0; i < bytes.byteLength; i++) {
200
+ this.writeU8(bytes[i] as number);
201
+ }
202
+ } else {
203
+ for (let i = bytes.byteLength - 1; i >= 0; i--) {
204
+ this.writeU8(bytes[i] as number);
205
+ }
206
+ }
207
+ }
208
+
209
+ public writeBytes(value: Uint8Array): void {
210
+ this.allocSafe(value.byteLength);
211
+
212
+ for (let i = 0; i < value.byteLength; i++) {
213
+ this.writeU8(value[i] as number);
214
+ }
215
+ }
216
+
217
+ public writeString(value: string): void {
218
+ const encoder = new TextEncoder();
219
+ const bytes = encoder.encode(value);
220
+
221
+ this.allocSafe(bytes.length);
222
+ this.writeBytes(bytes);
223
+ }
224
+
225
+ public writeStringWithLength(value: string): void {
226
+ const encoder = new TextEncoder();
227
+ const bytes = encoder.encode(value);
228
+
229
+ this.allocSafe(U32_BYTE_LENGTH + bytes.length);
230
+ this.writeU32(bytes.length);
231
+ this.writeBytes(bytes);
232
+ }
233
+
234
+ public getBuffer(clear: boolean = true): Uint8Array {
235
+ const buf = new Uint8Array(this.buffer.byteLength);
236
+ for (let i: u32 = 0; i < this.buffer.byteLength; i++) {
237
+ buf[i] = this.buffer.getUint8(i);
238
+ }
239
+
240
+ if (clear) this.clear();
241
+
242
+ return buf;
243
+ }
244
+
245
+ public reset(): void {
246
+ this.currentOffset = 0;
247
+ this.buffer = this.getDefaultBuffer(4);
248
+ }
249
+
250
+ public toBytesReader(): BinaryReader {
251
+ return new BinaryReader(this.getBuffer());
252
+ }
253
+
254
+ public getOffset(): u32 {
255
+ return this.currentOffset;
256
+ }
257
+
258
+ public setOffset(offset: u32): void {
259
+ this.currentOffset = offset;
260
+ }
261
+
262
+ public clear(): void {
263
+ this.currentOffset = 0;
264
+ this.buffer = this.getDefaultBuffer();
265
+ }
266
+
267
+ public [Symbol.dispose](): void {
268
+ this.clear();
269
+ }
270
+
271
+ public allocSafe(size: u32): void {
272
+ if (this.currentOffset + size > this.buffer.byteLength) {
273
+ this.resize(size);
274
+ }
275
+ }
276
+
277
+ public writeBytesWithLength(value: Uint8Array): void {
278
+ this.writeU32(value.length);
279
+ this.writeBytes(value);
280
+ }
281
+
282
+ public writeArrayOfBuffer(values: Uint8Array[], be: boolean = true): void {
283
+ const totalLength = BinaryWriter.estimateArrayOfBufferLength(values);
284
+
285
+ this.allocSafe(totalLength);
286
+ this.writeU16(values.length, be);
287
+
288
+ for (let i = 0; i < values.length; i++) {
289
+ this.writeU32((values[i] as Uint8Array).length, be);
290
+ this.writeBytes(values[i] as Uint8Array);
291
+ }
292
+ }
293
+
294
+ public writeU32Array(value: u32[], be: boolean = true): void {
295
+ if (value.length > 65535) throw new Error('Array size is too large');
296
+
297
+ this.writeU16(value.length, be);
298
+
299
+ for (let i = 0; i < value.length; i++) {
300
+ this.writeU32(value[i] as u32, be);
301
+ }
302
+ }
303
+
304
+ public writeU256Array(value: bigint[], be: boolean = true): void {
305
+ if (value.length > 65535) throw new Error('Array size is too large');
306
+
307
+ this.writeU16(value.length, be);
308
+
309
+ for (let i = 0; i < value.length; i++) {
310
+ this.writeU256(value[i] as bigint, be);
311
+ }
312
+ }
313
+
314
+ public writeU128Array(value: bigint[], be: boolean = true): void {
315
+ if (value.length > 65535) throw new Error('Array size is too large');
316
+
317
+ this.writeU16(value.length, be);
318
+ for (let i = 0; i < value.length; i++) {
319
+ this.writeU128(value[i] as bigint, be);
320
+ }
321
+ }
322
+
323
+ public writeStringArray(value: string[]): void {
324
+ if (value.length > 65535) throw new Error('Array size is too large');
325
+
326
+ this.writeU16(value.length);
327
+
328
+ for (let i = 0; i < value.length; i++) {
329
+ this.writeStringWithLength(value[i] as string);
330
+ }
331
+ }
332
+
333
+ public writeU16Array(value: u16[], be: boolean = true): void {
334
+ if (value.length > 65535) throw new Error('Array size is too large');
335
+
336
+ this.writeU16(value.length, be);
337
+
338
+ for (let i = 0; i < value.length; i++) {
339
+ this.writeU16(value[i] as u16, be);
340
+ }
341
+ }
342
+
343
+ public writeU8Array(value: u8[]): void {
344
+ if (value.length > 65535) throw new Error('Array size is too large');
345
+
346
+ this.writeU16(value.length);
347
+
348
+ for (let i = 0; i < value.length; i++) {
349
+ this.writeU8(value[i] as u8);
350
+ }
351
+ }
352
+
353
+ public writeU64Array(value: bigint[], be: boolean = true): void {
354
+ if (value.length > 65535) throw new Error('Array size is too large');
355
+
356
+ this.writeU16(value.length, be);
357
+
358
+ for (let i = 0; i < value.length; i++) {
359
+ this.writeU64(value[i] as bigint, be);
360
+ }
361
+ }
362
+
363
+ public writeBytesArray(value: Uint8Array[]): void {
364
+ if (value.length > 65535) throw new Error('Array size is too large');
365
+
366
+ this.writeU16(value.length);
367
+
368
+ for (let i = 0; i < value.length; i++) {
369
+ this.writeBytesWithLength(value[i] as Uint8Array);
370
+ }
371
+ }
372
+
373
+ private resize(size: u32): void {
374
+ const buf: Uint8Array = new Uint8Array(this.buffer.byteLength + size);
375
+ for (let i: number = 0; i < this.buffer.byteLength; i++) {
376
+ buf[i] = this.buffer.getUint8(i);
377
+ }
378
+
379
+ this.buffer = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
380
+ }
381
+
382
+ private getDefaultBuffer(length: number = 0): DataView {
383
+ return new DataView(new ArrayBuffer(length));
384
+ }
385
+ }