@nnilky/structo 1.0.2 → 1.0.3
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.
- package/README.md +130 -0
- package/dist/datatypes/containers/array.test.js +22 -0
- package/dist/datatypes/containers/fastObject.d.ts +19 -0
- package/dist/{structo/datatypes → datatypes}/containers/fastObject.js +13 -0
- package/dist/datatypes/containers/list.test.d.ts +1 -0
- package/dist/datatypes/containers/list.test.js +31 -0
- package/dist/{structo/datatypes → datatypes}/containers/object.d.ts +11 -0
- package/dist/{structo/datatypes → datatypes}/containers/object.js +11 -0
- package/dist/datatypes/containers/object.test.d.ts +1 -0
- package/dist/datatypes/containers/object.test.js +33 -0
- package/dist/datatypes/containers/sizedbuffer.test.d.ts +1 -0
- package/dist/datatypes/containers/sizedbuffer.test.js +27 -0
- package/dist/{structo/datatypes → datatypes}/index.d.ts +1 -0
- package/dist/{structo/datatypes → datatypes}/index.js +1 -0
- package/dist/datatypes/lazy.d.ts +1 -0
- package/dist/datatypes/lazy.js +1 -0
- package/dist/datatypes/numbers/bigints.test.d.ts +1 -0
- package/dist/datatypes/numbers/bigints.test.js +61 -0
- package/dist/datatypes/numbers/floats.test.d.ts +1 -0
- package/dist/datatypes/numbers/floats.test.js +71 -0
- package/dist/datatypes/numbers/sints.test.d.ts +1 -0
- package/dist/datatypes/numbers/sints.test.js +87 -0
- package/dist/datatypes/numbers/uints.test.d.ts +1 -0
- package/dist/datatypes/numbers/uints.test.js +87 -0
- package/dist/datatypes/transforms/pipe.test.d.ts +1 -0
- package/dist/datatypes/transforms/pipe.test.js +13 -0
- package/dist/datatypes/utilities/constant.d.ts +2 -0
- package/dist/datatypes/utilities/constant.js +13 -0
- package/dist/datatypes/utilities/remember.d.ts +5 -0
- package/dist/datatypes/utilities/remember.js +26 -0
- package/dist/datatypes/utils.test.d.ts +7 -0
- package/dist/datatypes/utils.test.js +33 -0
- package/dist/datatypes/values/buffer.test.d.ts +1 -0
- package/dist/datatypes/values/buffer.test.js +43 -0
- package/dist/{structo/datatypes → datatypes}/values/string.js +7 -6
- package/dist/datatypes/values/string.test.d.ts +1 -0
- package/dist/datatypes/values/string.test.js +18 -0
- package/dist/types.js +1 -0
- package/dist/utils.test.d.ts +1 -0
- package/dist/utils.test.js +1 -0
- package/dist/{structo/write.js → write.js} +7 -5
- package/package.json +1 -1
- package/dist/structo/datatypes/containers/fastObject.d.ts +0 -6
- package/dist/{structo/datatypes → datatypes}/containers/array.d.ts +0 -0
- package/dist/{structo/datatypes → datatypes}/containers/array.js +0 -0
- package/dist/{structo/types.js → datatypes/containers/array.test.d.ts} +0 -0
- package/dist/{structo/datatypes → datatypes}/containers/list.d.ts +0 -0
- package/dist/{structo/datatypes → datatypes}/containers/list.js +0 -0
- package/dist/{structo/datatypes → datatypes}/containers/sizedbuffer.d.ts +0 -0
- package/dist/{structo/datatypes → datatypes}/containers/sizedbuffer.js +0 -0
- package/dist/{structo/datatypes → datatypes}/numbers/bigints.d.ts +0 -0
- package/dist/{structo/datatypes → datatypes}/numbers/bigints.js +0 -0
- package/dist/{structo/datatypes → datatypes}/numbers/floats.d.ts +0 -0
- package/dist/{structo/datatypes → datatypes}/numbers/floats.js +0 -0
- package/dist/{structo/datatypes → datatypes}/numbers/sints.d.ts +0 -0
- package/dist/{structo/datatypes → datatypes}/numbers/sints.js +0 -0
- package/dist/{structo/datatypes → datatypes}/numbers/uints.d.ts +0 -0
- package/dist/{structo/datatypes → datatypes}/numbers/uints.js +0 -0
- package/dist/{structo/datatypes → datatypes}/transforms/pipe.d.ts +0 -0
- package/dist/{structo/datatypes → datatypes}/transforms/pipe.js +0 -0
- package/dist/{structo/datatypes → datatypes}/transforms/readOffset.d.ts +0 -0
- package/dist/{structo/datatypes → datatypes}/transforms/readOffset.js +0 -0
- package/dist/{structo/datatypes → datatypes}/transforms/transform.d.ts +0 -0
- package/dist/{structo/datatypes → datatypes}/transforms/transform.js +0 -0
- package/dist/{structo/datatypes → datatypes}/values/buffer.d.ts +0 -0
- package/dist/{structo/datatypes → datatypes}/values/buffer.js +0 -0
- package/dist/{structo/datatypes → datatypes}/values/byteliteral.d.ts +0 -0
- package/dist/{structo/datatypes → datatypes}/values/byteliteral.js +0 -0
- package/dist/{structo/datatypes → datatypes}/values/string.d.ts +0 -0
- package/dist/{structo/index.d.ts → index.d.ts} +1 -1
- package/dist/{structo/index.js → index.js} +1 -1
- /package/dist/{structo/read.d.ts → read.d.ts} +0 -0
- /package/dist/{structo/read.js → read.js} +0 -0
- /package/dist/{structo/types.d.ts → types.d.ts} +0 -0
- /package/dist/{structo/write.d.ts → write.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -1 +1,131 @@
|
|
|
1
1
|
# Structo
|
|
2
|
+
|
|
3
|
+
Define binary objects in zod style schemas
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
import * as st from "@nnilky/structo";
|
|
7
|
+
|
|
8
|
+
type Vec3 = st.InferOutput<typeof Vec3>
|
|
9
|
+
const Vec3 = st.object({
|
|
10
|
+
x: st.f64(),
|
|
11
|
+
y: st.f64(),
|
|
12
|
+
z: st.f64(),
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
type Entity = st.InferOutput<typeof Entity>
|
|
16
|
+
const Entity = st.object({
|
|
17
|
+
id: st.u64(),
|
|
18
|
+
position: Vec3,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
- Lightweight, base size is <1KB and each datatype is a few hundred bytes
|
|
24
|
+
- Fast, from [benchmarks](./benchmark) only 2-
|
|
25
|
+
- Supports Web/Node.js compatible
|
|
26
|
+
- Easily implemented
|
|
27
|
+
|
|
28
|
+
Each serializer is completely seperate from the base library, meaning you only pay for what you use.
|
|
29
|
+
|
|
30
|
+
## Implementing your own Serializer
|
|
31
|
+
|
|
32
|
+
Implementing your own serializer is incredibly simple, heres the `f64` serializer for example
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
export function f64(endian: "little" | "big" = "little"): st.Serializer<number> {
|
|
36
|
+
return {
|
|
37
|
+
size: 8,
|
|
38
|
+
write: (ctx, value) => {
|
|
39
|
+
ctx.alloc(8);
|
|
40
|
+
ctx.view.setFloat64(ctx.offset, value, endian === "little");
|
|
41
|
+
ctx.offset += 8;
|
|
42
|
+
},
|
|
43
|
+
read: (ctx) => {
|
|
44
|
+
const value = ctx.view.getFloat64(ctx.offset, endian === "little");
|
|
45
|
+
ctx.offset += 8;
|
|
46
|
+
return value;
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The `alloc()` in the write function is a utility provided to you to ensure you have enough space ahead of you in the buffer to write to.
|
|
53
|
+
|
|
54
|
+
When reading and writing, you must increment the `ctx.offset` so the next value can be read from. However,
|
|
55
|
+
|
|
56
|
+
The `size` attribute is optional, but if included can be used to do allocations in advance.
|
|
57
|
+
|
|
58
|
+
> Important: You must modify the ctx object, do not spread over it since this will break the reference
|
|
59
|
+
|
|
60
|
+
### Container Example
|
|
61
|
+
|
|
62
|
+
Here is the list serializer
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
export function list<T>(options: {
|
|
66
|
+
type: st.Serializer<T>;
|
|
67
|
+
length: st.Serializer<number>;
|
|
68
|
+
}): st.Serializer<T[]> {
|
|
69
|
+
const lengthType = options.length;
|
|
70
|
+
const valueType = options.type;
|
|
71
|
+
|
|
72
|
+
return {
|
|
73
|
+
write: (ctx, value) => {
|
|
74
|
+
lengthType.write(ctx, value.length);
|
|
75
|
+
for (const v of value) {
|
|
76
|
+
lengthType.write(ctx, v);
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
read: (ctx) => {
|
|
80
|
+
const size = lengthType.read(ctx);
|
|
81
|
+
|
|
82
|
+
const arr = []
|
|
83
|
+
for (let i = 0; i < size; i++) {
|
|
84
|
+
arr.push(valueType.read(ctx))
|
|
85
|
+
}
|
|
86
|
+
return arr;
|
|
87
|
+
},
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Transforms
|
|
93
|
+
|
|
94
|
+
```ts
|
|
95
|
+
const Bits = st.pipe(
|
|
96
|
+
st.u32()
|
|
97
|
+
st.transform(v => v * 8)
|
|
98
|
+
)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Transforms are utility that let you modify a read/written value. They allow you to processing declaratively.
|
|
102
|
+
|
|
103
|
+
### Writing your Own
|
|
104
|
+
|
|
105
|
+
Here is the `transform` transformation function, a `transform` just a function that takes a type and returns a serializer.
|
|
106
|
+
|
|
107
|
+
```ts
|
|
108
|
+
export function transform<T>(callback: (value: T) => T) {
|
|
109
|
+
return (type: st.Serializer<T>): st.Serializer<T> => ({
|
|
110
|
+
size: type.size,
|
|
111
|
+
read: (ctx) => {
|
|
112
|
+
const value = type.read(ctx);
|
|
113
|
+
return callback(value);
|
|
114
|
+
},
|
|
115
|
+
write: (ctx, value) => {
|
|
116
|
+
let outValue = callback(value);
|
|
117
|
+
type.write(ctx, outValue);
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## FaQ
|
|
124
|
+
|
|
125
|
+
- Why do I have to do `import * as st from "@nnilky/structo"`?
|
|
126
|
+
- By using an `* as` import, bundles can erase the names as runtime without having to worry about runtime effects
|
|
127
|
+
- additionally, by putting it under a namespace it reduces con
|
|
128
|
+
- Will data streaming be implemented?
|
|
129
|
+
- Sadly this library isn't built for data streaming, the exposed API for serializers need the full array to be accessible
|
|
130
|
+
- If you want data streaming, your going to have to fork this and re-implement the standard types
|
|
131
|
+
- What's the difference`
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, it } from "bun:test";
|
|
2
|
+
import { expectEncode, expectError } from "../utils.test";
|
|
3
|
+
import * as st from "../../index";
|
|
4
|
+
describe("st.array", () => {
|
|
5
|
+
it("encode correctly", () => {
|
|
6
|
+
const spec = st.array(4, st.u16());
|
|
7
|
+
expectEncode(spec, [1, 2, 3, 4]);
|
|
8
|
+
});
|
|
9
|
+
it("works on empty lists", () => {
|
|
10
|
+
const spec = st.array(0, st.u16());
|
|
11
|
+
expectEncode(spec, []);
|
|
12
|
+
});
|
|
13
|
+
it("throws error on invalid size", () => {
|
|
14
|
+
const spec = st.array(2, st.u16());
|
|
15
|
+
expectError(() => st.write(spec, [1]));
|
|
16
|
+
});
|
|
17
|
+
it("throws error on invalid value", () => {
|
|
18
|
+
const spec = st.array(2, st.u16());
|
|
19
|
+
expectError(() => st.write(spec, [1, -1]));
|
|
20
|
+
expectError(() => st.write(spec, [2 ** 16 + 1, 0]));
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { InferInput, Serializer } from "../../types";
|
|
2
|
+
type InferObject<T> = T extends Record<string, Serializer<any>> ? {
|
|
3
|
+
[Key in keyof T]: InferInput<T[Key]>;
|
|
4
|
+
} : never;
|
|
5
|
+
/**
|
|
6
|
+
* `fastObject` is equivelent to object but it uses eval to improve performance
|
|
7
|
+
*
|
|
8
|
+
* This means that is should be avoided in scenarios where CSP is required (so can't be the default), but should be fine for all other cases
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* st.fastObject({
|
|
12
|
+
* name: st.string(st.u32()),
|
|
13
|
+
* age: st.u8(),
|
|
14
|
+
* createdAt: st.f64(),
|
|
15
|
+
* })
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare function fastObject<T extends Record<string, Serializer<any>>>(definition: T): Serializer<InferObject<T>>;
|
|
19
|
+
export {};
|
|
@@ -1,4 +1,17 @@
|
|
|
1
1
|
const definitionSymbol = Symbol();
|
|
2
|
+
/**
|
|
3
|
+
* `fastObject` is equivelent to object but it uses eval to improve performance
|
|
4
|
+
*
|
|
5
|
+
* This means that is should be avoided in scenarios where CSP is required (so can't be the default), but should be fine for all other cases
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* st.fastObject({
|
|
9
|
+
* name: st.string(st.u32()),
|
|
10
|
+
* age: st.u8(),
|
|
11
|
+
* createdAt: st.f64(),
|
|
12
|
+
* })
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
2
15
|
export function fastObject(definition) {
|
|
3
16
|
let serializers = [];
|
|
4
17
|
let writeBody = "";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { describe, it } from "bun:test";
|
|
2
|
+
import { expectEncode, expectEncodeSnapshot, expectError } from "../utils.test";
|
|
3
|
+
import * as st from "../../index";
|
|
4
|
+
describe("st.list", () => {
|
|
5
|
+
it("encode correctly", () => {
|
|
6
|
+
const spec = st.list({ type: st.u16(), length: st.u8() });
|
|
7
|
+
expectEncode(spec, [1, 2, 3, 4]);
|
|
8
|
+
});
|
|
9
|
+
it("works on empty lists", () => {
|
|
10
|
+
const spec = st.list({ type: st.u16(), length: st.u8() });
|
|
11
|
+
expectEncode(spec, []);
|
|
12
|
+
});
|
|
13
|
+
it("throws error on too large array", () => {
|
|
14
|
+
const spec = st.list({ type: st.u16(), length: st.u8() });
|
|
15
|
+
expectError(() => {
|
|
16
|
+
st.write(spec, Array.from({ length: 10000 }, () => 0));
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
it("throws error on invalid value", () => {
|
|
20
|
+
const spec = st.list({ type: st.u16(), length: st.u8() });
|
|
21
|
+
expectError(() => {
|
|
22
|
+
st.write(spec, [-1]);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
it(`matches snapshots`, () => {
|
|
26
|
+
expectEncodeSnapshot(st.list({
|
|
27
|
+
type: st.string(st.u16()),
|
|
28
|
+
length: st.s32(),
|
|
29
|
+
}), ["foo", "bar", "baz"]);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -5,5 +5,16 @@ type InferObjectInfer<T> = T extends Record<string, Serializer<any>> ? {
|
|
|
5
5
|
type InferObjectOutput<T> = T extends Record<string, Serializer<any>> ? {
|
|
6
6
|
[Key in keyof T]: InferOutput<T[Key]>;
|
|
7
7
|
} : never;
|
|
8
|
+
/**
|
|
9
|
+
* `object` is equivelent to a C struct, values are stored in the order defined
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* st.object({
|
|
13
|
+
* name: st.string(st.u32()),
|
|
14
|
+
* age: st.u8(),
|
|
15
|
+
* createdAt: st.f64(),
|
|
16
|
+
* })
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
8
19
|
export declare function object<T extends Record<string, Serializer<any>>>(definition: T): Serializer<InferObjectInfer<T>, InferObjectOutput<T>>;
|
|
9
20
|
export {};
|
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `object` is equivelent to a C struct, values are stored in the order defined
|
|
3
|
+
*
|
|
4
|
+
* ```ts
|
|
5
|
+
* st.object({
|
|
6
|
+
* name: st.string(st.u32()),
|
|
7
|
+
* age: st.u8(),
|
|
8
|
+
* createdAt: st.f64(),
|
|
9
|
+
* })
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
1
12
|
export function object(definition) {
|
|
2
13
|
const entires = Object.entries(definition);
|
|
3
14
|
// Use the fact: number + undefined = NaN
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//@ts-ignore TODO
|
|
2
|
+
import { describe, it, expect } from "bun:test";
|
|
3
|
+
import { bytes, expectEncode, expectEncodeSnapshot } from "../utils.test";
|
|
4
|
+
import * as st from "../../index";
|
|
5
|
+
describe("st.object", () => {
|
|
6
|
+
const test = st.object({
|
|
7
|
+
a: st.u8(),
|
|
8
|
+
b: st.u8(),
|
|
9
|
+
});
|
|
10
|
+
it("encodes correctly", () => {
|
|
11
|
+
st.write(test, { b: 2, a: 1 });
|
|
12
|
+
});
|
|
13
|
+
it("encode in correct order", () => {
|
|
14
|
+
const data = st.write(test, { b: 2, a: 1 });
|
|
15
|
+
const arr = new Uint8Array(data);
|
|
16
|
+
expect(arr[0]).toBe(1);
|
|
17
|
+
expect(arr[1]).toBe(2);
|
|
18
|
+
});
|
|
19
|
+
it("encodes empty", () => {
|
|
20
|
+
expectEncode(st.object({}), {});
|
|
21
|
+
});
|
|
22
|
+
it(`matches snapshots`, () => {
|
|
23
|
+
expectEncodeSnapshot(st.object({
|
|
24
|
+
number: st.u32(),
|
|
25
|
+
puppy: st.string(st.s32()),
|
|
26
|
+
buffer: st.buffer(4),
|
|
27
|
+
}), {
|
|
28
|
+
number: 1,
|
|
29
|
+
puppy: "woof woof bark bark",
|
|
30
|
+
buffer: bytes([19, 87, 19, 83]),
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { describe, it } from "bun:test";
|
|
2
|
+
import { bytes, expectEncode, expectError } from "../utils.test";
|
|
3
|
+
import * as st from "../../index";
|
|
4
|
+
describe("st.buffer", () => {
|
|
5
|
+
it("encode correctly", () => {
|
|
6
|
+
const buffer = st.sizedBuffer(st.u8());
|
|
7
|
+
expectEncode(buffer, bytes([1, 2]));
|
|
8
|
+
});
|
|
9
|
+
it("encodes empty correctly", () => {
|
|
10
|
+
const spec = st.sizedBuffer(st.u8());
|
|
11
|
+
expectEncode(spec, bytes([]));
|
|
12
|
+
});
|
|
13
|
+
it("holds large data", () => {
|
|
14
|
+
const size = 1024 * 1024 * 8; // 8MB
|
|
15
|
+
const spec = st.sizedBuffer(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.sizedBuffer(st.u8());
|
|
23
|
+
expectError(() => {
|
|
24
|
+
st.write(spec, bytes(Array.from({ length: 256 }, () => 0)));
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
});
|
|
@@ -10,6 +10,7 @@ export { sizedBuffer } from "./containers/sizedbuffer";
|
|
|
10
10
|
export { string } from "./values/string";
|
|
11
11
|
export { buffer } from "./values/buffer";
|
|
12
12
|
export { byteLiteral } from "./values/byteliteral";
|
|
13
|
+
export { createRememberedValue } from "./utilities/remember";
|
|
13
14
|
export { type Transform as Pipeline, pipe } from "./transforms/pipe";
|
|
14
15
|
export { positionOffset } from "./transforms/readOffset";
|
|
15
16
|
export { transform } from "./transforms/transform";
|
|
@@ -10,6 +10,7 @@ export { sizedBuffer } from "./containers/sizedbuffer";
|
|
|
10
10
|
export { string } from "./values/string";
|
|
11
11
|
export { buffer } from "./values/buffer";
|
|
12
12
|
export { byteLiteral } from "./values/byteliteral";
|
|
13
|
+
export { createRememberedValue } from "./utilities/remember";
|
|
13
14
|
export { pipe } from "./transforms/pipe";
|
|
14
15
|
export { positionOffset } from "./transforms/readOffset";
|
|
15
16
|
export { transform } from "./transforms/transform";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { describe, it, expect } from "bun:test";
|
|
2
|
+
import { expectEncode, expectEncodeSnapshot, expectError, randbigint } from "../utils.test";
|
|
3
|
+
import * as st from "../../index";
|
|
4
|
+
function test_bigint(options) {
|
|
5
|
+
const { name, range: [start, end], serializer, size, } = options;
|
|
6
|
+
describe(name, () => {
|
|
7
|
+
it("works in bounds", () => {
|
|
8
|
+
expectEncode(serializer, start);
|
|
9
|
+
for (let i = 0; i < 100; i++) {
|
|
10
|
+
expectEncode(serializer, randbigint(start, end));
|
|
11
|
+
}
|
|
12
|
+
expectEncode(serializer, end);
|
|
13
|
+
});
|
|
14
|
+
it("outside bounds", () => {
|
|
15
|
+
expectError(() => st.write(serializer, start - 1n));
|
|
16
|
+
expectError(() => st.write(serializer, end + 1n));
|
|
17
|
+
});
|
|
18
|
+
it(`is right size`, () => {
|
|
19
|
+
const expectValueSize = (value) => {
|
|
20
|
+
const data = st.write(serializer, value);
|
|
21
|
+
expect(data.byteLength).toBe(size);
|
|
22
|
+
};
|
|
23
|
+
for (let i = 0; i < 100; i++) {
|
|
24
|
+
expectValueSize(randbigint(start, end));
|
|
25
|
+
}
|
|
26
|
+
expectValueSize(start);
|
|
27
|
+
expectValueSize(end);
|
|
28
|
+
});
|
|
29
|
+
it(`matches snapshots`, () => {
|
|
30
|
+
expectEncodeSnapshot(serializer, 0n);
|
|
31
|
+
expectEncodeSnapshot(serializer, start);
|
|
32
|
+
expectEncodeSnapshot(serializer, start + 10n);
|
|
33
|
+
expectEncodeSnapshot(serializer, end - 10n);
|
|
34
|
+
expectEncodeSnapshot(serializer, end);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
test_bigint({
|
|
39
|
+
name: "st.u64(little)",
|
|
40
|
+
serializer: st.u64Bigint("little"),
|
|
41
|
+
range: [0n, 18446744073709551615n],
|
|
42
|
+
size: 8,
|
|
43
|
+
});
|
|
44
|
+
test_bigint({
|
|
45
|
+
name: "st.u64(big)",
|
|
46
|
+
serializer: st.u64Bigint("big"),
|
|
47
|
+
range: [0n, 18446744073709551615n],
|
|
48
|
+
size: 8,
|
|
49
|
+
});
|
|
50
|
+
test_bigint({
|
|
51
|
+
name: "st.s64(little)",
|
|
52
|
+
serializer: st.s64Bigint("little"),
|
|
53
|
+
range: [-9223372036854775808n, 9223372036854775807n],
|
|
54
|
+
size: 8,
|
|
55
|
+
});
|
|
56
|
+
test_bigint({
|
|
57
|
+
name: "st.s64(big)",
|
|
58
|
+
serializer: st.s64Bigint("big"),
|
|
59
|
+
range: [-9223372036854775808n, 9223372036854775807n],
|
|
60
|
+
size: 8,
|
|
61
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
//@ts-ignore TODO
|
|
2
|
+
import { describe, it, expect } from "bun:test";
|
|
3
|
+
import { expectEncode, expectEncodeSnapshot, expectError, randint } from "../utils.test";
|
|
4
|
+
import * as st from "../../index";
|
|
5
|
+
function test_sint(options) {
|
|
6
|
+
const { name, range: [start, end], serializer, size, } = options;
|
|
7
|
+
describe(name, () => {
|
|
8
|
+
it(`works in bounds`, () => {
|
|
9
|
+
expectEncode(serializer, start);
|
|
10
|
+
for (let i = 0; i < 100; i++) {
|
|
11
|
+
expectEncode(serializer, randint(start, end));
|
|
12
|
+
}
|
|
13
|
+
expectEncode(serializer, end);
|
|
14
|
+
});
|
|
15
|
+
it(`errors outside bounds`, () => {
|
|
16
|
+
expectError(() => st.write(serializer, start - 1));
|
|
17
|
+
expectError(() => st.write(serializer, end + 1));
|
|
18
|
+
});
|
|
19
|
+
it(`errors on decimal`, () => {
|
|
20
|
+
expectError(() => st.write(serializer, 0.1));
|
|
21
|
+
});
|
|
22
|
+
it(`is right size`, () => {
|
|
23
|
+
const expectValueSize = (value) => {
|
|
24
|
+
const data = st.write(serializer, value);
|
|
25
|
+
expect(data.byteLength).toBe(size);
|
|
26
|
+
};
|
|
27
|
+
for (let i = 0; i < 100; i++) {
|
|
28
|
+
expectValueSize(randint(start, end));
|
|
29
|
+
}
|
|
30
|
+
expectValueSize(start);
|
|
31
|
+
expectValueSize(end);
|
|
32
|
+
});
|
|
33
|
+
it(`matches snapshots`, () => {
|
|
34
|
+
expectEncodeSnapshot(serializer, 0);
|
|
35
|
+
expectEncodeSnapshot(serializer, start);
|
|
36
|
+
expectEncodeSnapshot(serializer, start + 10);
|
|
37
|
+
expectEncodeSnapshot(serializer, end - 10);
|
|
38
|
+
expectEncodeSnapshot(serializer, end);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
test_sint({
|
|
43
|
+
name: "st.s8",
|
|
44
|
+
serializer: st.s8(),
|
|
45
|
+
range: [-128, 127],
|
|
46
|
+
size: 1,
|
|
47
|
+
});
|
|
48
|
+
test_sint({
|
|
49
|
+
name: "st.s16(little)",
|
|
50
|
+
serializer: st.s16("little"),
|
|
51
|
+
range: [-32_768, 32_767],
|
|
52
|
+
size: 2,
|
|
53
|
+
});
|
|
54
|
+
test_sint({
|
|
55
|
+
name: "st.s16(big)",
|
|
56
|
+
serializer: st.s16("big"),
|
|
57
|
+
range: [-32_768, 32_767],
|
|
58
|
+
size: 2,
|
|
59
|
+
});
|
|
60
|
+
test_sint({
|
|
61
|
+
name: "st.s32(little)",
|
|
62
|
+
serializer: st.s32("little"),
|
|
63
|
+
range: [-2_147_483_648, 2_147_483_647],
|
|
64
|
+
size: 4,
|
|
65
|
+
});
|
|
66
|
+
test_sint({
|
|
67
|
+
name: "st.s32(big)",
|
|
68
|
+
serializer: st.s32("big"),
|
|
69
|
+
range: [-2_147_483_648, 2_147_483_647],
|
|
70
|
+
size: 4,
|
|
71
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
//@ts-ignore TODO
|
|
2
|
+
import { describe, it, expect } from "bun:test";
|
|
3
|
+
import { expectEncode, expectEncodeSnapshot, expectError, randint } from "../utils.test";
|
|
4
|
+
import * as st from "../../index";
|
|
5
|
+
function test_sint(options) {
|
|
6
|
+
const { name, range: [start, end], serializer, size, disableRangeCheck, } = options;
|
|
7
|
+
describe(name, () => {
|
|
8
|
+
it(`works in bounds`, () => {
|
|
9
|
+
expectEncode(serializer, start);
|
|
10
|
+
for (let i = 0; i < 100; i++) {
|
|
11
|
+
expectEncode(serializer, randint(start, end));
|
|
12
|
+
}
|
|
13
|
+
expectEncode(serializer, end);
|
|
14
|
+
});
|
|
15
|
+
if (!disableRangeCheck) {
|
|
16
|
+
it(`errors outside bounds`, () => {
|
|
17
|
+
expectError(() => st.write(serializer, start - 1));
|
|
18
|
+
expectError(() => st.write(serializer, end + 1));
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
it(`errors on decimal`, () => {
|
|
22
|
+
expectError(() => st.write(serializer, 0.1));
|
|
23
|
+
});
|
|
24
|
+
it(`is right size`, () => {
|
|
25
|
+
const expectValueSize = (value) => {
|
|
26
|
+
const data = st.write(serializer, value);
|
|
27
|
+
expect(data.byteLength).toBe(size);
|
|
28
|
+
};
|
|
29
|
+
for (let i = 0; i < 100; i++) {
|
|
30
|
+
expectValueSize(randint(start, end));
|
|
31
|
+
}
|
|
32
|
+
expectValueSize(start);
|
|
33
|
+
expectValueSize(end);
|
|
34
|
+
});
|
|
35
|
+
it(`matches snapshots`, () => {
|
|
36
|
+
expectEncodeSnapshot(serializer, 0);
|
|
37
|
+
expectEncodeSnapshot(serializer, start);
|
|
38
|
+
expectEncodeSnapshot(serializer, start + 10);
|
|
39
|
+
expectEncodeSnapshot(serializer, end - 10);
|
|
40
|
+
expectEncodeSnapshot(serializer, end);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
test_sint({
|
|
45
|
+
name: "st.s8",
|
|
46
|
+
serializer: st.s8(),
|
|
47
|
+
range: [-128, 127],
|
|
48
|
+
size: 1,
|
|
49
|
+
});
|
|
50
|
+
test_sint({
|
|
51
|
+
name: "st.s16(little)",
|
|
52
|
+
serializer: st.s16("little"),
|
|
53
|
+
range: [-32_768, 32_767],
|
|
54
|
+
size: 2,
|
|
55
|
+
});
|
|
56
|
+
test_sint({
|
|
57
|
+
name: "st.s16(big)",
|
|
58
|
+
serializer: st.s16("big"),
|
|
59
|
+
range: [-32_768, 32_767],
|
|
60
|
+
size: 2,
|
|
61
|
+
});
|
|
62
|
+
test_sint({
|
|
63
|
+
name: "st.s32(little)",
|
|
64
|
+
serializer: st.s32("little"),
|
|
65
|
+
range: [-2_147_483_648, 2_147_483_647],
|
|
66
|
+
size: 4,
|
|
67
|
+
});
|
|
68
|
+
test_sint({
|
|
69
|
+
name: "st.s32(big)",
|
|
70
|
+
serializer: st.s32("big"),
|
|
71
|
+
range: [-2_147_483_648, 2_147_483_647],
|
|
72
|
+
size: 4,
|
|
73
|
+
});
|
|
74
|
+
test_sint({
|
|
75
|
+
name: "st.s64(little)",
|
|
76
|
+
serializer: st.s64("little"),
|
|
77
|
+
range: [-(2 ** 62), 2 ** 62],
|
|
78
|
+
size: 8,
|
|
79
|
+
disableRangeCheck: true,
|
|
80
|
+
});
|
|
81
|
+
test_sint({
|
|
82
|
+
name: "st.s64(big)",
|
|
83
|
+
serializer: st.s64("big"),
|
|
84
|
+
range: [-(2 ** 62), 2 ** 62],
|
|
85
|
+
size: 8,
|
|
86
|
+
disableRangeCheck: true,
|
|
87
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
//@ts-ignore TODO
|
|
2
|
+
import { describe, it, expect } from "bun:test";
|
|
3
|
+
import { expectEncode, expectEncodeSnapshot, expectError, randint } from "../utils.test";
|
|
4
|
+
import * as st from "../../index";
|
|
5
|
+
function test_uint(options) {
|
|
6
|
+
const { name, range: [start, end], serializer, size, disableMaxCheck, } = options;
|
|
7
|
+
describe(name, () => {
|
|
8
|
+
it(`works in bounds`, () => {
|
|
9
|
+
expectEncode(serializer, start);
|
|
10
|
+
for (let i = 0; i < 100; i++) {
|
|
11
|
+
expectEncode(serializer, randint(start, end));
|
|
12
|
+
}
|
|
13
|
+
expectEncode(serializer, end);
|
|
14
|
+
});
|
|
15
|
+
it(`errors outside bounds`, () => {
|
|
16
|
+
expectError(() => st.write(serializer, start - 1));
|
|
17
|
+
if (!disableMaxCheck) {
|
|
18
|
+
expectError(() => st.write(serializer, end + 1));
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
it(`errors on decimal`, () => {
|
|
22
|
+
expectError(() => st.write(serializer, 0.1));
|
|
23
|
+
});
|
|
24
|
+
it(`is right size`, () => {
|
|
25
|
+
const expectValueSize = (value) => {
|
|
26
|
+
const data = st.write(serializer, value);
|
|
27
|
+
expect(data.byteLength).toBe(size);
|
|
28
|
+
};
|
|
29
|
+
for (let i = 0; i < 100; i++) {
|
|
30
|
+
expectValueSize(randint(start, end));
|
|
31
|
+
}
|
|
32
|
+
expectValueSize(start);
|
|
33
|
+
expectValueSize(end);
|
|
34
|
+
});
|
|
35
|
+
it(`matches snapshots`, () => {
|
|
36
|
+
expectEncodeSnapshot(serializer, 0);
|
|
37
|
+
expectEncodeSnapshot(serializer, start);
|
|
38
|
+
expectEncodeSnapshot(serializer, start + 10);
|
|
39
|
+
expectEncodeSnapshot(serializer, end - 10);
|
|
40
|
+
expectEncodeSnapshot(serializer, end);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
test_uint({
|
|
45
|
+
name: "st.u8",
|
|
46
|
+
serializer: st.u8(),
|
|
47
|
+
range: [0, 255],
|
|
48
|
+
size: 1,
|
|
49
|
+
});
|
|
50
|
+
test_uint({
|
|
51
|
+
name: "st.u16(little)",
|
|
52
|
+
serializer: st.u16("little"),
|
|
53
|
+
range: [0, 65_535],
|
|
54
|
+
size: 2,
|
|
55
|
+
});
|
|
56
|
+
test_uint({
|
|
57
|
+
name: "st.u16(big)",
|
|
58
|
+
serializer: st.u16("big"),
|
|
59
|
+
range: [0, 65_535],
|
|
60
|
+
size: 2,
|
|
61
|
+
});
|
|
62
|
+
test_uint({
|
|
63
|
+
name: "st.u32(little)",
|
|
64
|
+
serializer: st.u32("little"),
|
|
65
|
+
range: [0, 4_294_967_295],
|
|
66
|
+
size: 4,
|
|
67
|
+
});
|
|
68
|
+
test_uint({
|
|
69
|
+
name: "st.u32(big)",
|
|
70
|
+
serializer: st.u32("big"),
|
|
71
|
+
range: [0, 4_294_967_295],
|
|
72
|
+
size: 4,
|
|
73
|
+
});
|
|
74
|
+
test_uint({
|
|
75
|
+
name: "st.u64(little)",
|
|
76
|
+
serializer: st.u64("little"),
|
|
77
|
+
range: [0, 2 ** 63],
|
|
78
|
+
size: 8,
|
|
79
|
+
disableMaxCheck: true,
|
|
80
|
+
});
|
|
81
|
+
test_uint({
|
|
82
|
+
name: "st.u64(big)",
|
|
83
|
+
serializer: st.u64("big"),
|
|
84
|
+
range: [0, 2 ** 63],
|
|
85
|
+
size: 8,
|
|
86
|
+
disableMaxCheck: true,
|
|
87
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { describe, it } from "bun:test";
|
|
2
|
+
import { bytes, expectEncode } from "../utils.test";
|
|
3
|
+
import * as st from "../../index";
|
|
4
|
+
describe("st.pipe", () => {
|
|
5
|
+
it("applies correctly", () => {
|
|
6
|
+
const buffer = st.sizedBuffer(st.u8());
|
|
7
|
+
expectEncode(buffer, bytes([1, 2]));
|
|
8
|
+
});
|
|
9
|
+
it("runs in correct order", () => {
|
|
10
|
+
const spec = st.sizedBuffer(st.u8());
|
|
11
|
+
expectEncode(spec, bytes([]));
|
|
12
|
+
});
|
|
13
|
+
});
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function createRememberedValue() {
|
|
2
|
+
const stack = [];
|
|
3
|
+
function store(serializer) {
|
|
4
|
+
return {
|
|
5
|
+
size: serializer.size,
|
|
6
|
+
read: (ctx) => {
|
|
7
|
+
const value = serializer.read(ctx);
|
|
8
|
+
stack.push(value);
|
|
9
|
+
return value;
|
|
10
|
+
},
|
|
11
|
+
write: (ctx, value) => {
|
|
12
|
+
serializer.write(ctx, value);
|
|
13
|
+
stack.push(value);
|
|
14
|
+
return value;
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function load() {
|
|
19
|
+
return {
|
|
20
|
+
size: 0,
|
|
21
|
+
read: () => stack.pop(),
|
|
22
|
+
write: () => { },
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return { save: store, load: load };
|
|
26
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
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: <T>(serializer: st.Serializer<T>, value: T) => void;
|
|
5
|
+
export declare const expectEncodeSnapshot: <T>(serializer: st.Serializer<T>, value: T) => void;
|
|
6
|
+
export declare const expectError: (callback: () => void) => void;
|
|
7
|
+
export declare const bytes: (bytes: number[]) => ArrayBuffer;
|
|
@@ -0,0 +1,33 @@
|
|
|
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) => {
|
|
14
|
+
const data = st.write(serializer, value);
|
|
15
|
+
const newValue = st.read(serializer, data);
|
|
16
|
+
expect(value).toEqual(newValue);
|
|
17
|
+
};
|
|
18
|
+
export const expectEncodeSnapshot = (serializer, value) => {
|
|
19
|
+
const data = st.write(serializer, value);
|
|
20
|
+
expect(data).toMatchSnapshot();
|
|
21
|
+
};
|
|
22
|
+
export const expectError = (callback) => {
|
|
23
|
+
try {
|
|
24
|
+
callback();
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
throw new Error("Expected Error");
|
|
30
|
+
};
|
|
31
|
+
export const bytes = (bytes) => {
|
|
32
|
+
return new Uint8Array(bytes).buffer;
|
|
33
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { describe, it } from "bun:test";
|
|
2
|
+
import { bytes, expectEncode, expectError } from "../utils.test";
|
|
3
|
+
import * as st from "../../index";
|
|
4
|
+
describe("st.buffer", () => {
|
|
5
|
+
const buffer = st.buffer(2);
|
|
6
|
+
it("encode correctly", () => {
|
|
7
|
+
expectEncode(buffer, bytes([1, 2]));
|
|
8
|
+
});
|
|
9
|
+
it("encodes empty correctly", () => {
|
|
10
|
+
const spec = st.buffer(0);
|
|
11
|
+
expectEncode(spec, bytes([]));
|
|
12
|
+
});
|
|
13
|
+
it("holds large data", () => {
|
|
14
|
+
const size = 1024 * 1024 * 8; // 8MB
|
|
15
|
+
const spec = st.buffer(size);
|
|
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("large data writes work", () => {
|
|
22
|
+
const size = 1024 * 1024 * 8; // 8MB
|
|
23
|
+
const spec = st.object({
|
|
24
|
+
before: st.u8(),
|
|
25
|
+
data: st.buffer(size),
|
|
26
|
+
after: st.u8(),
|
|
27
|
+
});
|
|
28
|
+
const data = new Uint8Array(size);
|
|
29
|
+
data.set([3, 4], 1000);
|
|
30
|
+
data.set([3, 4], 2000);
|
|
31
|
+
expectEncode(spec, {
|
|
32
|
+
before: 1,
|
|
33
|
+
data: data.buffer,
|
|
34
|
+
after: 2,
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
it("errors on invalid length", () => {
|
|
38
|
+
const spec = st.buffer(5);
|
|
39
|
+
expectError(() => {
|
|
40
|
+
st.write(spec, bytes([1, 2, 3, 4]));
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
});
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
export function string(length) {
|
|
2
|
-
const { read: readLength, write: writeLength } = length;
|
|
2
|
+
const { read: readLength, write: writeLength, size: lengthSize = 0 } = length;
|
|
3
3
|
const encoder = new TextEncoder();
|
|
4
4
|
const decoder = new TextDecoder();
|
|
5
5
|
return {
|
|
6
6
|
write: (ctx, value) => {
|
|
7
7
|
const bytes = encoder.encode(value);
|
|
8
|
-
|
|
9
|
-
ctx.alloc(
|
|
10
|
-
|
|
11
|
-
arr.
|
|
12
|
-
|
|
8
|
+
const length = bytes.byteLength;
|
|
9
|
+
ctx.alloc(length + lengthSize);
|
|
10
|
+
writeLength(ctx, length);
|
|
11
|
+
const arr = new Uint8Array(ctx.buffer, ctx.offset);
|
|
12
|
+
arr.set(bytes);
|
|
13
|
+
ctx.offset += length;
|
|
13
14
|
},
|
|
14
15
|
read: (ctx) => {
|
|
15
16
|
const length = readLength(ctx);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
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 too long strings", () => {
|
|
14
|
+
expectError(() => {
|
|
15
|
+
st.write(string_u8, "A".repeat(256));
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
});
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -20,8 +20,8 @@ export function createdWriterContext(type) {
|
|
|
20
20
|
};
|
|
21
21
|
}
|
|
22
22
|
else {
|
|
23
|
-
let bufferLength =
|
|
24
|
-
let buffer = new ArrayBuffer(bufferLength);
|
|
23
|
+
let bufferLength = 128;
|
|
24
|
+
let buffer = new ArrayBuffer(bufferLength, { maxByteLength: 1024 });
|
|
25
25
|
const view = new DataView(buffer);
|
|
26
26
|
return {
|
|
27
27
|
offset: 0,
|
|
@@ -30,9 +30,11 @@ export function createdWriterContext(type) {
|
|
|
30
30
|
alloc(length) {
|
|
31
31
|
if (length < 0)
|
|
32
32
|
return;
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
if (buffer.resizable) {
|
|
34
|
+
}
|
|
35
|
+
while (this.offset + length > bufferLength) {
|
|
36
|
+
bufferLength = bufferLength * 2;
|
|
37
|
+
this.buffer.resize(bufferLength);
|
|
36
38
|
this.view = new DataView(this.buffer);
|
|
37
39
|
}
|
|
38
40
|
},
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"description": "A library for serializing and deserializing binary content",
|
|
4
4
|
"keywords": ["binary", "library", "utility", "web", "node"],
|
|
5
5
|
"license": "ISC",
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.3",
|
|
7
7
|
"author": "Ben Brady",
|
|
8
8
|
"private": false,
|
|
9
9
|
"publishConfig": {"access": "public"},
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { InferInput, Serializer } from "../../types";
|
|
2
|
-
type InferObject<T> = T extends Record<string, Serializer<any>> ? {
|
|
3
|
-
[Key in keyof T]: InferInput<T[Key]>;
|
|
4
|
-
} : never;
|
|
5
|
-
export declare function fastObject<T extends Record<string, Serializer<any>>>(definition: T): Serializer<InferObject<T>>;
|
|
6
|
-
export {};
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export type { InferInput as Infer, InferInput, InferOutput, ReaderContext, WriterContext, Serializer, } from "./types";
|
|
2
2
|
export * from "./datatypes";
|
|
3
|
-
export { write, createdWriterContext } from "./write";
|
|
4
3
|
export { read, createReaderContext } from "./read";
|
|
4
|
+
export { write, createdWriterContext } from "./write";
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|