@nnilky/structo 1.0.4 → 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/README.md +1 -1
- package/dist/datatypes/containers/array.d.ts +8 -0
- package/dist/datatypes/containers/array.js +8 -0
- package/dist/datatypes/containers/array.test.js +6 -10
- package/dist/datatypes/containers/exhuastiveArray.d.ts +9 -0
- package/dist/datatypes/containers/exhuastiveArray.js +24 -0
- package/dist/datatypes/containers/exhuastiveArray.test.js +38 -0
- package/dist/datatypes/containers/fastObject.d.ts +2 -0
- package/dist/datatypes/containers/fastObject.js +2 -0
- package/dist/datatypes/containers/fastObject.test.js +45 -0
- package/dist/datatypes/containers/list.d.ts +11 -4
- package/dist/datatypes/containers/list.js +17 -9
- package/dist/datatypes/containers/list.test.js +9 -17
- package/dist/datatypes/containers/object.js +7 -1
- package/dist/datatypes/containers/object.test.js +23 -11
- package/dist/datatypes/containers/sizedbytes.d.ts +2 -0
- package/dist/datatypes/containers/{sizedbuffer.js → sizedbytes.js} +1 -1
- package/dist/datatypes/containers/{sizedbuffer.test.js → sizedbytes.test.js} +5 -5
- package/dist/datatypes/containers/string.d.ts +2 -0
- package/dist/datatypes/containers/string.js +24 -0
- package/dist/datatypes/containers/string.test.js +24 -0
- package/dist/datatypes/containers/taggedUnion.d.ts +26 -0
- package/dist/datatypes/containers/taggedUnion.js +35 -0
- package/dist/datatypes/containers/taggedUnion.test.js +67 -0
- package/dist/datatypes/index.d.ts +5 -8
- package/dist/datatypes/index.js +5 -8
- package/dist/datatypes/numbers/bigints.d.ts +10 -0
- package/dist/datatypes/numbers/bigints.js +10 -0
- package/dist/datatypes/numbers/bigints.test.js +11 -11
- package/dist/datatypes/numbers/floats.d.ts +4 -0
- package/dist/datatypes/numbers/floats.js +18 -0
- package/dist/datatypes/numbers/floats.test.js +49 -47
- package/dist/datatypes/numbers/sints.d.ts +4 -0
- package/dist/datatypes/numbers/sints.js +4 -0
- package/dist/datatypes/numbers/sints.test.js +11 -11
- package/dist/datatypes/numbers/uints.d.ts +4 -0
- package/dist/datatypes/numbers/uints.js +4 -0
- package/dist/datatypes/numbers/uints.test.js +11 -11
- package/dist/datatypes/transforms/encode.d.ts +2 -0
- package/dist/datatypes/transforms/encode.js +7 -0
- package/dist/datatypes/transforms/fixedOffset.d.ts +2 -0
- package/dist/datatypes/transforms/{readOffset.js → fixedOffset.js} +1 -1
- package/dist/datatypes/transforms/modify.d.ts +2 -0
- package/dist/datatypes/transforms/modify.js +7 -0
- package/dist/datatypes/transforms/noAdvance.d.ts +16 -0
- package/dist/datatypes/transforms/noAdvance.js +30 -0
- package/dist/datatypes/transforms/pipe.js +12 -0
- package/dist/datatypes/utilities/remember.d.ts +11 -1
- package/dist/datatypes/utilities/remember.js +15 -5
- package/dist/datatypes/utilities/remember.test.d.ts +1 -0
- package/dist/datatypes/utilities/remember.test.js +44 -0
- package/dist/datatypes/utils.test.d.ts +2 -1
- package/dist/datatypes/utils.test.js +6 -2
- package/dist/datatypes/values/byteliteral.d.ts +1 -1
- package/dist/datatypes/values/byteliteral.js +1 -1
- package/dist/datatypes/values/bytes.d.ts +9 -0
- package/dist/datatypes/values/{buffer.js → bytes.js} +8 -1
- package/dist/datatypes/values/bytes.test.d.ts +1 -0
- package/dist/datatypes/values/{buffer.test.js → bytes.test.js} +12 -14
- 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 +12 -0
- package/dist/datatypes/values/string.js +22 -8
- package/dist/datatypes/values/string.test.js +8 -8
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/read.d.ts +1 -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/dist/write.d.ts +1 -1
- package/package.json +12 -7
- package/dist/datatypes/containers/sizedbuffer.d.ts +0 -2
- package/dist/datatypes/transforms/pipe.test.js +0 -13
- package/dist/datatypes/transforms/readOffset.d.ts +0 -2
- package/dist/datatypes/transforms/transform.d.ts +0 -2
- package/dist/datatypes/transforms/transform.js +0 -13
- package/dist/datatypes/utilities/constant.d.ts +0 -2
- package/dist/datatypes/utilities/constant.js +0 -13
- package/dist/datatypes/values/buffer.d.ts +0 -2
- /package/dist/datatypes/containers/{sizedbuffer.test.d.ts → exhuastiveArray.test.d.ts} +0 -0
- /package/dist/datatypes/{lazy.d.ts → containers/fastObject.test.d.ts} +0 -0
- /package/dist/datatypes/{lazy.js → containers/sizedbytes.test.d.ts} +0 -0
- /package/dist/datatypes/{transforms/pipe.test.d.ts → containers/string.test.d.ts} +0 -0
- /package/dist/datatypes/{values/buffer.test.d.ts → containers/taggedUnion.test.d.ts} +0 -0
|
@@ -1,3 +1,13 @@
|
|
|
1
1
|
import type { Serializer } from "../../types";
|
|
2
|
+
/**
|
|
3
|
+
* 64bit unsigned interger
|
|
4
|
+
*
|
|
5
|
+
* This version uses bigints to ensure accuracy is not lost
|
|
6
|
+
*/
|
|
2
7
|
export declare function u64Bigint(endian?: "little" | "big"): Serializer<number | bigint, bigint>;
|
|
8
|
+
/**
|
|
9
|
+
* 64bit signed interger
|
|
10
|
+
*
|
|
11
|
+
* This version uses bigints to ensure accuracy is not lost
|
|
12
|
+
*/
|
|
3
13
|
export declare function s64Bigint(endian?: "little" | "big"): Serializer<number | bigint, bigint>;
|
|
@@ -3,6 +3,11 @@ const checkValue = (value, start, end) => {
|
|
|
3
3
|
throw new Error("Out of Range");
|
|
4
4
|
}
|
|
5
5
|
};
|
|
6
|
+
/**
|
|
7
|
+
* 64bit unsigned interger
|
|
8
|
+
*
|
|
9
|
+
* This version uses bigints to ensure accuracy is not lost
|
|
10
|
+
*/
|
|
6
11
|
export function u64Bigint(endian = "little") {
|
|
7
12
|
return {
|
|
8
13
|
size: 8,
|
|
@@ -19,6 +24,11 @@ export function u64Bigint(endian = "little") {
|
|
|
19
24
|
},
|
|
20
25
|
};
|
|
21
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* 64bit signed interger
|
|
29
|
+
*
|
|
30
|
+
* This version uses bigints to ensure accuracy is not lost
|
|
31
|
+
*/
|
|
22
32
|
export function s64Bigint(endian = "little") {
|
|
23
33
|
return {
|
|
24
34
|
size: 8,
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { describe, it, expect } from "bun:test";
|
|
2
|
-
import {
|
|
2
|
+
import { encodeTest, encodeSnapshotTest, randbigint, encodeFailTest } from "../../utils.test";
|
|
3
3
|
import * as st from "../../index";
|
|
4
4
|
function test_bigint(options) {
|
|
5
5
|
const { name, range: [start, end], serializer, size, } = options;
|
|
6
6
|
describe(name, () => {
|
|
7
7
|
it("works in bounds", () => {
|
|
8
|
-
|
|
8
|
+
encodeTest(serializer, start);
|
|
9
9
|
for (let i = 0; i < 100; i++) {
|
|
10
|
-
|
|
10
|
+
encodeTest(serializer, randbigint(start, end));
|
|
11
11
|
}
|
|
12
|
-
|
|
12
|
+
encodeTest(serializer, end);
|
|
13
13
|
});
|
|
14
14
|
it("outside bounds", () => {
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
encodeFailTest(serializer, start - 1n);
|
|
16
|
+
encodeFailTest(serializer, end + 1n);
|
|
17
17
|
});
|
|
18
18
|
it(`is right size`, () => {
|
|
19
19
|
const expectValueSize = (value) => {
|
|
@@ -27,11 +27,11 @@ function test_bigint(options) {
|
|
|
27
27
|
expectValueSize(end);
|
|
28
28
|
});
|
|
29
29
|
it(`matches snapshots`, () => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
encodeSnapshotTest(serializer, 0n);
|
|
31
|
+
encodeSnapshotTest(serializer, start);
|
|
32
|
+
encodeSnapshotTest(serializer, start + 10n);
|
|
33
|
+
encodeSnapshotTest(serializer, end - 10n);
|
|
34
|
+
encodeSnapshotTest(serializer, end);
|
|
35
35
|
});
|
|
36
36
|
});
|
|
37
37
|
}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import type { Serializer } from "../../types";
|
|
2
|
+
/** 16bit float */
|
|
3
|
+
export declare function f16(endian?: "little" | "big"): Serializer<number>;
|
|
4
|
+
/** 32bit float */
|
|
2
5
|
export declare function f32(endian?: "little" | "big"): Serializer<number>;
|
|
6
|
+
/** 64bit float */
|
|
3
7
|
export declare function f64(endian?: "little" | "big"): Serializer<number>;
|
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
/** 16bit float */
|
|
2
|
+
export function f16(endian = "little") {
|
|
3
|
+
return {
|
|
4
|
+
size: 2,
|
|
5
|
+
write: (ctx, value) => {
|
|
6
|
+
ctx.alloc(2);
|
|
7
|
+
ctx.view.setFloat16(ctx.offset, value, endian === "little");
|
|
8
|
+
ctx.offset += 2;
|
|
9
|
+
},
|
|
10
|
+
read: (ctx) => {
|
|
11
|
+
const value = ctx.view.getFloat16(ctx.offset, endian === "little");
|
|
12
|
+
ctx.offset += 2;
|
|
13
|
+
return value;
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** 32bit float */
|
|
1
18
|
export function f32(endian = "little") {
|
|
2
19
|
return {
|
|
3
20
|
size: 4,
|
|
@@ -13,6 +30,7 @@ export function f32(endian = "little") {
|
|
|
13
30
|
},
|
|
14
31
|
};
|
|
15
32
|
}
|
|
33
|
+
/** 64bit float */
|
|
16
34
|
export function f64(endian = "little") {
|
|
17
35
|
return {
|
|
18
36
|
size: 8,
|
|
@@ -1,71 +1,73 @@
|
|
|
1
1
|
//@ts-ignore TODO
|
|
2
2
|
import { describe, it, expect } from "bun:test";
|
|
3
|
-
import {
|
|
3
|
+
import { encodeTest, expectEncodeSize } from "../../utils.test";
|
|
4
4
|
import * as st from "../../index";
|
|
5
|
-
function
|
|
6
|
-
const { name,
|
|
5
|
+
function test_float(options) {
|
|
6
|
+
const { name, serializer, size } = options;
|
|
7
|
+
const expectEncodeApproximately = (value) => {
|
|
8
|
+
const data = st.write(serializer, value);
|
|
9
|
+
const newValue = st.read(serializer, data);
|
|
10
|
+
if (isNaN(value) && isNaN(newValue))
|
|
11
|
+
return;
|
|
12
|
+
if (value === newValue)
|
|
13
|
+
return;
|
|
14
|
+
if (Math.abs(value - newValue) < 0.000001)
|
|
15
|
+
return;
|
|
16
|
+
expect(false, "Failed comparsion tests");
|
|
17
|
+
};
|
|
7
18
|
describe(name, () => {
|
|
8
19
|
it(`works in bounds`, () => {
|
|
9
|
-
expectEncode(serializer, start);
|
|
10
20
|
for (let i = 0; i < 100; i++) {
|
|
11
|
-
|
|
21
|
+
expectEncodeApproximately(Math.random());
|
|
12
22
|
}
|
|
13
|
-
expectEncode(serializer, end);
|
|
14
23
|
});
|
|
15
|
-
it(`
|
|
16
|
-
|
|
17
|
-
|
|
24
|
+
it(`works on Infinty`, () => {
|
|
25
|
+
encodeTest(serializer, Infinity);
|
|
26
|
+
encodeTest(serializer, -Infinity);
|
|
18
27
|
});
|
|
19
|
-
it(`
|
|
20
|
-
|
|
28
|
+
it(`works on NaN`, () => {
|
|
29
|
+
encodeTest(serializer, NaN);
|
|
30
|
+
});
|
|
31
|
+
it(`works on 0`, () => {
|
|
32
|
+
encodeTest(serializer, 0);
|
|
33
|
+
});
|
|
34
|
+
it(`works on -0`, () => {
|
|
35
|
+
encodeTest(serializer, -0);
|
|
21
36
|
});
|
|
22
37
|
it(`is right size`, () => {
|
|
23
|
-
const expectValueSize = (value) => {
|
|
24
|
-
const data = st.write(serializer, value);
|
|
25
|
-
expect(data.byteLength).toBe(size);
|
|
26
|
-
};
|
|
27
38
|
for (let i = 0; i < 100; i++) {
|
|
28
|
-
|
|
39
|
+
expectEncodeSize(serializer, size, Math.random());
|
|
29
40
|
}
|
|
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
41
|
});
|
|
40
42
|
});
|
|
41
43
|
}
|
|
42
|
-
|
|
43
|
-
name: "st.
|
|
44
|
-
serializer: st.
|
|
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],
|
|
44
|
+
test_float({
|
|
45
|
+
name: "st.f16(little)",
|
|
46
|
+
serializer: st.f16("little"),
|
|
52
47
|
size: 2,
|
|
53
48
|
});
|
|
54
|
-
|
|
55
|
-
name: "st.
|
|
56
|
-
serializer: st.
|
|
57
|
-
range: [-32_768, 32_767],
|
|
49
|
+
test_float({
|
|
50
|
+
name: "st.f16(big)",
|
|
51
|
+
serializer: st.f16("big"),
|
|
58
52
|
size: 2,
|
|
59
53
|
});
|
|
60
|
-
|
|
61
|
-
name: "st.
|
|
62
|
-
serializer: st.
|
|
63
|
-
range: [-2_147_483_648, 2_147_483_647],
|
|
54
|
+
test_float({
|
|
55
|
+
name: "st.f32(little)",
|
|
56
|
+
serializer: st.f32("little"),
|
|
64
57
|
size: 4,
|
|
65
58
|
});
|
|
66
|
-
|
|
67
|
-
name: "st.
|
|
68
|
-
serializer: st.
|
|
69
|
-
range: [-2_147_483_648, 2_147_483_647],
|
|
59
|
+
test_float({
|
|
60
|
+
name: "st.f32(big)",
|
|
61
|
+
serializer: st.f32("big"),
|
|
70
62
|
size: 4,
|
|
71
63
|
});
|
|
64
|
+
test_float({
|
|
65
|
+
name: "st.f64(little)",
|
|
66
|
+
serializer: st.f64("little"),
|
|
67
|
+
size: 8,
|
|
68
|
+
});
|
|
69
|
+
test_float({
|
|
70
|
+
name: "st.f64(big)",
|
|
71
|
+
serializer: st.f64("big"),
|
|
72
|
+
size: 8,
|
|
73
|
+
});
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { Serializer } from "../../types";
|
|
2
|
+
/** 8bit signed integer */
|
|
2
3
|
export declare function s8(): Serializer<number>;
|
|
4
|
+
/** 16bit signed integer */
|
|
3
5
|
export declare function s16(endian?: "little" | "big"): Serializer<number>;
|
|
6
|
+
/** 32bit signed integer */
|
|
4
7
|
export declare function s32(endian?: "little" | "big"): Serializer<number>;
|
|
8
|
+
/** 64bit signed integer */
|
|
5
9
|
export declare function s64(endian?: "little" | "big"): Serializer<number>;
|
|
@@ -6,6 +6,7 @@ const checkValue = (value, start, end) => {
|
|
|
6
6
|
throw new Error("Out of Range");
|
|
7
7
|
}
|
|
8
8
|
};
|
|
9
|
+
/** 8bit signed integer */
|
|
9
10
|
export function s8() {
|
|
10
11
|
return {
|
|
11
12
|
size: 1,
|
|
@@ -22,6 +23,7 @@ export function s8() {
|
|
|
22
23
|
},
|
|
23
24
|
};
|
|
24
25
|
}
|
|
26
|
+
/** 16bit signed integer */
|
|
25
27
|
export function s16(endian = "little") {
|
|
26
28
|
return {
|
|
27
29
|
size: 2,
|
|
@@ -38,6 +40,7 @@ export function s16(endian = "little") {
|
|
|
38
40
|
},
|
|
39
41
|
};
|
|
40
42
|
}
|
|
43
|
+
/** 32bit signed integer */
|
|
41
44
|
export function s32(endian = "little") {
|
|
42
45
|
return {
|
|
43
46
|
size: 4,
|
|
@@ -54,6 +57,7 @@ export function s32(endian = "little") {
|
|
|
54
57
|
},
|
|
55
58
|
};
|
|
56
59
|
}
|
|
60
|
+
/** 64bit signed integer */
|
|
57
61
|
export function s64(endian = "little") {
|
|
58
62
|
return {
|
|
59
63
|
size: 8,
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
//@ts-ignore TODO
|
|
2
2
|
import { describe, it, expect } from "bun:test";
|
|
3
|
-
import {
|
|
3
|
+
import { encodeTest, encodeSnapshotTest, expectError, randint, encodeFailTest, } from "../../utils.test";
|
|
4
4
|
import * as st from "../../index";
|
|
5
5
|
function test_sint(options) {
|
|
6
6
|
const { name, range: [start, end], serializer, size, disableRangeCheck, } = options;
|
|
7
7
|
describe(name, () => {
|
|
8
8
|
it(`works in bounds`, () => {
|
|
9
|
-
|
|
9
|
+
encodeTest(serializer, start);
|
|
10
10
|
for (let i = 0; i < 100; i++) {
|
|
11
|
-
|
|
11
|
+
encodeTest(serializer, randint(start, end));
|
|
12
12
|
}
|
|
13
|
-
|
|
13
|
+
encodeTest(serializer, end);
|
|
14
14
|
});
|
|
15
15
|
if (!disableRangeCheck) {
|
|
16
16
|
it(`errors outside bounds`, () => {
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
encodeFailTest(serializer, start - 1);
|
|
18
|
+
encodeFailTest(serializer, end + 1);
|
|
19
19
|
});
|
|
20
20
|
}
|
|
21
21
|
it(`errors on decimal`, () => {
|
|
@@ -33,11 +33,11 @@ function test_sint(options) {
|
|
|
33
33
|
expectValueSize(end);
|
|
34
34
|
});
|
|
35
35
|
it(`matches snapshots`, () => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
encodeSnapshotTest(serializer, 0);
|
|
37
|
+
encodeSnapshotTest(serializer, start);
|
|
38
|
+
encodeSnapshotTest(serializer, start + 10);
|
|
39
|
+
encodeSnapshotTest(serializer, end - 10);
|
|
40
|
+
encodeSnapshotTest(serializer, end);
|
|
41
41
|
});
|
|
42
42
|
});
|
|
43
43
|
}
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import type { Serializer } from "../../types";
|
|
2
|
+
/** 8bit unsigned integer */
|
|
2
3
|
export declare function u8(): Serializer<number>;
|
|
4
|
+
/** 16bit unsigned integer */
|
|
3
5
|
export declare function u16(endian?: "little" | "big"): Serializer<number>;
|
|
6
|
+
/** 32bit unsigned integer */
|
|
4
7
|
export declare function u32(endian?: "little" | "big"): Serializer<number>;
|
|
8
|
+
/** 64bit unsigned integer */
|
|
5
9
|
export declare function u64(endian?: "little" | "big"): Serializer<number>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/** 8bit unsigned integer */
|
|
1
2
|
export function u8() {
|
|
2
3
|
return {
|
|
3
4
|
size: 1,
|
|
@@ -17,6 +18,7 @@ export function u8() {
|
|
|
17
18
|
},
|
|
18
19
|
};
|
|
19
20
|
}
|
|
21
|
+
/** 16bit unsigned integer */
|
|
20
22
|
export function u16(endian = "little") {
|
|
21
23
|
return {
|
|
22
24
|
size: 2,
|
|
@@ -36,6 +38,7 @@ export function u16(endian = "little") {
|
|
|
36
38
|
},
|
|
37
39
|
};
|
|
38
40
|
}
|
|
41
|
+
/** 32bit unsigned integer */
|
|
39
42
|
export function u32(endian = "little") {
|
|
40
43
|
return {
|
|
41
44
|
size: 4,
|
|
@@ -55,6 +58,7 @@ export function u32(endian = "little") {
|
|
|
55
58
|
},
|
|
56
59
|
};
|
|
57
60
|
}
|
|
61
|
+
/** 64bit unsigned integer */
|
|
58
62
|
export function u64(endian = "little") {
|
|
59
63
|
return {
|
|
60
64
|
size: 8,
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
//@ts-ignore TODO
|
|
2
2
|
import { describe, it, expect } from "bun:test";
|
|
3
|
-
import {
|
|
3
|
+
import { encodeTest, encodeSnapshotTest, expectError, randint, encodeFailTest, } from "../../utils.test";
|
|
4
4
|
import * as st from "../../index";
|
|
5
5
|
function test_uint(options) {
|
|
6
6
|
const { name, range: [start, end], serializer, size, disableMaxCheck, } = options;
|
|
7
7
|
describe(name, () => {
|
|
8
8
|
it(`works in bounds`, () => {
|
|
9
|
-
|
|
9
|
+
encodeTest(serializer, start);
|
|
10
10
|
for (let i = 0; i < 100; i++) {
|
|
11
|
-
|
|
11
|
+
encodeTest(serializer, randint(start, end));
|
|
12
12
|
}
|
|
13
|
-
|
|
13
|
+
encodeTest(serializer, end);
|
|
14
14
|
});
|
|
15
15
|
it(`errors outside bounds`, () => {
|
|
16
|
-
|
|
16
|
+
encodeFailTest(serializer, start - 1);
|
|
17
17
|
if (!disableMaxCheck) {
|
|
18
|
-
|
|
18
|
+
encodeFailTest(serializer, end + 1);
|
|
19
19
|
}
|
|
20
20
|
});
|
|
21
21
|
it(`errors on decimal`, () => {
|
|
@@ -33,11 +33,11 @@ function test_uint(options) {
|
|
|
33
33
|
expectValueSize(end);
|
|
34
34
|
});
|
|
35
35
|
it(`matches snapshots`, () => {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
encodeSnapshotTest(serializer, 0);
|
|
37
|
+
encodeSnapshotTest(serializer, start);
|
|
38
|
+
encodeSnapshotTest(serializer, start + 10);
|
|
39
|
+
encodeSnapshotTest(serializer, end - 10);
|
|
40
|
+
encodeSnapshotTest(serializer, end);
|
|
41
41
|
});
|
|
42
42
|
});
|
|
43
43
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
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>;
|
|
@@ -0,0 +1,30 @@
|
|
|
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,3 +1,15 @@
|
|
|
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
|
+
*/
|
|
1
13
|
export function pipe(type, ...pipeline) {
|
|
2
14
|
//@ts-ignore
|
|
3
15
|
return pipeline.reduce((v, func) => func(v), type);
|
|
@@ -1,5 +1,15 @@
|
|
|
1
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
|
+
*/
|
|
2
12
|
export declare function createRememberedValue<T>(): {
|
|
3
13
|
save: (serializer: Serializer<T>) => Serializer<T>;
|
|
4
|
-
load: () => Serializer<T>;
|
|
14
|
+
load: (serializer?: Serializer<T>) => Serializer<T>;
|
|
5
15
|
};
|
|
@@ -1,6 +1,16 @@
|
|
|
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
|
+
*/
|
|
1
11
|
export function createRememberedValue() {
|
|
2
12
|
const stack = [];
|
|
3
|
-
function
|
|
13
|
+
function save(serializer) {
|
|
4
14
|
return {
|
|
5
15
|
size: serializer.size,
|
|
6
16
|
read: (ctx) => {
|
|
@@ -15,12 +25,12 @@ export function createRememberedValue() {
|
|
|
15
25
|
},
|
|
16
26
|
};
|
|
17
27
|
}
|
|
18
|
-
function load() {
|
|
28
|
+
function load(serializer) {
|
|
19
29
|
return {
|
|
20
|
-
size: 0,
|
|
30
|
+
size: serializer?.size ?? 0,
|
|
21
31
|
read: () => stack.pop(),
|
|
22
|
-
write: () =>
|
|
32
|
+
write: (ctx) => serializer && serializer.write(ctx, stack.pop()),
|
|
23
33
|
};
|
|
24
34
|
}
|
|
25
|
-
return { save:
|
|
35
|
+
return { save: save, load: load };
|
|
26
36
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,44 @@
|
|
|
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,7 +1,8 @@
|
|
|
1
1
|
import * as st from "../index";
|
|
2
2
|
export declare const randint: (start: number, end: number) => number;
|
|
3
3
|
export declare const randbigint: (start: bigint, end: bigint) => bigint;
|
|
4
|
-
export declare const expectEncode: <
|
|
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;
|
|
5
6
|
export declare const expectEncodeSnapshot: <T>(serializer: st.Serializer<T>, value: T) => void;
|
|
6
7
|
export declare const expectError: (callback: () => void) => void;
|
|
7
8
|
export declare const bytes: (bytes: number[]) => ArrayBuffer;
|
|
@@ -10,10 +10,14 @@ export const randbigint = (start, end) => {
|
|
|
10
10
|
const offset = BigInt(Math.floor(Number(range) * Math.random()));
|
|
11
11
|
return start + offset;
|
|
12
12
|
};
|
|
13
|
-
export const expectEncode = (serializer, value) => {
|
|
13
|
+
export const expectEncode = (serializer, value, expected) => {
|
|
14
14
|
const data = st.write(serializer, value);
|
|
15
15
|
const newValue = st.read(serializer, data);
|
|
16
|
-
expect(
|
|
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);
|
|
17
21
|
};
|
|
18
22
|
export const expectEncodeSnapshot = (serializer, value) => {
|
|
19
23
|
const data = st.write(serializer, value);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { Serializer } from "../../types";
|
|
2
|
-
export declare function
|
|
2
|
+
export declare function bytesLiteral(bytes: number[]): Serializer<number[]>;
|