@nnilky/structo 1.0.8 → 1.1.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 (122) hide show
  1. package/README.md +4 -4
  2. package/dist/datatypes/containers/array.d.ts +1 -1
  3. package/dist/datatypes/containers/array.js +9 -12
  4. package/dist/datatypes/containers/array.test.js +2 -2
  5. package/dist/datatypes/containers/exhuastiveArray.d.ts +1 -1
  6. package/dist/datatypes/containers/exhuastiveArray.js +7 -7
  7. package/dist/datatypes/containers/exhuastiveArray.test.js +2 -2
  8. package/dist/datatypes/containers/fastObject.d.ts +1 -1
  9. package/dist/datatypes/containers/fastObject.test.js +2 -2
  10. package/dist/datatypes/containers/list.d.ts +1 -1
  11. package/dist/datatypes/containers/list.js +7 -7
  12. package/dist/datatypes/containers/list.test.js +2 -2
  13. package/dist/datatypes/containers/object.d.ts +1 -1
  14. package/dist/datatypes/containers/object.js +9 -8
  15. package/dist/datatypes/containers/object.test.js +2 -2
  16. package/dist/datatypes/containers/taggedUnion.d.ts +1 -1
  17. package/dist/datatypes/containers/taggedUnion.test.js +2 -2
  18. package/dist/datatypes/index.d.ts +13 -13
  19. package/dist/datatypes/index.js +13 -13
  20. package/dist/datatypes/numbers/bigints.d.ts +1 -1
  21. package/dist/datatypes/numbers/bigints.js +2 -2
  22. package/dist/datatypes/numbers/bigints.test.js +2 -2
  23. package/dist/datatypes/numbers/floats.d.ts +1 -1
  24. package/dist/datatypes/numbers/floats.js +12 -9
  25. package/dist/datatypes/numbers/floats.test.js +2 -2
  26. package/dist/datatypes/numbers/sints.d.ts +1 -1
  27. package/dist/datatypes/numbers/sints.js +13 -10
  28. package/dist/datatypes/numbers/sints.test.js +2 -2
  29. package/dist/datatypes/numbers/uints.d.ts +1 -1
  30. package/dist/datatypes/numbers/uints.js +13 -10
  31. package/dist/datatypes/numbers/uints.test.js +2 -2
  32. package/dist/datatypes/values/bytes.d.ts +2 -2
  33. package/dist/datatypes/values/bytes.js +6 -6
  34. package/dist/datatypes/values/bytes.test.js +4 -4
  35. package/dist/datatypes/values/sizedbytes.d.ts +2 -2
  36. package/dist/datatypes/values/sizedbytes.js +3 -4
  37. package/dist/datatypes/values/sizedbytes.test.js +3 -3
  38. package/dist/datatypes/values/string.d.ts +1 -1
  39. package/dist/datatypes/values/string.js +2 -3
  40. package/dist/datatypes/values/string.test.js +2 -2
  41. package/dist/index.d.ts +6 -6
  42. package/dist/index.js +5 -5
  43. package/dist/read.d.ts +2 -3
  44. package/dist/read.js +10 -12
  45. package/dist/transforms/encode.d.ts +1 -1
  46. package/dist/transforms/enum.d.ts +1 -1
  47. package/dist/transforms/enum.js +1 -1
  48. package/dist/transforms/enum.test.js +2 -2
  49. package/dist/transforms/index.d.ts +11 -11
  50. package/dist/transforms/index.js +11 -11
  51. package/dist/transforms/literal.d.ts +1 -1
  52. package/dist/transforms/literal.js +1 -1
  53. package/dist/transforms/literal.test.js +2 -2
  54. package/dist/transforms/modify.d.ts +1 -1
  55. package/dist/transforms/modify.test.js +2 -2
  56. package/dist/transforms/offset.d.ts +1 -1
  57. package/dist/transforms/offset.test.js +2 -2
  58. package/dist/transforms/pipe.d.ts +1 -1
  59. package/dist/transforms/toAscii.d.ts +1 -1
  60. package/dist/transforms/toAscii.js +3 -3
  61. package/dist/transforms/toAscii.test.js +2 -2
  62. package/dist/transforms/toBase64.d.ts +1 -1
  63. package/dist/transforms/toBase64.js +3 -3
  64. package/dist/transforms/toBase64.test.js +2 -2
  65. package/dist/transforms/toBytes.d.ts +1 -1
  66. package/dist/transforms/toBytes.js +3 -3
  67. package/dist/transforms/toBytes.test.js +2 -2
  68. package/dist/transforms/toHex.d.ts +3 -3
  69. package/dist/transforms/toHex.js +5 -5
  70. package/dist/transforms/toHex.test.js +2 -2
  71. package/dist/transforms/toTypedArray.d.ts +11 -6
  72. package/dist/transforms/toTypedArray.js +11 -6
  73. package/dist/transforms/toTypedArray.test.js +20 -11
  74. package/dist/types.d.ts +11 -9
  75. package/dist/utilities/index.d.ts +3 -3
  76. package/dist/utilities/index.js +3 -3
  77. package/dist/utilities/lazy.d.ts +1 -1
  78. package/dist/utilities/lazy.test.js +2 -2
  79. package/dist/utilities/reference.d.ts +1 -1
  80. package/dist/utilities/reference.test.js +2 -2
  81. package/dist/utilities/remember.d.ts +2 -2
  82. package/dist/utilities/remember.js +3 -3
  83. package/dist/utilities/remember.test.js +2 -2
  84. package/dist/utils.test.d.ts +2 -2
  85. package/dist/utils.test.js +2 -4
  86. package/dist/write.d.ts +2 -2
  87. package/dist/write.js +47 -34
  88. package/package.json +7 -2
  89. package/dist/datatypes/containers/sizedbytes.d.ts +0 -2
  90. package/dist/datatypes/containers/sizedbytes.js +0 -17
  91. package/dist/datatypes/containers/sizedbytes.test.d.ts +0 -1
  92. package/dist/datatypes/containers/sizedbytes.test.js +0 -27
  93. package/dist/datatypes/containers/string.d.ts +0 -2
  94. package/dist/datatypes/containers/string.js +0 -24
  95. package/dist/datatypes/containers/string.test.d.ts +0 -1
  96. package/dist/datatypes/containers/string.test.js +0 -24
  97. package/dist/datatypes/transforms/encode.d.ts +0 -2
  98. package/dist/datatypes/transforms/encode.js +0 -7
  99. package/dist/datatypes/transforms/fixedOffset.d.ts +0 -2
  100. package/dist/datatypes/transforms/fixedOffset.js +0 -18
  101. package/dist/datatypes/transforms/modify.d.ts +0 -2
  102. package/dist/datatypes/transforms/modify.js +0 -7
  103. package/dist/datatypes/transforms/noAdvance.d.ts +0 -16
  104. package/dist/datatypes/transforms/noAdvance.js +0 -30
  105. package/dist/datatypes/transforms/pipe.d.ts +0 -11
  106. package/dist/datatypes/transforms/pipe.js +0 -16
  107. package/dist/datatypes/utilities/remember.d.ts +0 -15
  108. package/dist/datatypes/utilities/remember.js +0 -36
  109. package/dist/datatypes/utilities/remember.test.d.ts +0 -1
  110. package/dist/datatypes/utilities/remember.test.js +0 -44
  111. package/dist/datatypes/utils.test.d.ts +0 -8
  112. package/dist/datatypes/utils.test.js +0 -37
  113. package/dist/datatypes/values/byteliteral.d.ts +0 -2
  114. package/dist/datatypes/values/byteliteral.js +0 -20
  115. package/dist/datatypes/values/json.d.ts +0 -10
  116. package/dist/datatypes/values/json.js +0 -21
  117. package/dist/transforms/fixedOffset.d.ts +0 -2
  118. package/dist/transforms/fixedOffset.js +0 -18
  119. package/dist/transforms/noAdvance.d.ts +0 -16
  120. package/dist/transforms/noAdvance.js +0 -30
  121. package/dist/transforms/noAdvance.test.d.ts +0 -1
  122. package/dist/transforms/noAdvance.test.js +0 -17
