@rotu/structview 0.6.1 → 0.7.0

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 (62) hide show
  1. package/README.md +3 -3
  2. package/esm/_dnt.test_shims.d.ts.map +1 -0
  3. package/esm/bigendian.d.ts.map +1 -0
  4. package/esm/bigendian_test.d.ts.map +1 -0
  5. package/esm/deps/jsr.io/@std/assert/1.0.15/almost_equals.d.ts.map +1 -0
  6. package/esm/deps/jsr.io/@std/assert/1.0.15/array_includes.d.ts.map +1 -0
  7. package/esm/deps/jsr.io/@std/assert/1.0.15/assert.d.ts.map +1 -0
  8. package/esm/deps/jsr.io/@std/assert/1.0.15/assertion_error.d.ts.map +1 -0
  9. package/esm/deps/jsr.io/@std/assert/1.0.15/equal.d.ts.map +1 -0
  10. package/esm/deps/jsr.io/@std/assert/1.0.15/equals.d.ts.map +1 -0
  11. package/esm/deps/jsr.io/@std/assert/1.0.15/exists.d.ts.map +1 -0
  12. package/esm/deps/jsr.io/@std/assert/1.0.15/fail.d.ts.map +1 -0
  13. package/esm/deps/jsr.io/@std/assert/1.0.15/false.d.ts.map +1 -0
  14. package/esm/deps/jsr.io/@std/assert/1.0.15/greater.d.ts.map +1 -0
  15. package/esm/deps/jsr.io/@std/assert/1.0.15/greater_or_equal.d.ts.map +1 -0
  16. package/esm/deps/jsr.io/@std/assert/1.0.15/instance_of.d.ts.map +1 -0
  17. package/esm/deps/jsr.io/@std/assert/1.0.15/is_error.d.ts.map +1 -0
  18. package/esm/deps/jsr.io/@std/assert/1.0.15/less.d.ts.map +1 -0
  19. package/esm/deps/jsr.io/@std/assert/1.0.15/less_or_equal.d.ts.map +1 -0
  20. package/esm/deps/jsr.io/@std/assert/1.0.15/match.d.ts.map +1 -0
  21. package/esm/deps/jsr.io/@std/assert/1.0.15/mod.d.ts.map +1 -0
  22. package/esm/deps/jsr.io/@std/assert/1.0.15/not_equals.d.ts.map +1 -0
  23. package/esm/deps/jsr.io/@std/assert/1.0.15/not_instance_of.d.ts.map +1 -0
  24. package/esm/deps/jsr.io/@std/assert/1.0.15/not_match.d.ts.map +1 -0
  25. package/esm/deps/jsr.io/@std/assert/1.0.15/not_strict_equals.d.ts.map +1 -0
  26. package/esm/deps/jsr.io/@std/assert/1.0.15/object_match.d.ts.map +1 -0
  27. package/esm/deps/jsr.io/@std/assert/1.0.15/rejects.d.ts.map +1 -0
  28. package/esm/deps/jsr.io/@std/assert/1.0.15/strict_equals.d.ts.map +1 -0
  29. package/esm/deps/jsr.io/@std/assert/1.0.15/string_includes.d.ts.map +1 -0
  30. package/esm/deps/jsr.io/@std/assert/1.0.15/throws.d.ts.map +1 -0
  31. package/esm/deps/jsr.io/@std/assert/1.0.15/unimplemented.d.ts.map +1 -0
  32. package/esm/deps/jsr.io/@std/assert/1.0.15/unreachable.d.ts.map +1 -0
  33. package/esm/deps/jsr.io/@std/internal/1.0.12/build_message.d.ts.map +1 -0
  34. package/esm/deps/jsr.io/@std/internal/1.0.12/diff.d.ts.map +1 -0
  35. package/esm/deps/jsr.io/@std/internal/1.0.12/diff_str.d.ts.map +1 -0
  36. package/esm/deps/jsr.io/@std/internal/1.0.12/format.d.ts.map +1 -0
  37. package/esm/deps/jsr.io/@std/internal/1.0.12/styles.d.ts.map +1 -0
  38. package/esm/deps/jsr.io/@std/internal/1.0.12/types.d.ts.map +1 -0
  39. package/esm/mod.d.ts +161 -0
  40. package/esm/mod.d.ts.map +1 -0
  41. package/esm/mod.js +378 -0
  42. package/esm/mod_test.d.ts.map +1 -0
  43. package/esm/package.json +3 -0
  44. package/package.json +14 -11
  45. package/.github/workflows/deno.yml +0 -32
  46. package/.github/workflows/publish.yml +0 -20
  47. package/.vscode/settings.json +0 -4
  48. package/_dist/bigendian.d.ts +0 -32
  49. package/_dist/bigendian.d.ts.map +0 -1
  50. package/_dist/mod.d.ts +0 -135
  51. package/_dist/mod.d.ts.map +0 -1
  52. package/bigendian.js +0 -122
  53. package/bigendian.js.map +0 -1
  54. package/bigendian.ts +0 -136
  55. package/bigendian_test.ts +0 -70
  56. package/deno.json +0 -18
  57. package/deno.lock +0 -23
  58. package/mod.js +0 -336
  59. package/mod.js.map +0 -1
  60. package/mod.ts +0 -487
  61. package/mod_bench.ts +0 -98
  62. package/mod_test.ts +0 -319
