@nnilky/structo 1.0.1 → 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.d.ts +2 -0
- package/dist/datatypes/containers/array.js +22 -0
- package/dist/datatypes/containers/array.test.d.ts +1 -0
- package/dist/datatypes/containers/array.test.js +22 -0
- package/dist/datatypes/containers/fastObject.d.ts +19 -0
- package/dist/datatypes/containers/fastObject.js +59 -0
- package/dist/datatypes/containers/list.d.ts +5 -0
- package/dist/datatypes/containers/list.js +22 -0
- package/dist/datatypes/containers/list.test.d.ts +1 -0
- package/dist/datatypes/containers/list.test.js +31 -0
- package/dist/datatypes/containers/object.d.ts +20 -0
- package/dist/datatypes/containers/object.js +35 -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.d.ts +2 -0
- package/dist/datatypes/containers/sizedbuffer.js +17 -0
- package/dist/datatypes/containers/sizedbuffer.test.d.ts +1 -0
- package/dist/datatypes/containers/sizedbuffer.test.js +27 -0
- package/dist/datatypes/index.d.ts +16 -0
- package/dist/datatypes/index.js +16 -0
- package/dist/datatypes/lazy.d.ts +1 -0
- package/dist/datatypes/lazy.js +1 -0
- package/dist/datatypes/numbers/bigints.d.ts +3 -0
- package/dist/datatypes/numbers/bigints.js +37 -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.d.ts +3 -0
- package/dist/datatypes/numbers/floats.js +30 -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.d.ts +5 -0
- package/dist/datatypes/numbers/sints.js +72 -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.d.ts +5 -0
- package/dist/datatypes/numbers/uints.js +76 -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.d.ts +11 -0
- package/dist/datatypes/transforms/pipe.js +4 -0
- package/dist/datatypes/transforms/pipe.test.d.ts +1 -0
- package/dist/datatypes/transforms/pipe.test.js +13 -0
- package/dist/datatypes/transforms/readOffset.d.ts +2 -0
- package/dist/datatypes/transforms/readOffset.js +18 -0
- package/dist/datatypes/transforms/transform.d.ts +2 -0
- package/dist/datatypes/transforms/transform.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.d.ts +2 -0
- package/dist/datatypes/values/buffer.js +18 -0
- package/dist/datatypes/values/buffer.test.d.ts +1 -0
- package/dist/datatypes/values/buffer.test.js +43 -0
- package/dist/datatypes/values/byteliteral.d.ts +2 -0
- package/dist/datatypes/values/byteliteral.js +20 -0
- package/dist/datatypes/values/string.d.ts +2 -0
- package/dist/datatypes/values/string.js +22 -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 +4 -0
- package/dist/index.js +3 -0
- package/dist/read.d.ts +7 -0
- package/dist/read.js +10 -0
- package/dist/types.d.ts +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/write.d.ts +3 -0
- package/dist/write.js +43 -0
- package/package.json +4 -4
|
@@ -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,5 @@
|
|
|
1
|
+
import type { Serializer } from "../../types";
|
|
2
|
+
export declare function s8(): Serializer<number>;
|
|
3
|
+
export declare function s16(endian?: "little" | "big"): Serializer<number>;
|
|
4
|
+
export declare function s32(endian?: "little" | "big"): Serializer<number>;
|
|
5
|
+
export declare function s64(endian?: "little" | "big"): Serializer<number>;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
const checkValue = (value, start, end) => {
|
|
2
|
+
if (!Number.isInteger(value)) {
|
|
3
|
+
throw new Error("Not Integer");
|
|
4
|
+
}
|
|
5
|
+
if (value < start || value >= end) {
|
|
6
|
+
throw new Error("Out of Range");
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
export function s8() {
|
|
10
|
+
return {
|
|
11
|
+
size: 1,
|
|
12
|
+
write: (ctx, value) => {
|
|
13
|
+
checkValue(value, -(2 ** 7), 2 ** 7);
|
|
14
|
+
ctx.alloc(1);
|
|
15
|
+
ctx.view.setInt8(ctx.offset, value);
|
|
16
|
+
ctx.offset += 1;
|
|
17
|
+
},
|
|
18
|
+
read: (ctx) => {
|
|
19
|
+
const value = ctx.view.getInt8(ctx.offset);
|
|
20
|
+
ctx.offset += 1;
|
|
21
|
+
return value;
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
export function s16(endian = "little") {
|
|
26
|
+
return {
|
|
27
|
+
size: 2,
|
|
28
|
+
write: (ctx, value) => {
|
|
29
|
+
checkValue(value, -(2 ** 15), 2 ** 15);
|
|
30
|
+
ctx.alloc(2);
|
|
31
|
+
ctx.view.setInt16(ctx.offset, value, endian === "little");
|
|
32
|
+
ctx.offset += 2;
|
|
33
|
+
},
|
|
34
|
+
read: (ctx) => {
|
|
35
|
+
const value = ctx.view.getInt16(ctx.offset, endian === "little");
|
|
36
|
+
ctx.offset += 2;
|
|
37
|
+
return value;
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
export function s32(endian = "little") {
|
|
42
|
+
return {
|
|
43
|
+
size: 4,
|
|
44
|
+
write: (ctx, value) => {
|
|
45
|
+
checkValue(value, -(2 ** 31), 2 ** 31);
|
|
46
|
+
ctx.alloc(4);
|
|
47
|
+
ctx.view.setInt32(ctx.offset, value, endian === "little");
|
|
48
|
+
ctx.offset += 4;
|
|
49
|
+
},
|
|
50
|
+
read: (ctx) => {
|
|
51
|
+
const value = ctx.view.getInt32(ctx.offset, endian === "little");
|
|
52
|
+
ctx.offset += 4;
|
|
53
|
+
return value;
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export function s64(endian = "little") {
|
|
58
|
+
return {
|
|
59
|
+
size: 8,
|
|
60
|
+
write: (ctx, value) => {
|
|
61
|
+
checkValue(value, -(2 ** 63), 2 ** 63);
|
|
62
|
+
ctx.alloc(8);
|
|
63
|
+
ctx.view.setBigInt64(ctx.offset, BigInt(value), endian === "little");
|
|
64
|
+
ctx.offset += 8;
|
|
65
|
+
},
|
|
66
|
+
read: (ctx) => {
|
|
67
|
+
const value = Number(ctx.view.getBigInt64(ctx.offset, endian === "little"));
|
|
68
|
+
ctx.offset += 8;
|
|
69
|
+
return value;
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
}
|
|
@@ -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,5 @@
|
|
|
1
|
+
import type { Serializer } from "../../types";
|
|
2
|
+
export declare function u8(): Serializer<number>;
|
|
3
|
+
export declare function u16(endian?: "little" | "big"): Serializer<number>;
|
|
4
|
+
export declare function u32(endian?: "little" | "big"): Serializer<number>;
|
|
5
|
+
export declare function u64(endian?: "little" | "big"): Serializer<number>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
export function u8() {
|
|
2
|
+
return {
|
|
3
|
+
size: 1,
|
|
4
|
+
write: (ctx, value) => {
|
|
5
|
+
if (!Number.isInteger(value))
|
|
6
|
+
throw new Error("Not Integer");
|
|
7
|
+
if (value < 0 || value >= 2 ** 8)
|
|
8
|
+
throw new Error("Out of Range");
|
|
9
|
+
ctx.alloc(1);
|
|
10
|
+
ctx.view.setUint8(ctx.offset, value);
|
|
11
|
+
ctx.offset += 1;
|
|
12
|
+
},
|
|
13
|
+
read: (ctx) => {
|
|
14
|
+
const value = ctx.view.getUint8(ctx.offset);
|
|
15
|
+
ctx.offset += 1;
|
|
16
|
+
return value;
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
export function u16(endian = "little") {
|
|
21
|
+
return {
|
|
22
|
+
size: 2,
|
|
23
|
+
write: (ctx, value) => {
|
|
24
|
+
if (!Number.isInteger(value))
|
|
25
|
+
throw new Error("Not Integer");
|
|
26
|
+
if (value < 0 || value >= 2 ** 16)
|
|
27
|
+
throw new Error("Out of Range");
|
|
28
|
+
ctx.alloc(2);
|
|
29
|
+
ctx.view.setUint16(ctx.offset, value, endian === "little");
|
|
30
|
+
ctx.offset += 2;
|
|
31
|
+
},
|
|
32
|
+
read: (ctx) => {
|
|
33
|
+
const value = ctx.view.getUint16(ctx.offset, endian === "little");
|
|
34
|
+
ctx.offset += 2;
|
|
35
|
+
return value;
|
|
36
|
+
},
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export function u32(endian = "little") {
|
|
40
|
+
return {
|
|
41
|
+
size: 4,
|
|
42
|
+
write: (ctx, value) => {
|
|
43
|
+
if (!Number.isInteger(value))
|
|
44
|
+
throw new Error("Not Integer");
|
|
45
|
+
if (value < 0 || value >= 2 ** 32)
|
|
46
|
+
throw new Error("Out of Range");
|
|
47
|
+
ctx.alloc(4);
|
|
48
|
+
ctx.view.setUint32(ctx.offset, value, endian === "little");
|
|
49
|
+
ctx.offset += 4;
|
|
50
|
+
},
|
|
51
|
+
read: (ctx) => {
|
|
52
|
+
const value = ctx.view.getUint32(ctx.offset, endian === "little");
|
|
53
|
+
ctx.offset += 4;
|
|
54
|
+
return value;
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
export function u64(endian = "little") {
|
|
59
|
+
return {
|
|
60
|
+
size: 8,
|
|
61
|
+
write: (ctx, value) => {
|
|
62
|
+
if (!Number.isInteger(value))
|
|
63
|
+
throw new Error("Not Integer");
|
|
64
|
+
if (value < 0 || value >= 2 ** 64)
|
|
65
|
+
throw new Error("Out of Range");
|
|
66
|
+
ctx.alloc(8);
|
|
67
|
+
ctx.view.setBigUint64(ctx.offset, BigInt(value), endian === "little");
|
|
68
|
+
ctx.offset += 8;
|
|
69
|
+
},
|
|
70
|
+
read: (ctx) => {
|
|
71
|
+
const value = Number(ctx.view.getBigUint64(ctx.offset, endian === "little"));
|
|
72
|
+
ctx.offset += 8;
|
|
73
|
+
return value;
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
@@ -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,11 @@
|
|
|
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>;
|
|
@@ -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,18 @@
|
|
|
1
|
+
export function positionOffset(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
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function transform(callback) {
|
|
2
|
+
return (type) => ({
|
|
3
|
+
size: type.size,
|
|
4
|
+
read: (ctx) => {
|
|
5
|
+
const value = type.read(ctx);
|
|
6
|
+
return callback(value);
|
|
7
|
+
},
|
|
8
|
+
write: (ctx, value) => {
|
|
9
|
+
let outValue = callback(value);
|
|
10
|
+
type.write(ctx, outValue);
|
|
11
|
+
},
|
|
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,18 @@
|
|
|
1
|
+
export function buffer(size) {
|
|
2
|
+
return {
|
|
3
|
+
size,
|
|
4
|
+
write: (ctx, value) => {
|
|
5
|
+
const bytes = new Uint8Array(value);
|
|
6
|
+
if (bytes.length !== size)
|
|
7
|
+
throw new Error("Invalid Length");
|
|
8
|
+
ctx.alloc(size);
|
|
9
|
+
new Uint8Array(ctx.buffer).set(bytes, ctx.offset);
|
|
10
|
+
ctx.offset += size;
|
|
11
|
+
},
|
|
12
|
+
read: (ctx) => {
|
|
13
|
+
const slice = ctx.buffer.slice(ctx.offset, ctx.offset + size);
|
|
14
|
+
ctx.offset += size;
|
|
15
|
+
return slice;
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
@@ -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
|
+
});
|