@nnilky/structo 1.0.5 → 1.0.7
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/dist/datatypes/containers/array.test.js +6 -10
- package/dist/datatypes/containers/exhuastiveArray.test.js +9 -12
- package/dist/datatypes/containers/fastObject.d.ts +2 -0
- package/dist/datatypes/containers/fastObject.js +2 -0
- package/dist/datatypes/containers/fastObject.test.js +18 -6
- package/dist/datatypes/containers/list.test.js +6 -12
- package/dist/datatypes/containers/object.js +7 -1
- package/dist/datatypes/containers/object.test.js +22 -10
- package/dist/datatypes/containers/taggedUnion.d.ts +12 -8
- package/dist/datatypes/containers/taggedUnion.js +4 -2
- package/dist/datatypes/containers/taggedUnion.test.js +22 -18
- package/dist/datatypes/index.d.ts +2 -9
- package/dist/datatypes/index.js +2 -9
- package/dist/datatypes/numbers/bigints.test.js +11 -11
- package/dist/datatypes/numbers/floats.test.js +6 -6
- package/dist/datatypes/numbers/sints.test.js +11 -11
- package/dist/datatypes/numbers/uints.test.js +11 -11
- package/dist/datatypes/values/bytes.test.js +6 -8
- package/dist/datatypes/values/json.d.ts +10 -0
- package/dist/datatypes/values/json.js +21 -0
- package/dist/datatypes/values/sizedbytes.d.ts +2 -0
- package/dist/datatypes/values/sizedbytes.js +17 -0
- package/dist/datatypes/values/sizedbytes.test.d.ts +1 -0
- package/dist/datatypes/values/sizedbytes.test.js +25 -0
- package/dist/datatypes/values/string.d.ts +14 -0
- package/dist/datatypes/values/string.js +36 -0
- package/dist/datatypes/values/string.test.d.ts +1 -0
- package/dist/datatypes/values/string.test.js +18 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/transforms/encode.d.ts +2 -0
- package/dist/transforms/encode.js +7 -0
- package/dist/transforms/enum.d.ts +2 -0
- package/dist/transforms/enum.js +13 -0
- package/dist/transforms/enum.test.d.ts +1 -0
- package/dist/transforms/enum.test.js +21 -0
- package/dist/transforms/fixedOffset.d.ts +2 -0
- package/dist/transforms/fixedOffset.js +18 -0
- package/dist/transforms/index.d.ts +12 -0
- package/dist/transforms/index.js +12 -0
- package/dist/transforms/literal.d.ts +1 -0
- package/dist/transforms/literal.js +12 -0
- package/dist/transforms/literal.test.d.ts +1 -0
- package/dist/transforms/literal.test.js +23 -0
- package/dist/transforms/modify.d.ts +2 -0
- package/dist/transforms/modify.js +7 -0
- package/dist/transforms/noAdvance.d.ts +16 -0
- package/dist/transforms/noAdvance.js +30 -0
- package/dist/transforms/noAdvance.test.d.ts +1 -0
- package/dist/transforms/noAdvance.test.js +17 -0
- package/dist/transforms/pipe.d.ts +11 -0
- package/dist/transforms/pipe.js +16 -0
- package/dist/transforms/toAscii.d.ts +1 -0
- package/dist/transforms/toAscii.js +11 -0
- package/dist/transforms/toAscii.test.d.ts +1 -0
- package/dist/transforms/toAscii.test.js +25 -0
- package/dist/transforms/toBase64.d.ts +1 -0
- package/dist/transforms/toBase64.js +4 -0
- package/dist/transforms/toBase64.test.d.ts +1 -0
- package/dist/transforms/toBase64.test.js +27 -0
- package/dist/transforms/toBytes.d.ts +13 -0
- package/dist/transforms/toBytes.js +21 -0
- package/dist/transforms/toBytes.test.d.ts +1 -0
- package/dist/transforms/toBytes.test.js +27 -0
- package/dist/transforms/toHex.d.ts +13 -0
- package/dist/transforms/toHex.js +16 -0
- package/dist/transforms/toHex.test.d.ts +1 -0
- package/dist/transforms/toHex.test.js +23 -0
- package/dist/transforms/toTypedArray.d.ts +16 -0
- package/dist/transforms/toTypedArray.js +14 -0
- package/dist/transforms/toTypedArray.test.d.ts +1 -0
- package/dist/transforms/toTypedArray.test.js +29 -0
- package/dist/utilities/index.d.ts +2 -0
- package/dist/utilities/index.js +2 -0
- package/dist/utilities/lazy.d.ts +2 -0
- package/dist/utilities/lazy.js +25 -0
- package/dist/utilities/lazy.test.d.ts +1 -0
- package/dist/utilities/lazy.test.js +36 -0
- package/dist/utilities/remember.d.ts +17 -0
- package/dist/utilities/remember.js +38 -0
- package/dist/utilities/remember.test.d.ts +1 -0
- package/dist/utilities/remember.test.js +76 -0
- package/dist/utils.test.d.ts +9 -1
- package/dist/utils.test.js +42 -1
- package/package.json +12 -7
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
type TypedArray = {
|
|
2
|
+
buffer: ArrayBuffer;
|
|
3
|
+
};
|
|
4
|
+
type TypedArrayConstructor<T extends TypedArray> = new (array: ArrayBuffer) => T;
|
|
5
|
+
/**
|
|
6
|
+
* Converts an `ArrayBuffer` to a `TypedArray`
|
|
7
|
+
*
|
|
8
|
+
* ```
|
|
9
|
+
* st.pipe(
|
|
10
|
+
* st.bytes(16),
|
|
11
|
+
* toTypedArray(Uint8Array),
|
|
12
|
+
* )
|
|
13
|
+
* ```
|
|
14
|
+
*/
|
|
15
|
+
export declare function toTypedArray<T extends TypedArray>(arrayType: TypedArrayConstructor<T>): import("./pipe").Transform<T, ArrayBuffer>;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { encode } from "./encode";
|
|
2
|
+
/**
|
|
3
|
+
* Converts an `ArrayBuffer` to a `TypedArray`
|
|
4
|
+
*
|
|
5
|
+
* ```
|
|
6
|
+
* st.pipe(
|
|
7
|
+
* st.bytes(16),
|
|
8
|
+
* toTypedArray(Uint8Array),
|
|
9
|
+
* )
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export function toTypedArray(arrayType) {
|
|
13
|
+
return encode((v) => v.buffer, (v) => new arrayType(v));
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { describe, it } from "bun:test";
|
|
2
|
+
import { encodeTest, encodeSnapshotTest, expectError } from "../utils.test";
|
|
3
|
+
import * as st from "../index";
|
|
4
|
+
describe("st.toArrayBuffer", () => {
|
|
5
|
+
it("encode correctly", () => {
|
|
6
|
+
encodeTest(st.pipe(st.bytes(6), //
|
|
7
|
+
st.toTypedArray(Uint8Array)), new Uint8Array([1, 2, 3, 4, 5, 6]));
|
|
8
|
+
});
|
|
9
|
+
it("encode different types correctly", () => {
|
|
10
|
+
encodeTest(st.pipe(st.bytes(3), //
|
|
11
|
+
st.toTypedArray(Uint8Array)), new Uint8Array([1, 2, 3]));
|
|
12
|
+
encodeTest(st.pipe(st.bytes(5 * 2), //
|
|
13
|
+
st.toTypedArray(Uint16Array)), new Uint16Array([1, 2, 3, 63, 74]));
|
|
14
|
+
encodeTest(st.pipe(st.bytes(3 * 8), //
|
|
15
|
+
st.toTypedArray(Float64Array)), new Float64Array([Math.random(), Math.random(), Math.random()]));
|
|
16
|
+
});
|
|
17
|
+
it("errors on different types", () => {
|
|
18
|
+
expectError(() => {
|
|
19
|
+
st.write(st.pipe(st.bytes(3), //
|
|
20
|
+
st.toTypedArray(Uint16Array)), new Uint16Array([1]));
|
|
21
|
+
});
|
|
22
|
+
});
|
|
23
|
+
it("snapshot tests", () => {
|
|
24
|
+
encodeSnapshotTest(st.pipe(st.bytes(4 * 2), //
|
|
25
|
+
st.toTypedArray(Uint16Array)), new Uint16Array([1, 6, 3, 12]));
|
|
26
|
+
encodeSnapshotTest(st.pipe(st.bytes(3 * 8), //
|
|
27
|
+
st.toTypedArray(Float64Array)), new Float64Array([1.52, 0.3523, 0.152]));
|
|
28
|
+
});
|
|
29
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function lazy(type) {
|
|
2
|
+
let _size;
|
|
3
|
+
let resolve = () => {
|
|
4
|
+
const t = type();
|
|
5
|
+
_size = t.size ?? undefined;
|
|
6
|
+
serializer.read = t.read;
|
|
7
|
+
serializer.write = t.write;
|
|
8
|
+
resolve = () => { };
|
|
9
|
+
};
|
|
10
|
+
const serializer = {
|
|
11
|
+
get size() {
|
|
12
|
+
resolve();
|
|
13
|
+
return _size;
|
|
14
|
+
},
|
|
15
|
+
read(ctx) {
|
|
16
|
+
resolve();
|
|
17
|
+
return this.read(ctx);
|
|
18
|
+
},
|
|
19
|
+
write(ctx, value) {
|
|
20
|
+
resolve();
|
|
21
|
+
return this.write(ctx, value);
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
return serializer;
|
|
25
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
|
+
import { encodeTest } from "../utils.test";
|
|
3
|
+
import * as st from "../index";
|
|
4
|
+
describe("st.lazy", () => {
|
|
5
|
+
it("encodes correctly", () => {
|
|
6
|
+
const spec = st.lazy(() => st.object({
|
|
7
|
+
a: st.array(4, st.u8()),
|
|
8
|
+
b: st.u16(),
|
|
9
|
+
}));
|
|
10
|
+
encodeTest(spec, {
|
|
11
|
+
a: [1, 2, 3, 4],
|
|
12
|
+
b: 2,
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
it("nested objects function", () => {
|
|
16
|
+
const spec = st.object({
|
|
17
|
+
a: st.array(4, st.u8()),
|
|
18
|
+
b: st.lazy(() => st.object({
|
|
19
|
+
a: st.lazy(() => st.u16()),
|
|
20
|
+
})),
|
|
21
|
+
});
|
|
22
|
+
encodeTest(spec, {
|
|
23
|
+
a: [1, 2, 3, 4],
|
|
24
|
+
b: { a: 1 },
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
it("size is calculated correctly", () => {
|
|
28
|
+
const spec = st.lazy(() => st.object({
|
|
29
|
+
b: st.lazy(() => st.object({
|
|
30
|
+
a: st.u32(),
|
|
31
|
+
b: st.u8(),
|
|
32
|
+
})),
|
|
33
|
+
}));
|
|
34
|
+
expect(spec.size).toBe(5);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Serializer } from "../types";
|
|
2
|
+
/**
|
|
3
|
+
* createRememberedValue lets you save and recall a value when serializing
|
|
4
|
+
*
|
|
5
|
+
* ```
|
|
6
|
+
* const length = st.createRememberedValue<number>()
|
|
7
|
+
* st.object({
|
|
8
|
+
* length: length.save(st.u32()),
|
|
9
|
+
* type: st.u8(),
|
|
10
|
+
* data: st.sizedBytes(length.load())
|
|
11
|
+
* })
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export declare function createRememberedValue<T>(): {
|
|
15
|
+
save: (serializer: Serializer<T>) => Serializer<T>;
|
|
16
|
+
load: (serializer?: Serializer<T>) => Serializer<T>;
|
|
17
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* createRememberedValue lets you save and recall a value when serializing
|
|
3
|
+
*
|
|
4
|
+
* ```
|
|
5
|
+
* const length = st.createRememberedValue<number>()
|
|
6
|
+
* st.object({
|
|
7
|
+
* length: length.save(st.u32()),
|
|
8
|
+
* type: st.u8(),
|
|
9
|
+
* data: st.sizedBytes(length.load())
|
|
10
|
+
* })
|
|
11
|
+
* ```
|
|
12
|
+
*/
|
|
13
|
+
export function createRememberedValue() {
|
|
14
|
+
const stack = [];
|
|
15
|
+
function save(serializer) {
|
|
16
|
+
return {
|
|
17
|
+
size: serializer.size,
|
|
18
|
+
read: (ctx) => {
|
|
19
|
+
const value = serializer.read(ctx);
|
|
20
|
+
stack.push(value);
|
|
21
|
+
return value;
|
|
22
|
+
},
|
|
23
|
+
write: (ctx, value) => {
|
|
24
|
+
serializer.write(ctx, value);
|
|
25
|
+
stack.push(value);
|
|
26
|
+
return value;
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function load(serializer) {
|
|
31
|
+
return {
|
|
32
|
+
size: serializer?.size ?? 0,
|
|
33
|
+
read: () => stack.pop(),
|
|
34
|
+
write: (ctx) => serializer && serializer.write(ctx, stack.pop()),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
return { save: save, load: load };
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { describe, expect, it } from "bun:test";
|
|
2
|
+
import { encodeTest, encodeSnapshotTest } from "../utils.test";
|
|
3
|
+
import * as st from "../index";
|
|
4
|
+
describe("st.remember", () => {
|
|
5
|
+
it("encodes correctly", () => {
|
|
6
|
+
const v = st.createRememberedValue();
|
|
7
|
+
const spec = st.object({
|
|
8
|
+
a: v.save(st.u32()),
|
|
9
|
+
b: st.list(v.load(), st.u8()),
|
|
10
|
+
});
|
|
11
|
+
encodeTest(spec, {
|
|
12
|
+
a: 3,
|
|
13
|
+
b: [1, 3, 4],
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
it("multiple runs function", () => {
|
|
17
|
+
const v = st.createRememberedValue();
|
|
18
|
+
const spec = st.object({
|
|
19
|
+
a: v.save(st.u32()),
|
|
20
|
+
b: st.list(v.load(), st.u8()),
|
|
21
|
+
});
|
|
22
|
+
encodeTest(spec, { a: 3, b: [1, 3, 4] });
|
|
23
|
+
encodeTest(spec, { a: 3, b: [1, 3, 4] });
|
|
24
|
+
encodeTest(spec, { a: 3, b: [1, 3, 4] });
|
|
25
|
+
});
|
|
26
|
+
it("omitted serializer doesn't write data ", () => {
|
|
27
|
+
const v = st.createRememberedValue();
|
|
28
|
+
const spec = st.object({
|
|
29
|
+
a: v.save(st.u32()),
|
|
30
|
+
b: v.load(),
|
|
31
|
+
});
|
|
32
|
+
const output = st.write(spec, { a: 3, b: 0 });
|
|
33
|
+
expect(spec.size).toBe(4);
|
|
34
|
+
expect(output.byteLength).toBe(4);
|
|
35
|
+
});
|
|
36
|
+
it("serializer is used write data ", () => {
|
|
37
|
+
const v = st.createRememberedValue();
|
|
38
|
+
const spec = st.object({
|
|
39
|
+
a: v.save(st.u32()),
|
|
40
|
+
b: v.load(st.u8()),
|
|
41
|
+
});
|
|
42
|
+
encodeTest(spec, { a: 3, b: 0 }, { a: 3, b: 3 });
|
|
43
|
+
});
|
|
44
|
+
it("handles recursive objects", () => {
|
|
45
|
+
const size = st.createRememberedValue();
|
|
46
|
+
//@ts-expect-error, recursive types
|
|
47
|
+
const Node = st.lazy(() => st.object({
|
|
48
|
+
size: size.save(st.u32()),
|
|
49
|
+
children: st.list(size.load(), Node),
|
|
50
|
+
}));
|
|
51
|
+
encodeTest(Node, {
|
|
52
|
+
size: 2,
|
|
53
|
+
children: [
|
|
54
|
+
{ size: 0, children: [] },
|
|
55
|
+
{
|
|
56
|
+
size: 1,
|
|
57
|
+
children: [{ size: 0, children: [] }],
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
it("snapshots are correct", () => {
|
|
63
|
+
const v = st.createRememberedValue();
|
|
64
|
+
encodeSnapshotTest(st.object({
|
|
65
|
+
a: v.save(st.u32()),
|
|
66
|
+
b: st.list(v.load(), st.u8()),
|
|
67
|
+
}), {
|
|
68
|
+
a: 3,
|
|
69
|
+
b: [1, 3, 4],
|
|
70
|
+
});
|
|
71
|
+
encodeSnapshotTest(st.object({
|
|
72
|
+
a: v.save(st.u32()),
|
|
73
|
+
b: v.load(st.u8()),
|
|
74
|
+
}), { a: 3, b: 0 });
|
|
75
|
+
});
|
|
76
|
+
});
|
package/dist/utils.test.d.ts
CHANGED
|
@@ -1 +1,9 @@
|
|
|
1
|
-
|
|
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 encodeTest: <TIn, TOut>(serializer: st.Serializer<TIn, TOut>, value: TIn, expected?: TOut) => void;
|
|
5
|
+
export declare const encodeFailTest: <TIn, TOut>(serializer: st.Serializer<TIn, TOut>, value: TIn) => void;
|
|
6
|
+
export declare const expectEncodeSize: <TIn, TOut>(serializer: st.Serializer<TIn, TOut>, size: number, value: TIn) => void;
|
|
7
|
+
export declare const encodeSnapshotTest: <T>(serializer: st.Serializer<T>, value: T) => void;
|
|
8
|
+
export declare const expectError: (callback: () => void) => void;
|
|
9
|
+
export declare const bytes: (bytes: number[]) => ArrayBuffer;
|
package/dist/utils.test.js
CHANGED
|
@@ -1 +1,42 @@
|
|
|
1
|
-
|
|
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 encodeTest = (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 encodeFailTest = (serializer, value) => {
|
|
19
|
+
expectError(() => {
|
|
20
|
+
st.write(serializer, value);
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
export const expectEncodeSize = (serializer, size, value) => {
|
|
24
|
+
const data = st.write(serializer, value);
|
|
25
|
+
expect(data.byteLength).toEqual(size);
|
|
26
|
+
};
|
|
27
|
+
export const encodeSnapshotTest = (serializer, value) => {
|
|
28
|
+
const data = st.write(serializer, value);
|
|
29
|
+
expect(data).toMatchSnapshot();
|
|
30
|
+
};
|
|
31
|
+
export const expectError = (callback) => {
|
|
32
|
+
try {
|
|
33
|
+
callback();
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
throw new Error("Expected Error");
|
|
39
|
+
};
|
|
40
|
+
export const bytes = (bytes) => {
|
|
41
|
+
return new Uint8Array(bytes).buffer;
|
|
42
|
+
};
|
package/package.json
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nnilky/structo",
|
|
3
3
|
"description": "A library for serializing and deserializing binary content",
|
|
4
|
-
"keywords": [
|
|
4
|
+
"keywords": [
|
|
5
|
+
"binary",
|
|
6
|
+
"library",
|
|
7
|
+
"utility",
|
|
8
|
+
"web",
|
|
9
|
+
"node"
|
|
10
|
+
],
|
|
5
11
|
"license": "ISC",
|
|
6
|
-
"version": "1.0.
|
|
12
|
+
"version": "1.0.7",
|
|
7
13
|
"author": "Ben Brady",
|
|
8
14
|
"private": false,
|
|
9
|
-
"publishConfig": {
|
|
10
|
-
|
|
15
|
+
"publishConfig": {
|
|
16
|
+
"access": "public"
|
|
17
|
+
},
|
|
11
18
|
"repository": {
|
|
12
19
|
"type": "git",
|
|
13
20
|
"url": "git+https://github.com/Ben-Brady/structo-ts.git"
|
|
14
21
|
},
|
|
15
|
-
|
|
16
22
|
"readme": "README.md",
|
|
17
23
|
"type": "module",
|
|
18
24
|
"main": "./dist/index.js",
|
|
@@ -38,12 +44,11 @@
|
|
|
38
44
|
"./dist/**/*.js.map",
|
|
39
45
|
"./dist/**/*.js"
|
|
40
46
|
],
|
|
41
|
-
|
|
42
47
|
"scripts": {
|
|
43
48
|
"build": "tsc",
|
|
44
49
|
"prepublish": "tsc",
|
|
45
50
|
"check": "tsc --noEmit",
|
|
46
|
-
"test": "
|
|
51
|
+
"test": "bun test src --only-failures --coverage"
|
|
47
52
|
},
|
|
48
53
|
"devDependencies": {
|
|
49
54
|
"@types/bun": "^1.3.14",
|