package/mod.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"mod.js","sources":["./mod.ts"],"names":[],"mappings":"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"}
package/mod.ts DELETED
@@ -1,487 +0,0 @@
1
- /**
2
- * Strongly typed classes for accessing binary data in a structured way
3
- * @module
4
- */
5
-
6
- const dataViewSymbol = Symbol.for("Struct.dataview")
7
- type AnyStruct = {
8
- get [dataViewSymbol](): DataView
9
- }
10
- // deno-lint-ignore no-explicit-any
11
- type Constructor<T> = { new (...args: any[]): T }
12
- // deno-lint-ignore no-explicit-any
13
- type AnyConstructor = Constructor<any>
14
-
15
- type SubclassWithProperties<
16
- Ctor extends Constructor<object>,
17
- Mixin,
18
- > =
19
- & { [K in keyof Ctor]: Ctor[K] }
20
- & {
21
- new (
22
- ...args: ConstructorParameters<Ctor>
23
- ): InstanceType<Ctor> & { -readonly [K in keyof Mixin]: Mixin[K] }
24
- }
25
-
26
- type TPropertyDescriptor<T> = {
27
- enumerable?: boolean
28
- configurable?: boolean
29
- get?(): T
30
- set?(t: T): undefined
31
- value?: T
32
- writable?: boolean
33
- }
34
-
35
- type MixinFromProps<Props extends object> = {
36
- [K in keyof Props]: Props[K] extends TPropertyDescriptor<infer V> ? V
37
- : unknown
38
- }
39
-
40
- /**
41
- * Get the underlying DataView of a struct
42
- * @param struct
43
- * @returns
44
- */
45
- export function structDataView(struct: AnyStruct): DataView {
46
- const result = struct[dataViewSymbol]
47
- if (!(result instanceof DataView)) {
48
- throw new TypeError("not a struct")
49
- }
50
- return struct[dataViewSymbol]
51
- }
52
- /**
53
- * Helper method to create a view of a contiguous subregion of a Struct's memory
54
- * @param struct
55
- * @param start byte offset to start
56
- * @param end byte offset of the end of the subrange
57
- * @returns region of the given struct.
58
- */
59
- function structBytes(struct: AnyStruct, start?: number, end?: number) {
60
- const dv = structDataView(struct)
61
- start ??= 0
62
- end ??= dv.byteLength
63
- console.assert(start <= end)
64
- console.assert(end <= dv.byteLength)
65
- return new Uint8Array(dv.buffer, dv.byteOffset + start, end - start)
66
- }
67
-
68
- /**
69
- * Type of a property descriptor for a struct
70
- */
71
- export type StructPropertyDescriptor<T> =
72
- & ThisType<AnyStruct>
73
- & TPropertyDescriptor<T>
74
-
75
- /**
76
- * Define a descriptor based on a dataview of the struct
77
- * @param fieldGetter function which, given a dataview, returns
78
- * @returns
79
- */
80
- export function fromDataView<Fn extends (dv: DataView) => unknown>(
81
- fieldGetter: Fn,
82
- ): StructPropertyDescriptor<ReturnType<Fn>> {
83
- return {
84
- enumerable: true,
85
- get() {
86
- const dv = this[dataViewSymbol]
87
- return fieldGetter(dv)
88
- },
89
- } as ThisType<Struct>
90
- }
91
-
92
- /**
93
- * Field for a 8-bit unsigned integer
94
- */
95
- export function u8(fieldOffset: number): StructPropertyDescriptor<number> {
96
- return {
97
- enumerable: true,
98
- get() {
99
- return structDataView(this).getUint8(fieldOffset)
100
- },
101
- set(value) {
102
- structDataView(this).setUint8(fieldOffset, value)
103
- },
104
- }
105
- }
106
- /**
107
- * Field for a little-endian 16-bit unsigned integer
108
- */
109
- export function u16(fieldOffset: number): StructPropertyDescriptor<number> {
110
- return {
111
- enumerable: true,
112
- get() {
113
- return structDataView(this).getUint16(fieldOffset, true)
114
- },
115
- set(value) {
116
- structDataView(this).setUint16(fieldOffset, value, true)
117
- },
118
- }
119
- }
120
- /**
121
- * Field for a little-endian 32-bit unsigned integer
122
- */
123
- export function u32(fieldOffset: number): StructPropertyDescriptor<number> {
124
- return {
125
- enumerable: true,
126
- get() {
127
- return structDataView(this).getUint32(fieldOffset, true)
128
- },
129
- set(value) {
130
- structDataView(this).setUint32(fieldOffset, value, true)
131
- },
132
- }
133
- }
134
- /**
135
- * Field for a little-endian 64-bit unsigned integer
136
- */
137
- export function u64(fieldOffset: number): StructPropertyDescriptor<bigint> {
138
- return {
139
- enumerable: true,
140
- get() {
141
- return structDataView(this).getBigUint64(fieldOffset, true)
142
- },
143
- set(value) {
144
- structDataView(this).setBigUint64(fieldOffset, value, true)
145
- },
146
- }
147
- }
148
- /**
149
- * Field for a little-endian 8-bit signed integer
150
- */
151
- export function i8(fieldOffset: number): StructPropertyDescriptor<number> {
152
- return {
153
- enumerable: true,
154
- get() {
155
- return structDataView(this).getInt8(fieldOffset)
156
- },
157
- set(value) {
158
- structDataView(this).setInt8(fieldOffset, value)
159
- },
160
- }
161
- }
162
- /**
163
- * Field for a little-endian 16-bit signed integer
164
- */
165
- export function i16(fieldOffset: number): StructPropertyDescriptor<number> {
166
- return {
167
- enumerable: true,
168
- get() {
169
- return structDataView(this).getInt16(fieldOffset, true)
170
- },
171
- set(value) {
172
- structDataView(this).setInt16(fieldOffset, value, true)
173
- },
174
- }
175
- }
176
- /**
177
- * Field for a little-endian 32-bit signed integer
178
- */
179
- export function i32(fieldOffset: number): StructPropertyDescriptor<number> {
180
- return {
181
- enumerable: true,
182
- get() {
183
- return structDataView(this).getInt32(fieldOffset, true)
184
- },
185
- set(value) {
186
- structDataView(this).setInt32(fieldOffset, value, true)
187
- },
188
- }
189
- }
190
- /**
191
- * Field for a little-endian 64-bit signed integer
192
- */
193
- export function i64(fieldOffset: number): StructPropertyDescriptor<bigint> {
194
- return {
195
- enumerable: true,
196
- get() {
197
- return structDataView(this).getBigInt64(fieldOffset, true)
198
- },
199
- set(value) {
200
- structDataView(this).setBigInt64(fieldOffset, value, true)
201
- },
202
- }
203
- }
204
-
205
- /**
206
- * Field for a little-endian 16-bit binary float (float16_t)
207
- */
208
- export function f16(fieldOffset: number): StructPropertyDescriptor<number> {
209
- return {
210
- enumerable: true,
211
- get() {
212
- return structDataView(this).getFloat16(fieldOffset, true)
213
- },
214
- set(value) {
215
- structDataView(this).setFloat16(fieldOffset, value, true)
216
- },
217
- }
218
- }
219
-
220
- /**
221
- * Field for a little-endian 32-bit binary float (float32_t)
222
- */
223
- export function f32(fieldOffset: number): StructPropertyDescriptor<number> {
224
- return {
225
- enumerable: true,
226
- get() {
227
- return structDataView(this).getFloat32(fieldOffset, true)
228
- },
229
- set(value) {
230
- structDataView(this).setFloat32(fieldOffset, value, true)
231
- },
232
- }
233
- }
234
-
235
- /**
236
- * Field for a little-endian 64-bit binary float (float64_t)
237
- */
238
- export function f64(fieldOffset: number): StructPropertyDescriptor<number> {
239
- return {
240
- enumerable: true,
241
- get() {
242
- return structDataView(this).getFloat64(fieldOffset, true)
243
- },
244
- set(value) {
245
- structDataView(this).setFloat64(fieldOffset, value, true)
246
- },
247
- }
248
- }
249
-
250
- /**
251
- * Field for a UTF-8 fixed-length string
252
- */
253
- export function string(
254
- fieldOffset: number,
255
- byteLength: number,
256
- ): StructPropertyDescriptor<string> {
257
- const TEXT_DECODER = new TextDecoder()
258
- const TEXT_ENCODER = new TextEncoder()
259
- return {
260
- enumerable: true,
261
- get() {
262
- const str = TEXT_DECODER.decode(
263
- structBytes(this, fieldOffset, fieldOffset + byteLength),
264
- )
265
- // trim all trailing null characters
266
- return str.replace(/\0+$/, "")
267
- },
268
- set(value) {
269
- const bytes = structBytes(
270
- this,
271
- fieldOffset,
272
- fieldOffset + byteLength,
273
- )
274
- bytes.fill(0)
275
- TEXT_ENCODER.encodeInto(value, bytes)
276
- },
277
- }
278
- }
279
-
280
- /**
281
- * Field for a boolean stored in a byte (0 = false, nonzero = true)
282
- * True will be stored as 1
283
- */
284
- export function bool(fieldOffset: number): StructPropertyDescriptor<boolean> {
285
- return {
286
- enumerable: true,
287
- get() {
288
- return Boolean(structDataView(this).getUint8(fieldOffset))
289
- },
290
- set(value) {
291
- structDataView(this).setUint8(fieldOffset, value ? 1 : 0)
292
- },
293
- }
294
- }
295
-
296
- type StructConstructor<T extends object> = {
297
- new (arg: {
298
- buffer: ArrayBufferLike
299
- byteOffset?: number
300
- byteLength?: number
301
- }): T
302
- }
303
-
304
- /**
305
- * Field for an embedded struct
306
- * @param ctor constructor for the inner struct
307
- * @param byteOffset where the inner struct starts relative to the outer struct
308
- * @param bytelength the length in bytes of the inner struct
309
- * @returns property descriptor for a struct
310
- */
311
- export function substruct<
312
- T extends object,
313
- >(
314
- ctor: StructConstructor<T>,
315
- byteOffset?: number,
316
- bytelength?: number,
317
- ): StructPropertyDescriptor<T> {
318
- return fromDataView(
319
- function (dv) {
320
- const offset2 = dv.byteOffset + (byteOffset ?? 0)
321
- const bytelength2 = bytelength ?? (dv.byteLength - (byteOffset ?? 0))
322
- return Reflect.construct(ctor, [{
323
- buffer: dv.buffer,
324
- byteOffset: offset2,
325
- byteLength: bytelength2,
326
- }])
327
- },
328
- )
329
- }
330
-
331
- /**
332
- * Base class for a structured binary object
333
- * Note there are no predeclared string-keyed properties - all property names are reserved for user-defined fields
334
- */
335
- export class Struct {
336
- [dataViewSymbol]: DataView
337
- get [Symbol.toStringTag](): string {
338
- return Struct.name
339
- }
340
- static toDataView(o: Struct): DataView {
341
- return o[dataViewSymbol]
342
- }
343
-
344
- /**
345
- * Create a new Struct
346
- * @param arg options for creating the struct.
347
- * If options has a `.buffer` property, we will use that as the backing memory (e.g. any TypedArray or DataView).
348
- * If options has no `.buffer` property but has a `.byteLength`, we will allocate a new buffer for the object.
349
- */
350
- constructor(
351
- arg:
352
- | {
353
- buffer: ArrayBufferLike
354
- byteOffset?: number
355
- byteLength?: number
356
- }
357
- | {
358
- buffer?: undefined
359
- byteOffset?: number
360
- byteLength: number
361
- },
362
- ) {
363
- if (typeof arg !== "object" || arg === null) {
364
- throw new TypeError("Expected argument to be an object")
365
- }
366
-
367
- Object.preventExtensions(this)
368
- if (arg.buffer) {
369
- this[dataViewSymbol] = new DataView(
370
- arg.buffer,
371
- arg.byteOffset,
372
- arg.byteLength,
373
- )
374
- } else if (typeof arg.byteLength === "number") {
375
- this[dataViewSymbol] = new DataView(
376
- new ArrayBuffer(arg.byteLength + (arg.byteOffset ?? 0)),
377
- arg.byteOffset,
378
- arg.byteLength,
379
- )
380
- } else {
381
- throw new TypeError(
382
- "Must provide either {buffer} or {byteLength}",
383
- )
384
- }
385
- }
386
- }
387
-
388
- /**
389
- * Subclass a type by adding the given property descriptors
390
- * @param ctor constructor for the base class
391
- * @param propertyDescriptors properties to add to subclass instances
392
- * @returns A new class, inheriting from the base class, with the new property descriptors added
393
- */
394
- function subclassWithProperties<
395
- const Ctor extends AnyConstructor,
396
- const Props extends PropertyDescriptorMap,
397
- >(
398
- ctor: Ctor,
399
- propertyDescriptors: Props,
400
- ): SubclassWithProperties<Ctor, MixinFromProps<Props>> {
401
- return (class extends ctor {
402
- static {
403
- Object.defineProperties(this.prototype, propertyDescriptors)
404
- }
405
- })
406
- }
407
-
408
- /**
409
- * Subclass struct by adding the given property descriptors
410
- * @param propertyDescriptors properties to add to subclass instances
411
- * @returns A new class, inheriting from `Struct`, with the new property descriptors added
412
- */
413
- export function defineStruct<const Props extends PropertyDescriptorMap>(
414
- propertyDescriptors: Props,
415
- ): SubclassWithProperties<typeof Struct, MixinFromProps<Props>> {
416
- return subclassWithProperties(Struct, propertyDescriptors)
417
- }
418
-
419
- /**
420
- * Create a new struct subclass for an array of structs
421
- * @param arrayOptions
422
- * @returns A new class, inheriting from `Struct` whose elements are statically typed structs
423
- */
424
- export function defineArray<Ctor extends StructConstructor<object>>(
425
- arrayOptions: {
426
- /** Constructor for an object view of each element*/
427
- struct: Ctor
428
- /** Number of bytes between the start of consecutive elements */
429
- byteStride: number
430
- /** Total number of elements in the array (not bytes). If omitted, the array length will depend on the size of its underlying buffer */
431
- length?: number
432
- },
433
- ): StructConstructor<
434
- {
435
- get length(): number
436
- element(i: number): InstanceType<Ctor>
437
- [i: number]: InstanceType<Ctor>
438
- } & Iterable<InstanceType<Ctor>>
439
- > {
440
- const { struct, byteStride, length } = arrayOptions
441
-
442
- // Define a subclass of Struct which translates array-like index access into element access
443
- // x[2] -> x.element(2)
444
- const ProxiedStruct = function (
445
- ...args: ConstructorParameters<typeof Struct>
446
- ) {
447
- return Reflect.construct(Struct, args, new.target)
448
- } as unknown as StructConstructor<Struct & { [i: number]: Ctor }>
449
-
450
- ProxiedStruct.prototype = new Proxy(Struct.prototype, {
451
- get(target, p, receiver) {
452
- if (typeof p === "string") {
453
- const i = parseInt(p)
454
- if (p === String(i)) {
455
- return receiver.element(i)
456
- }
457
- }
458
- return Reflect.get(target, p, receiver)
459
- },
460
- })
461
-
462
- class StructArray extends ProxiedStruct {
463
- #struct = struct
464
- #length = length
465
- #byteStride = byteStride
466
-
467
- get length() {
468
- if (typeof this.#length === "number") {
469
- return this.#length
470
- }
471
- return structDataView(this).byteLength / this.#byteStride
472
- }
473
- element(i: number) {
474
- const ctor = this.#struct
475
- return new ctor(
476
- structBytes(this, this.#byteStride * i, this.#byteStride * (i + 1)),
477
- )
478
- }
479
- *[Symbol.iterator]() {
480
- for (let i = 0; i < this.length; ++i) {
481
- yield this.element(i)
482
- }
483
- }
484
- }
485
- // deno-lint-ignore no-explicit-any
486
- return StructArray as any
487
- }
package/mod_bench.ts DELETED
@@ -1,98 +0,0 @@
1
- /**
2
- * Benchmark tests for struct packing and unpacking.
3
- * We don't care about being blazing fast - this is to make sure we're not doing anything *eggregiously slow*
4
- * @module
5
- */
6
-
7
- import { assertEquals } from "jsr:/@std/assert@1/equals"
8
- import { defineStruct, f32, f64, string, u16, u32, u8 } from "./mod.ts"
9
-
10
- const StructClass = defineStruct({
11
- x1: f32(0),
12
- x2: f64(4),
13
- x3: u32(12),
14
- x4: u16(16),
15
- x5: u8(18),
16
- x6: string(19, 11),
17
- })
18
-
19
- const testObject = {
20
- x1: Math.fround(Math.SQRT2),
21
- x2: Math.PI,
22
- x3: 0x01234567,
23
- x4: 0x0123,
24
- x5: 0x01,
25
- x6: "Hello world",
26
- }
27
-
28
- const testBytes = Uint8Array.fromHex(
29
- "f304b53f182d4454fb2109406745230123010148656c6c6f20776f726c64",
30
- )
31
- const BYTE_LENGTH = 30
32
-
33
- function manualUnpack(ab: ArrayBuffer) {
34
- const dv = new DataView(ab)
35
- return {
36
- x1: dv.getFloat32(0, true),
37
- x2: dv.getFloat64(4, true),
38
- x3: dv.getUint32(12, true),
39
- x4: dv.getUint16(16, true),
40
- x5: dv.getUint8(18),
41
- x6: new TextDecoder().decode(new Uint8Array(ab, 19, 11)),
42
- }
43
- }
44
-
45
- function manualPack(
46
- x: typeof testObject,
47
- ) {
48
- const ab = new ArrayBuffer(BYTE_LENGTH)
49
- const dv = new DataView(ab)
50
- dv.setFloat32(0, x.x1, true)
51
- dv.setFloat64(4, x.x2, true)
52
- dv.setUint32(12, x.x3, true)
53
- dv.setUint16(16, x.x4, true)
54
- dv.setUint8(18, x.x5)
55
- new TextEncoder().encodeInto(x.x6, new Uint8Array(ab, 19, 11))
56
- return ab
57
- }
58
-
59
- Deno.bench("pack with Struct", { group: "pack", baseline: true }, () => {
60
- const result = new Uint8Array(BYTE_LENGTH)
61
- const s = new StructClass(result)
62
- s.x1 = testObject.x1
63
- s.x2 = testObject.x2
64
- s.x3 = testObject.x3
65
- s.x4 = testObject.x4
66
- s.x5 = testObject.x5
67
- s.x6 = testObject.x6
68
- assertEquals(result, testBytes)
69
- })
70
-
71
- Deno.bench("pack manually", { group: "pack" }, () => {
72
- const result = manualPack(testObject)
73
- assertEquals(new Uint8Array(result), testBytes)
74
- })
75
-
76
- // Surprisingly, this turns out to be *faster* than the DataView version! I think it's because of V8 optimizations for a class instance vs an object literal.
77
- Deno.bench("unpack with Struct", { group: "unpack", baseline: true }, () => {
78
- const result = new StructClass({
79
- buffer: testBytes.buffer,
80
- byteLength: BYTE_LENGTH,
81
- })
82
- assertEquals(result.x1, testObject.x1)
83
- assertEquals(result.x2, testObject.x2)
84
- assertEquals(result.x3, testObject.x3)
85
- assertEquals(result.x4, testObject.x4)
86
- assertEquals(result.x5, testObject.x5)
87
- assertEquals(result.x6, testObject.x6)
88
- })
89
-
90
- Deno.bench("unpack manually", { group: "unpack" }, () => {
91
- const result = manualUnpack(testBytes.buffer)
92
- assertEquals(result.x1, testObject.x1)
93
- assertEquals(result.x2, testObject.x2)
94
- assertEquals(result.x3, testObject.x3)
95
- assertEquals(result.x4, testObject.x4)
96
- assertEquals(result.x5, testObject.x5)
97
- assertEquals(result.x6, testObject.x6)
98
- })