toiljs 0.0.14 → 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 (225) 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 +2926 -191
  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/head/metadata.d.ts +3 -1
  28. package/build/client/head/metadata.js +8 -0
  29. package/build/client/index.d.ts +4 -4
  30. package/build/client/index.js +2 -2
  31. package/build/client/navigation/navigation.d.ts +2 -0
  32. package/build/client/navigation/navigation.js +9 -1
  33. package/build/client/navigation/prefetch.d.ts +1 -0
  34. package/build/client/navigation/prefetch.js +35 -0
  35. package/build/client/routing/Router.js +1 -1
  36. package/build/client/routing/hooks.js +6 -2
  37. package/build/client/routing/loader.d.ts +25 -0
  38. package/build/client/routing/loader.js +53 -7
  39. package/build/client/routing/mount.js +4 -3
  40. package/build/compiler/.tsbuildinfo +1 -1
  41. package/build/compiler/config.d.ts +18 -0
  42. package/build/compiler/config.js +8 -0
  43. package/build/compiler/docs.js +16 -16
  44. package/build/compiler/generate.js +3 -0
  45. package/build/compiler/index.d.ts +2 -2
  46. package/build/compiler/index.js +3 -1
  47. package/build/compiler/plugin.js +156 -0
  48. package/build/compiler/prerender.d.ts +1 -0
  49. package/build/compiler/prerender.js +2 -1
  50. package/build/compiler/seo.d.ts +2 -2
  51. package/build/compiler/seo.js +8 -6
  52. package/build/compiler/ssg.d.ts +5 -0
  53. package/build/compiler/ssg.js +121 -0
  54. package/build/io/.tsbuildinfo +1 -1
  55. package/build/logger/.tsbuildinfo +1 -1
  56. package/build/shared/.tsbuildinfo +1 -1
  57. package/eslint.config.js +48 -48
  58. package/examples/basic/client/404.tsx +11 -11
  59. package/examples/basic/client/components/.gitkeep +1 -1
  60. package/examples/basic/client/global-error.tsx +13 -13
  61. package/examples/basic/client/layout.tsx +25 -25
  62. package/examples/basic/client/public/images/.gitkeep +1 -1
  63. package/examples/basic/client/public/images/logo.svg +36 -36
  64. package/examples/basic/client/public/robots.txt +2 -2
  65. package/examples/basic/client/routes/docs/[...slug].tsx +12 -12
  66. package/examples/basic/client/routes/features/error/error.tsx +16 -16
  67. package/examples/basic/client/routes/features/template/b.tsx +14 -14
  68. package/examples/basic/client/routes/files/[[...slug]].tsx +21 -21
  69. package/examples/basic/client/routes/gallery/layout.tsx +13 -13
  70. package/examples/basic/client/routes/io.tsx +24 -24
  71. package/examples/basic/client/routes/loader-demo/loading.tsx +13 -13
  72. package/examples/basic/client/routes/search.tsx +61 -61
  73. package/examples/basic/client/toil.tsx +5 -5
  74. package/package.json +155 -147
  75. package/presets/eslint.js +88 -88
  76. package/presets/no-uint8array-tostring.js +200 -200
  77. package/presets/prettier.json +18 -18
  78. package/presets/tsconfig.json +37 -37
  79. package/src/backend/index.ts +160 -160
  80. package/src/cli/proc.ts +50 -50
  81. package/src/cli/updates.ts +69 -69
  82. package/src/cli/validate.ts +31 -31
  83. package/src/client/channel/channel.ts +146 -146
  84. package/src/client/components/Form.tsx +65 -65
  85. package/src/client/components/Script.tsx +113 -113
  86. package/src/client/components/Slot.tsx +21 -21
  87. package/src/client/dev/devtools.tsx +973 -0
  88. package/src/client/dev/error-overlay.tsx +30 -4
  89. package/src/client/head/head.ts +167 -167
  90. package/src/client/head/metadata.ts +19 -1
  91. package/src/client/index.ts +19 -9
  92. package/src/client/navigation/NavLink.tsx +86 -86
  93. package/src/client/navigation/navigation.ts +25 -5
  94. package/src/client/navigation/prefetch.ts +169 -130
  95. package/src/client/navigation/scroll.ts +53 -53
  96. package/src/client/routing/Router.tsx +8 -2
  97. package/src/client/routing/action.ts +122 -122
  98. package/src/client/routing/error-boundary.tsx +43 -43
  99. package/src/client/routing/hooks.ts +21 -6
  100. package/src/client/routing/loader.ts +325 -225
  101. package/src/client/routing/match.ts +47 -47
  102. package/src/client/routing/mount.tsx +54 -52
  103. package/src/client/routing/params-context.ts +10 -10
  104. package/src/client/routing/slot-context.ts +7 -7
  105. package/src/client/search/search.ts +189 -189
  106. package/src/client/search/use-page-search.ts +73 -73
  107. package/src/client/types.ts +73 -73
  108. package/src/compiler/config.ts +47 -1
  109. package/src/compiler/docs.ts +228 -228
  110. package/src/compiler/generate.ts +394 -391
  111. package/src/compiler/index.ts +64 -54
  112. package/src/compiler/pages.ts +70 -70
  113. package/src/compiler/plugin.ts +170 -2
  114. package/src/compiler/prerender.ts +5 -1
  115. package/src/compiler/seo.ts +23 -7
  116. package/src/compiler/ssg.ts +162 -0
  117. package/src/io/BinaryReader.ts +340 -340
  118. package/src/io/BinaryWriter.ts +385 -385
  119. package/src/io/FastMap.ts +127 -127
  120. package/src/io/index.ts +11 -11
  121. package/src/io/lengths.ts +14 -14
  122. package/src/io/types.ts +18 -18
  123. package/src/logger/index.ts +22 -22
  124. package/src/server/index.ts +10 -10
  125. package/src/server/main.ts +13 -13
  126. package/src/server/tsconfig.json +4 -4
  127. package/src/shared/index.ts +10 -10
  128. package/std/client/index.d.ts +15 -15
  129. package/std/client/package.json +3 -3
  130. package/test/assembly/example.spec.ts +7 -7
  131. package/test/channel.test.ts +21 -21
  132. package/test/dom/Link.test.tsx +47 -47
  133. package/test/dom/NavLink.test.tsx +37 -37
  134. package/test/dom/error-overlay.test.tsx +44 -44
  135. package/test/dom/loader.test.tsx +121 -121
  136. package/test/dom/navigation.test.ts +59 -59
  137. package/test/dom/revalidate.test.tsx +38 -38
  138. package/test/dom/route-head.test.tsx +78 -78
  139. package/test/dom/router-loading.test.tsx +44 -44
  140. package/test/dom/scroll.test.ts +56 -56
  141. package/test/dom/use-metadata.test.tsx +58 -0
  142. package/test/io.test.ts +93 -93
  143. package/test/navlink.test.ts +28 -28
  144. package/test/placeholder.test.ts +9 -9
  145. package/test/routes.test.ts +76 -76
  146. package/test/seo.test.ts +175 -164
  147. package/test/slot-layouts.test.ts +69 -69
  148. package/test/ssg.test.ts +36 -0
  149. package/test/update.test.ts +44 -44
  150. package/test/validate.test.ts +42 -42
  151. package/toil-routes.d.ts +7 -0
  152. package/toilconfig.json +30 -30
  153. package/tsconfig.backend.json +13 -13
  154. package/tsconfig.base.json +35 -35
  155. package/tsconfig.cli.json +13 -13
  156. package/tsconfig.client.json +14 -14
  157. package/tsconfig.compiler.json +13 -13
  158. package/tsconfig.io.json +12 -12
  159. package/tsconfig.json +22 -22
  160. package/tsconfig.logger.json +12 -12
  161. package/tsconfig.server.json +10 -10
  162. package/tsconfig.shared.json +12 -12
  163. package/vitest.config.ts +26 -26
  164. package/.idea/codeStyles/Project.xml +0 -54
  165. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  166. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  167. package/.idea/modules.xml +0 -8
  168. package/.idea/prettier.xml +0 -7
  169. package/.idea/toiljs.iml +0 -8
  170. package/.idea/vcs.xml +0 -6
  171. package/.toil/entry.tsx +0 -9
  172. package/.toil/index.html +0 -12
  173. package/.toil/routes.ts +0 -9
  174. package/build/cli/configure.d.ts +0 -16
  175. package/build/cli/configure.js +0 -272
  176. package/build/cli/create.d.ts +0 -16
  177. package/build/cli/create.js +0 -420
  178. package/build/cli/diagnostics.d.ts +0 -55
  179. package/build/cli/diagnostics.js +0 -333
  180. package/build/cli/doctor.d.ts +0 -6
  181. package/build/cli/doctor.js +0 -249
  182. package/build/cli/features.d.ts +0 -25
  183. package/build/cli/features.js +0 -107
  184. package/build/cli/index.d.ts +0 -2
  185. package/build/cli/proc.d.ts +0 -6
  186. package/build/cli/proc.js +0 -31
  187. package/build/cli/ui.d.ts +0 -9
  188. package/build/cli/ui.js +0 -75
  189. package/build/cli/update.d.ts +0 -7
  190. package/build/cli/update.js +0 -117
  191. package/build/cli/updates.d.ts +0 -10
  192. package/build/cli/updates.js +0 -45
  193. package/build/cli/validate.d.ts +0 -4
  194. package/build/cli/validate.js +0 -19
  195. package/build/client/Link.d.ts +0 -8
  196. package/build/client/Link.js +0 -44
  197. package/build/client/NavLink.d.ts +0 -14
  198. package/build/client/NavLink.js +0 -37
  199. package/build/client/Router.d.ts +0 -7
  200. package/build/client/Router.js +0 -55
  201. package/build/client/channel.d.ts +0 -23
  202. package/build/client/channel.js +0 -94
  203. package/build/client/error-boundary.d.ts +0 -16
  204. package/build/client/error-boundary.js +0 -19
  205. package/build/client/head.d.ts +0 -26
  206. package/build/client/head.js +0 -87
  207. package/build/client/hooks.d.ts +0 -17
  208. package/build/client/hooks.js +0 -48
  209. package/build/client/lazy.d.ts +0 -16
  210. package/build/client/lazy.js +0 -53
  211. package/build/client/match.d.ts +0 -2
  212. package/build/client/match.js +0 -32
  213. package/build/client/mount.d.ts +0 -2
  214. package/build/client/mount.js +0 -13
  215. package/build/client/navigation.d.ts +0 -13
  216. package/build/client/navigation.js +0 -97
  217. package/build/client/params-context.d.ts +0 -2
  218. package/build/client/params-context.js +0 -2
  219. package/build/client/prefetch.d.ts +0 -11
  220. package/build/client/prefetch.js +0 -100
  221. package/build/client/runtime.d.ts +0 -31
  222. package/build/client/runtime.js +0 -112
  223. package/build/client/scroll.d.ts +0 -8
  224. package/build/client/scroll.js +0 -36
  225. 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
+ }