@@ -1,3 +1,3 @@
1
- export { lazy } from "./lazy";
2
- export { createReference } from "./reference";
3
- export { createRememberedValue } from "./remember";
1
+ export { lazy } from "./lazy.js";
2
+ export { createReference } from "./reference.js";
3
+ export { createRememberedValue } from "./remember.js";
@@ -1,2 +1,2 @@
1
- import type { Serializer } from "../types";
1
+ import type { Serializer } from "../types.js";
2
2
  export declare function lazy<TIn, TOut = TIn>(type: () => Serializer<TIn, TOut>): Serializer<TIn, TOut>;
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from "bun:test";
2
- import { encodeTest } from "../utils.test";
3
- import * as st from "../index";
2
+ import { encodeTest } from "../utils.test.js";
3
+ import * as st from "../index.js";
4
4
  describe("st.lazy", () => {
5
5
  it("encodes correctly", () => {
6
6
  const spec = st.lazy(() => st.object({
@@ -1,4 +1,4 @@
1
- import type { Serializer } from "../types";
1
+ import type { Serializer } from "../types.js";
2
2
  /**
3
3
  * createReference lets you defer writing a value until later, useful for lengths and sizes
4
4
  *
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from "bun:test";
2
- import { encodeTest, encodeSnapshotTest, expectError } from "../utils.test";
3
- import * as st from "../index";
2
+ import { encodeTest, encodeSnapshotTest, expectError } from "../utils.test.js";
3
+ import * as st from "../index.js";
4
4
  describe("st.createReference", () => {
5
5
  it("encodes correctly", () => {
6
6
  const length = st.createReference();
@@ -1,11 +1,11 @@
1
- import type { Serializer } from "../types";
1
+ import type { Serializer } from "../types.js";
2
2
  /**
3
3
  * createRememberedValue lets you save and recall a value when serializing
4
4
  *
5
5
  * This is useful for checksums and other values calculated from a writen value
6
6
  *
7
7
  * ```
8
- * const data = st.createRememberedValue<ArrayBuffer>()
8
+ * const data = st.createRememberedValue<Uint8Array>()
9
9
  * st.object({
10
10
  * data: data.save(st.bytes(1024))
11
11
  * checksum: crc32(data.load())
@@ -4,7 +4,7 @@
4
4
  * This is useful for checksums and other values calculated from a writen value
5
5
  *
6
6
  * ```
7
- * const data = st.createRememberedValue<ArrayBuffer>()
7
+ * const data = st.createRememberedValue<Uint8Array>()
8
8
  * st.object({
9
9
  * data: data.save(st.bytes(1024))
10
10
  * checksum: crc32(data.load())
@@ -18,7 +18,7 @@ export function createRememberedValue() {
18
18
  *
19
19
  * ---
20
20
  * ```
21
- * const data = st.createRememberedValue<ArrayBuffer>()
21
+ * const data = st.createRememberedValue<Uint8Array>()
22
22
  * st.object({
23
23
  * data: data.save(st.bytes(1024))
24
24
  * checksum: crc32(data.load())
@@ -50,7 +50,7 @@ export function createRememberedValue() {
50
50
  *
51
51
  * ---
52
52
  * ```
53
- * const data = st.createRememberedValue<ArrayBuffer>()
53
+ * const data = st.createRememberedValue<Uint8Array>()
54
54
  * st.object({
55
55
  * data: data.save(st.bytes(1024))
56
56
  * checksum: crc32(data.load())
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it } from "bun:test";
2
- import { encodeTest, encodeSnapshotTest } from "../utils.test";
3
- import * as st from "../index";
2
+ import { encodeTest, encodeSnapshotTest } from "../utils.test.js";
3
+ import * as st from "../index.js";
4
4
  describe("st.remember", () => {
5
5
  it("encodes correctly", () => {
6
6
  const v = st.createRememberedValue();
@@ -1,4 +1,4 @@
1
- import * as st from "./index";
1
+ import * as st from "./index.js";
2
2
  export declare const randint: (start: number, end: number) => number;
3
3
  export declare const randbigint: (start: bigint, end: bigint) => bigint;
4
4
  export declare const encodeTest: <TIn, TOut>(serializer: st.Serializer<TIn, TOut>, value: TIn, expected?: TOut) => void;
@@ -6,4 +6,4 @@ export declare const encodeFailTest: <TIn, TOut>(serializer: st.Serializer<TIn,
6
6
  export declare const expectEncodeSize: <TIn, TOut>(serializer: st.Serializer<TIn, TOut>, size: number, value: TIn) => void;
7
7
  export declare const encodeSnapshotTest: <T>(serializer: st.Serializer<T>, value: T) => void;
8
8
  export declare const expectError: (callback: () => void) => void;
9
- export declare const bytes: (bytes: number[]) => ArrayBuffer;
9
+ export declare const bytes: (bytes: number[]) => Uint8Array<ArrayBuffer>;
@@ -1,6 +1,6 @@
1
1
  //@ts-ignore TODO
2
2
  import { describe, it, expect } from "bun:test";
3
- import * as st from "./index";
3
+ import * as st from "./index.js";
4
4
  export const randint = (start, end) => {
5
5
  const range = end - start;
6
6
  return Math.floor(start + range * Math.random());
@@ -37,6 +37,4 @@ export const expectError = (callback) => {
37
37
  }
38
38
  throw new Error("Expected Error");
39
39
  };
40
- export const bytes = (bytes) => {
41
- return new Uint8Array(bytes).buffer;
42
- };
40
+ export const bytes = (bytes) => new Uint8Array(bytes);
package/dist/write.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- import type { WriterContext, Serializer } from "./types";
1
+ import type { Serializer } from "./types.js";
2
2
  export declare function write<TIn, TOut>(serializer: Serializer<TIn, TOut>, value: TIn): ArrayBuffer;
3
- export declare function createdWriterContext(type: Serializer<any>): WriterContext;
3
+ export declare function writeInto<TIn, TOut, TBuffer extends ArrayBuffer | SharedArrayBuffer>(buffer: TBuffer, offset: number, serializer: Serializer<TIn, TOut>, value: TIn): void;
package/dist/write.js CHANGED
@@ -1,49 +1,62 @@
1
1
  export function write(serializer, value) {
2
- const ctx = createdWriterContext(serializer);
2
+ let byteLength = serializer.size ?? 4096;
3
+ let buffer_ = new ArrayBuffer(byteLength);
4
+ let ctx = {
5
+ path: [],
6
+ offset: 0,
7
+ buffer: buffer_,
8
+ bytes: new Uint8Array(buffer_),
9
+ view: new DataView(buffer_),
10
+ reserve: (length) => {
11
+ if (length <= 0)
12
+ return;
13
+ while (ctx.offset + length > byteLength) {
14
+ byteLength *= 2;
15
+ ctx.buffer = ctx.buffer.transfer(byteLength);
16
+ ctx.view = new DataView(ctx.buffer);
17
+ ctx.bytes = new Uint8Array(ctx.buffer);
18
+ }
19
+ },
20
+ };
21
+ if (serializer.size) {
22
+ ctx.reserve = (length) => {
23
+ if (ctx.offset + length > byteLength) {
24
+ throw new Error("Attempted to allocate space when writing into buffer");
25
+ }
26
+ };
27
+ }
3
28
  try {
4
29
  serializer.write(ctx, value);
5
30
  }
6
31
  catch (e) {
7
- const path = ctx.stack.join("") ?? "root";
8
- throw new Error(`Serialization error at value${path}`, { cause: e });
32
+ const path = ctx.path.length === 0 ? "root" : "value" + ctx.path.join("");
33
+ throw new Error(`Serialization error at ${path}`, { cause: e });
9
34
  }
10
35
  if (ctx.buffer.byteLength === ctx.offset) {
11
36
  return ctx.buffer;
12
37
  }
13
38
  else {
14
- return ctx.buffer.transfer(ctx.offset);
39
+ return ctx.buffer.transferToFixedLength(ctx.offset);
15
40
  }
16
41
  }
17
- export function createdWriterContext(type) {
18
- if (type.size) {
19
- let buffer = new ArrayBuffer(type.size);
20
- const view = new DataView(buffer);
21
- return {
22
- stack: [],
23
- offset: 0,
24
- buffer,
25
- view,
26
- alloc: Function.prototype,
27
- };
42
+ export function writeInto(buffer, offset, serializer, value) {
43
+ let ctx = {
44
+ path: [],
45
+ offset: offset,
46
+ buffer: buffer,
47
+ bytes: new Uint8Array(buffer),
48
+ view: new DataView(buffer),
49
+ reserve(length) {
50
+ if (ctx.offset + length > ctx.buffer.byteLength) {
51
+ throw new Error("Attempted to allocate space when writing into buffer");
52
+ }
53
+ },
54
+ };
55
+ try {
56
+ serializer.write(ctx, value);
28
57
  }
29
- else {
30
- let bufferLength = 64;
31
- let buffer = new ArrayBuffer(bufferLength);
32
- const view = new DataView(buffer);
33
- return {
34
- stack: [],
35
- offset: 0,
36
- buffer,
37
- view,
38
- alloc(length) {
39
- if (length < 0)
40
- return;
41
- while (this.offset + length >= bufferLength) {
42
- bufferLength = this.buffer.byteLength * 2;
43
- this.buffer = this.buffer.transfer(bufferLength);
44
- this.view = new DataView(this.buffer);
45
- }
46
- },
47
- };
58
+ catch (e) {
59
+ const path = ctx.path.join("") ?? "root";
60
+ throw new Error(`Serialization error at value${path}`, { cause: e });
48
61
  }
49
62
  }
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "node"
10
10
  ],
11
11
  "license": "ISC",
12
- "version": "1.0.8",
12
+ "version": "1.1.0",
13
13
  "author": "Ben Brady",
14
14
  "private": false,
15
15
  "publishConfig": {
@@ -49,13 +49,18 @@
49
49
  "@types/node": "^25.9.2",
50
50
  "bun-types": "^1.3.14",
51
51
  "jest": "^30.4.2",
52
+ "tsx": "^4.22.4",
52
53
  "typescript": "^6.0.3"
53
54
  },
55
+ "dependencies": {
56
+ "@mitata/counters": "^0.0.8",
57
+ "mitata": "^1.0.34"
58
+ },
54
59
  "scripts": {
55
60
  "build": "tsc",
56
61
  "prepublish": "tsc",
57
62
  "check": "tsc --noEmit",
58
- "test": "bun test src --only-failures",
63
+ "test": "bun test src ",
59
64
  "test:coverage": "bun test src --only-failures --coverage"
60
65
  }
61
66
  }
@@ -1,2 +0,0 @@
1
- import type { Serializer } from "../../types";
2
- export declare function sizedBytes(length: Serializer<number>): Serializer<ArrayBuffer>;
@@ -1,17 +0,0 @@
1
- export function sizedBytes(length) {
2
- return {
3
- write: (ctx, value) => {
4
- length.write(ctx, value.byteLength);
5
- const bytes = new Uint8Array(value);
6
- ctx.alloc(value.byteLength);
7
- new Uint8Array(ctx.view.buffer).set(bytes, ctx.offset);
8
- ctx.offset += value.byteLength;
9
- },
10
- read: (ctx) => {
11
- const size = length.read(ctx);
12
- const slice = ctx.buffer.slice(ctx.offset, ctx.offset + size);
13
- ctx.offset += size;
14
- return slice;
15
- },
16
- };
17
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,27 +0,0 @@
1
- import { describe, it } from "bun:test";
2
- import { bytes, expectEncode, expectError } from "../utils.test";
3
- import * as st from "../../index";
4
- describe("st.sizedBytes", () => {
5
- it("encode correctly", () => {
6
- const buffer = st.sizedBytes(st.u8());
7
- expectEncode(buffer, bytes([1, 2]));
8
- });
9
- it("encodes empty correctly", () => {
10
- const spec = st.sizedBytes(st.u8());
11
- expectEncode(spec, bytes([]));
12
- });
13
- it("holds large data", () => {
14
- const size = 1024 * 1024 * 8; // 8MB
15
- const spec = st.sizedBytes(st.u32());
16
- const data = new Uint8Array(size);
17
- data.set([3, 4], 1000);
18
- data.set([3, 4], 2000);
19
- expectEncode(spec, data.buffer);
20
- });
21
- it("errors on invalid length", () => {
22
- const spec = st.sizedBytes(st.u8());
23
- expectError(() => {
24
- st.write(spec, bytes(Array.from({ length: 256 }, () => 0)));
25
- });
26
- });
27
- });
@@ -1,2 +0,0 @@
1
- import type { Serializer } from "../../types";
2
- export declare function string(length: Serializer<number>): Serializer<string>;
@@ -1,24 +0,0 @@
1
- export function string(length) {
2
- const encoder = new TextEncoder();
3
- const decoder = new TextDecoder();
4
- const lengthSize = length.size ?? 0;
5
- return {
6
- write: (ctx, value) => {
7
- if (typeof value !== "string")
8
- throw new Error("Expected String to encoder");
9
- const bytes = encoder.encode(value);
10
- const size = bytes.byteLength;
11
- ctx.alloc(size + lengthSize);
12
- length.write(ctx, size);
13
- const arr = new Uint8Array(ctx.buffer, ctx.offset);
14
- arr.set(bytes);
15
- ctx.offset += size;
16
- },
17
- read: (ctx) => {
18
- const size = length.read(ctx);
19
- const section = ctx.buffer.slice(ctx.offset, ctx.offset + size);
20
- ctx.offset += size;
21
- return decoder.decode(section);
22
- },
23
- };
24
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,24 +0,0 @@
1
- import { describe, it } from "bun:test";
2
- import { expectEncode, expectError } from "../utils.test";
3
- import * as st from "../../index";
4
- describe("st.string", () => {
5
- const string_u8 = st.string(st.u8());
6
- const string_u32 = st.string(st.u32());
7
- it("encode correctly", () => {
8
- expectEncode(string_u8, "foo");
9
- });
10
- it("works on empty strings", () => {
11
- expectEncode(string_u32, "");
12
- });
13
- it("errors on numbers", () => {
14
- expectError(() => {
15
- //@ts-expect-error, intentional mistake
16
- st.write(st.string(st.u8()), 8);
17
- });
18
- });
19
- it("errors on too long strings", () => {
20
- expectError(() => {
21
- st.write(string_u8, "A".repeat(256));
22
- });
23
- });
24
- });
@@ -1,2 +0,0 @@
1
- import type { Transform } from "./pipe";
2
- export declare function encode<TIn, TOut>(encodeTo: (value: TIn) => TOut, encodeFrom: (value: TOut) => TIn): Transform<TOut, TIn>;
@@ -1,7 +0,0 @@
1
- export function encode(encodeTo, encodeFrom) {
2
- return (type) => ({
3
- size: type.size,
4
- read: (ctx) => encodeTo(type.read(ctx)),
5
- write: (ctx, value) => type.write(ctx, encodeFrom(value)),
6
- });
7
- }
@@ -1,2 +0,0 @@
1
- import type { Serializer } from "../../types";
2
- export declare function fixedOffset<T>(delta: number): (type: Serializer<T>) => Serializer<T>;
@@ -1,18 +0,0 @@
1
- export function fixedOffset(delta) {
2
- return (type) => ({
3
- size: type.size,
4
- read: (ctx) => {
5
- let start = ctx.offset;
6
- ctx.offset += delta;
7
- const value = type.read(ctx);
8
- ctx.offset = start;
9
- return value;
10
- },
11
- write: (ctx, value) => {
12
- let start = ctx.offset;
13
- ctx.offset += delta;
14
- type.write(ctx, value);
15
- ctx.offset = start;
16
- },
17
- });
18
- }
@@ -1,2 +0,0 @@
1
- import type { Transform } from "./pipe";
2
- export declare function modify<T>(callback: (value: T) => T): Transform<T>;
@@ -1,7 +0,0 @@
1
- export function modify(callback) {
2
- return (type) => ({
3
- size: type.size,
4
- read: (ctx) => callback(type.read(ctx)),
5
- write: (ctx, value) => type.write(ctx, callback(value)),
6
- });
7
- }
@@ -1,16 +0,0 @@
1
- import type { Serializer } from "../../types";
2
- /**
3
- * Whilst reading this type, don't advance the offset after reading
4
- *
5
- * This can be useful for taggedUnions where they key is the first value in all the variants
6
- *
7
- * ```
8
- * st.object({
9
- * stringLength: st.pipe(
10
- * st.u16(),
11
- * st.noAdvance(),
12
- * ),
13
- * text: st.string(st.u16()),
14
- * })
15
- */
16
- export declare function noAdvance<T>(): (type: Serializer<T>) => Serializer<T>;
@@ -1,30 +0,0 @@
1
- /**
2
- * Whilst reading this type, don't advance the offset after reading
3
- *
4
- * This can be useful for taggedUnions where they key is the first value in all the variants
5
- *
6
- * ```
7
- * st.object({
8
- * stringLength: st.pipe(
9
- * st.u16(),
10
- * st.noAdvance(),
11
- * ),
12
- * text: st.string(st.u16()),
13
- * })
14
- */
15
- export function noAdvance() {
16
- return (type) => ({
17
- size: type.size,
18
- read: (ctx) => {
19
- let start = ctx.offset;
20
- const value = type.read(ctx);
21
- ctx.offset = start;
22
- return value;
23
- },
24
- write: (ctx, value) => {
25
- let start = ctx.offset;
26
- type.write(ctx, value);
27
- ctx.offset = start;
28
- },
29
- });
30
- }
@@ -1,11 +0,0 @@
1
- import type { Serializer } from "../../types";
2
- export type Transform<T = any, TNext = T> = (type: Serializer<TNext>) => Serializer<T>;
3
- export declare function pipe<TStart, T1>(type: Serializer<TStart>, p1: Transform<T1, TStart>): Serializer<T1>;
4
- export declare function pipe<TStart, T1, T2>(type: Serializer<TStart>, p1: Transform<T1, TStart>, p2: Transform<T2, T1>): Serializer<T2>;
5
- export declare function pipe<TStart, T1, T2, T3>(type: Serializer<TStart>, p1: Transform<T1, TStart>, p2: Transform<T2, T1>, p3: Transform<T3, T2>): Serializer<T3>;
6
- export declare function pipe<TStart, T1, T2, T3, T4>(type: Serializer<TStart>, p1: Transform<T1, TStart>, p2: Transform<T2, T1>, p3: Transform<T3, T2>, p4: Transform<T4, T3>): Serializer<T4>;
7
- export declare function pipe<TStart, T1, T2, T3, T4, T5>(type: Serializer<TStart>, p1: Transform<T1, TStart>, p2: Transform<T2, T1>, p3: Transform<T3, T2>, p4: Transform<T4, T3>, p5: Transform<T5, T4>): Serializer<T5>;
8
- export declare function pipe<TStart, T1, T2, T3, T4, T5, T6>(type: Serializer<TStart>, p1: Transform<T1, TStart>, p2: Transform<T2, T1>, p3: Transform<T3, T2>, p4: Transform<T4, T3>, p5: Transform<T5, T6>): Serializer<T6>;
9
- export declare function pipe<TStart, T1, T2, T3, T4, T5, T6, T7>(type: Serializer<TStart>, p1: Transform<T1, TStart>, p2: Transform<T2, T1>, p3: Transform<T3, T2>, p4: Transform<T4, T3>, p5: Transform<T5, T6>, p6: Transform<T6, T7>): Serializer<T7>;
10
- export declare function pipe<TStart, T1, T2, T3, T4, T5, T6, T7, T8>(type: Serializer<TStart>, p1: Transform<T1, TStart>, p2: Transform<T2, T1>, p3: Transform<T3, T2>, p4: Transform<T4, T3>, p5: Transform<T5, T6>, p6: Transform<T6, T7>, p7: Transform<T7, T8>): Serializer<T8>;
11
- export declare function pipe<TStart, T1, T2, T3, T4, T5, T6, T7, T8, T9>(type: Serializer<TStart>, p1: Transform<T1, TStart>, p2: Transform<T2, T1>, p3: Transform<T3, T2>, p4: Transform<T4, T3>, p5: Transform<T5, T6>, p6: Transform<T6, T7>, p7: Transform<T7, T8>, p8: Transform<T8, T9>): Serializer<T9>;
@@ -1,16 +0,0 @@
1
- /**
2
- * Pipe lets you chain modification functions together
3
- * ```
4
- * st.object({
5
- * age: st.u32(),
6
- * ageInMonths: st.pipe(
7
- * st.u32(),
8
- * st.modify(v => v * 12),
9
- * st.offset(-8),
10
- * )})
11
- * ```
12
- */
13
- export function pipe(type, ...pipeline) {
14
- //@ts-ignore
15
- return pipeline.reduce((v, func) => func(v), type);
16
- }
@@ -1,15 +0,0 @@
1
- import type { Serializer } from "../../types";
2
- /**
3
- * ```
4
- * const length = st.createRememberedValue<number>()
5
- * st.object({
6
- * length: length.save(st.u32()),
7
- * type: st.u8(),
8
- * data: st.sizedBytes(length.load())
9
- * })
10
- * ```
11
- */
12
- export declare function createRememberedValue<T>(): {
13
- save: (serializer: Serializer<T>) => Serializer<T>;
14
- load: (serializer?: Serializer<T>) => Serializer<T>;
15
- };
@@ -1,36 +0,0 @@
1
- /**
2
- * ```
3
- * const length = st.createRememberedValue<number>()
4
- * st.object({
5
- * length: length.save(st.u32()),
6
- * type: st.u8(),
7
- * data: st.sizedBytes(length.load())
8
- * })
9
- * ```
10
- */
11
- export function createRememberedValue() {
12
- const stack = [];
13
- function save(serializer) {
14
- return {
15
- size: serializer.size,
16
- read: (ctx) => {
17
- const value = serializer.read(ctx);
18
- stack.push(value);
19
- return value;
20
- },
21
- write: (ctx, value) => {
22
- serializer.write(ctx, value);
23
- stack.push(value);
24
- return value;
25
- },
26
- };
27
- }
28
- function load(serializer) {
29
- return {
30
- size: serializer?.size ?? 0,
31
- read: () => stack.pop(),
32
- write: (ctx) => serializer && serializer.write(ctx, stack.pop()),
33
- };
34
- }
35
- return { save: save, load: load };
36
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,44 +0,0 @@
1
- import { describe, expect, it } from "bun:test";
2
- import { expectEncode, expectEncodeSnapshot } from "../utils.test";
3
- import * as st from "../../index";
4
- describe("st.remember", () => {
5
- const v = st.createRememberedValue();
6
- it("encodes correctly", () => {
7
- const spec = st.object({
8
- a: v.save(st.u32()),
9
- b: st.list(v.load(), st.u8()),
10
- });
11
- expectEncode(spec, {
12
- a: 3,
13
- b: [1, 3, 4],
14
- });
15
- });
16
- it("omitted serializer doesn't write data ", () => {
17
- const spec = st.object({
18
- a: v.save(st.u32()),
19
- b: v.load(),
20
- });
21
- const output = st.write(spec, { a: 3, b: 0 });
22
- expect(output.byteLength).toBe(4);
23
- });
24
- it("serializer is used write data ", () => {
25
- const spec = st.object({
26
- a: v.save(st.u32()),
27
- b: v.load(st.u8()),
28
- });
29
- expectEncode(spec, { a: 3, b: 0 }, { a: 3, b: 3 });
30
- });
31
- it("snapshots are correct", () => {
32
- expectEncodeSnapshot(st.object({
33
- a: v.save(st.u32()),
34
- b: st.list(v.load(), st.u8()),
35
- }), {
36
- a: 3,
37
- b: [1, 3, 4],
38
- });
39
- expectEncodeSnapshot(st.object({
40
- a: v.save(st.u32()),
41
- b: v.load(st.u8()),
42
- }), { a: 3, b: 0 });
43
- });
44
- });
@@ -1,8 +0,0 @@
1
- import * as st from "../index";
2
- export declare const randint: (start: number, end: number) => number;
3
- export declare const randbigint: (start: bigint, end: bigint) => bigint;
4
- export declare const expectEncode: <TIn, TOut>(serializer: st.Serializer<TIn, TOut>, value: TIn, expected?: TOut) => void;
5
- export declare const expectEncodeSize: <TIn, TOut>(serializer: st.Serializer<TIn, TOut>, size: number, value: TIn) => void;
6
- export declare const expectEncodeSnapshot: <T>(serializer: st.Serializer<T>, value: T) => void;
7
- export declare const expectError: (callback: () => void) => void;
8
- export declare const bytes: (bytes: number[]) => ArrayBuffer;
@@ -1,37 +0,0 @@
1
- //@ts-ignore TODO
2
- import { describe, it, expect } from "bun:test";
3
- import * as st from "../index";
4
- export const randint = (start, end) => {
5
- const range = end - start;
6
- return Math.floor(start + range * Math.random());
7
- };
8
- export const randbigint = (start, end) => {
9
- const range = end - start;
10
- const offset = BigInt(Math.floor(Number(range) * Math.random()));
11
- return start + offset;
12
- };
13
- export const expectEncode = (serializer, value, expected) => {
14
- const data = st.write(serializer, value);
15
- const newValue = st.read(serializer, data);
16
- expect(newValue).toEqual((expected ?? value));
17
- };
18
- export const expectEncodeSize = (serializer, size, value) => {
19
- const data = st.write(serializer, value);
20
- expect(data.byteLength).toEqual(size);
21
- };
22
- export const expectEncodeSnapshot = (serializer, value) => {
23
- const data = st.write(serializer, value);
24
- expect(data).toMatchSnapshot();
25
- };
26
- export const expectError = (callback) => {
27
- try {
28
- callback();
29
- }
30
- catch {
31
- return;
32
- }
33
- throw new Error("Expected Error");
34
- };
35
- export const bytes = (bytes) => {
36
- return new Uint8Array(bytes).buffer;
37
- };
@@ -1,2 +0,0 @@
1
- import type { Serializer } from "../../types";
2
- export declare function bytesLiteral(bytes: number[]): Serializer<number[]>;