@nnilky/structo 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/dist/structo/datatypes/containers/array.d.ts +2 -0
  2. package/dist/structo/datatypes/containers/array.js +22 -0
  3. package/dist/structo/datatypes/containers/fastObject.d.ts +6 -0
  4. package/dist/structo/datatypes/containers/fastObject.js +46 -0
  5. package/dist/structo/datatypes/containers/list.d.ts +5 -0
  6. package/dist/structo/datatypes/containers/list.js +22 -0
  7. package/dist/structo/datatypes/containers/object.d.ts +9 -0
  8. package/dist/structo/datatypes/containers/object.js +24 -0
  9. package/dist/structo/datatypes/containers/sizedbuffer.d.ts +2 -0
  10. package/dist/structo/datatypes/containers/sizedbuffer.js +17 -0
  11. package/dist/structo/datatypes/index.d.ts +15 -0
  12. package/dist/structo/datatypes/index.js +15 -0
  13. package/dist/structo/datatypes/numbers/bigints.d.ts +3 -0
  14. package/dist/structo/datatypes/numbers/bigints.js +37 -0
  15. package/dist/structo/datatypes/numbers/floats.d.ts +3 -0
  16. package/dist/structo/datatypes/numbers/floats.js +30 -0
  17. package/dist/structo/datatypes/numbers/sints.d.ts +5 -0
  18. package/dist/structo/datatypes/numbers/sints.js +72 -0
  19. package/dist/structo/datatypes/numbers/uints.d.ts +5 -0
  20. package/dist/structo/datatypes/numbers/uints.js +76 -0
  21. package/dist/structo/datatypes/transforms/pipe.d.ts +11 -0
  22. package/dist/structo/datatypes/transforms/pipe.js +4 -0
  23. package/dist/structo/datatypes/transforms/readOffset.d.ts +2 -0
  24. package/dist/structo/datatypes/transforms/readOffset.js +18 -0
  25. package/dist/structo/datatypes/transforms/transform.d.ts +2 -0
  26. package/dist/structo/datatypes/transforms/transform.js +13 -0
  27. package/dist/structo/datatypes/values/buffer.d.ts +2 -0
  28. package/dist/structo/datatypes/values/buffer.js +18 -0
  29. package/dist/structo/datatypes/values/byteliteral.d.ts +2 -0
  30. package/dist/structo/datatypes/values/byteliteral.js +20 -0
  31. package/dist/structo/datatypes/values/string.d.ts +2 -0
  32. package/dist/structo/datatypes/values/string.js +21 -0
  33. package/dist/structo/index.d.ts +4 -0
  34. package/dist/structo/index.js +3 -0
  35. package/dist/structo/read.d.ts +7 -0
  36. package/dist/structo/read.js +10 -0
  37. package/dist/structo/types.d.ts +18 -0
  38. package/dist/structo/types.js +1 -0
  39. package/dist/structo/write.d.ts +3 -0
  40. package/dist/structo/write.js +41 -0
  41. package/package.json +4 -4
@@ -0,0 +1,2 @@
1
+ import type { Serializer } from "../../types";
2
+ export declare function array<T>(size: number, type: Serializer<T>): Serializer<T[]>;
@@ -0,0 +1,22 @@
1
+ export function array(size, type) {
2
+ const { read: readType, write: writeType, size: typeSize } = type;
3
+ return {
4
+ size: type.size ? size * type.size : undefined,
5
+ write: (ctx, value) => {
6
+ if (value.length !== size)
7
+ throw new Error("Invalid Size");
8
+ if (typeSize)
9
+ ctx.alloc(size * typeSize);
10
+ for (let i = 0; i < size; i++) {
11
+ writeType(ctx, value[i]);
12
+ }
13
+ },
14
+ read: (ctx) => {
15
+ const arr = new Array(size);
16
+ for (let i = 0; i < size; i++) {
17
+ arr[i] = readType(ctx);
18
+ }
19
+ return arr;
20
+ },
21
+ };
22
+ }
@@ -0,0 +1,6 @@
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 {};
@@ -0,0 +1,46 @@
1
+ const definitionSymbol = Symbol();
2
+ export function fastObject(definition) {
3
+ let serializers = [];
4
+ let writeBody = "";
5
+ let readBody = "";
6
+ function generateSerializers(serializer, keys) {
7
+ if (definitionSymbol in serializer) {
8
+ const definition = serializer[definitionSymbol];
9
+ readBody += `${keys[keys.length - 1]}: {`;
10
+ for (const key of Object.keys(definition)) {
11
+ generateSerializers(definition[key], [...keys, key]);
12
+ }
13
+ readBody += `},`;
14
+ }
15
+ else {
16
+ let path = "";
17
+ for (const key of keys) {
18
+ if (key.match(/[a-zA-Z_][a-zA-Z0-9_]*/)) {
19
+ path += `.${key}`;
20
+ }
21
+ else {
22
+ path += `[${JSON.stringify(key)}]`;
23
+ }
24
+ }
25
+ let name = `s${Object.keys(serializers).length}`;
26
+ serializers.push([name, serializer]);
27
+ writeBody += `${name}(c, v${path});`;
28
+ readBody += `${keys[keys.length - 1]}: ${name}(c),`;
29
+ }
30
+ }
31
+ for (const key of Object.keys(definition)) {
32
+ generateSerializers(definition[key], [key]);
33
+ }
34
+ const writeFactory = new Function(...serializers.map((v) => v[0]), `return (c, v) => {${writeBody}}`);
35
+ const readFactory = new Function(...serializers.map((v) => v[0]), `return (c, v) => ({${readBody}})`);
36
+ const write = writeFactory(...serializers.map((v) => v[1].write));
37
+ const read = readFactory(...serializers.map((v) => v[1].read));
38
+ let size = Object.values(definition).reduce((total, v) => total + v.size, 0);
39
+ return {
40
+ //@ts-ignore
41
+ [definitionSymbol]: definition,
42
+ size: isNaN(size) ? undefined : size,
43
+ write,
44
+ read,
45
+ };
46
+ }
@@ -0,0 +1,5 @@
1
+ import type { Serializer } from "../../types";
2
+ export declare function list<T>(options: {
3
+ type: Serializer<T>;
4
+ length: Serializer<number>;
5
+ }): Serializer<T[]>;
@@ -0,0 +1,22 @@
1
+ export function list(options) {
2
+ const { read: readLength, write: writeLength } = options.length;
3
+ const { read: readType, write: writeType, size: sizeType } = options.type;
4
+ return {
5
+ write: (ctx, value) => {
6
+ writeLength(ctx, value.length);
7
+ if (sizeType)
8
+ ctx.alloc(value.length * sizeType);
9
+ for (const v of value) {
10
+ writeType(ctx, v);
11
+ }
12
+ },
13
+ read: (ctx) => {
14
+ const size = readLength(ctx);
15
+ const arr = new Array(size);
16
+ for (let i = 0; i < size; i++) {
17
+ arr[i] = readType(ctx);
18
+ }
19
+ return arr;
20
+ },
21
+ };
22
+ }
@@ -0,0 +1,9 @@
1
+ import type { InferInput, InferOutput, Serializer } from "../../types";
2
+ type InferObjectInfer<T> = T extends Record<string, Serializer<any>> ? {
3
+ [Key in keyof T]: InferInput<T[Key]>;
4
+ } : never;
5
+ type InferObjectOutput<T> = T extends Record<string, Serializer<any>> ? {
6
+ [Key in keyof T]: InferOutput<T[Key]>;
7
+ } : never;
8
+ export declare function object<T extends Record<string, Serializer<any>>>(definition: T): Serializer<InferObjectInfer<T>, InferObjectOutput<T>>;
9
+ export {};
@@ -0,0 +1,24 @@
1
+ export function object(definition) {
2
+ const entires = Object.entries(definition);
3
+ // Use the fact: number + undefined = NaN
4
+ // Check for NaN afterwards
5
+ let computedSize = Object.values(definition).reduce((total, v) => total + v.size, 0);
6
+ const size = isNaN(computedSize) ? undefined : computedSize;
7
+ return {
8
+ size,
9
+ write: (ctx, value) => {
10
+ if (size)
11
+ ctx.alloc(size);
12
+ for (let i = 0; i < entires.length; i++) {
13
+ entires[i][1].write(ctx, value[entires[i][0]]);
14
+ }
15
+ },
16
+ read: (ctx) => {
17
+ const output = new Array(entires.length);
18
+ for (let i = 0; i < entires.length; i++) {
19
+ output[i] = [entires[i][0], entires[i][1].read(ctx)];
20
+ }
21
+ return Object.fromEntries(output);
22
+ },
23
+ };
24
+ }
@@ -0,0 +1,2 @@
1
+ import type { Serializer } from "../../types";
2
+ export declare function sizedBuffer(length: Serializer<number>): Serializer<ArrayBuffer>;
@@ -0,0 +1,17 @@
1
+ export function sizedBuffer(length) {
2
+ return {
3
+ write: (ctx, value) => {
4
+ length.write(ctx, value.byteLength);
5
+ const bytes = new Uint8Array(value);
6
+ ctx.alloc(value.byteLength);
7
+ new Uint8Array(ctx.view.buffer).set(bytes, ctx.offset);
8
+ ctx.offset += value.byteLength;
9
+ },
10
+ read: (ctx) => {
11
+ const size = length.read(ctx);
12
+ const slice = ctx.buffer.slice(ctx.offset, ctx.offset + size);
13
+ ctx.offset += size;
14
+ return slice;
15
+ },
16
+ };
17
+ }
@@ -0,0 +1,15 @@
1
+ export { u64Bigint, s64Bigint } from "./numbers/bigints";
2
+ export { f32, f64 } from "./numbers/floats";
3
+ export { s8, s16, s32, s64 } from "./numbers/sints";
4
+ export { u8, u16, u32, u64 } from "./numbers/uints";
5
+ export { array } from "./containers/array";
6
+ export { fastObject } from "./containers/fastObject";
7
+ export { object } from "./containers/object";
8
+ export { list } from "./containers/list";
9
+ export { sizedBuffer } from "./containers/sizedbuffer";
10
+ export { string } from "./values/string";
11
+ export { buffer } from "./values/buffer";
12
+ export { byteLiteral } from "./values/byteliteral";
13
+ export { type Transform as Pipeline, pipe } from "./transforms/pipe";
14
+ export { positionOffset } from "./transforms/readOffset";
15
+ export { transform } from "./transforms/transform";
@@ -0,0 +1,15 @@
1
+ export { u64Bigint, s64Bigint } from "./numbers/bigints";
2
+ export { f32, f64 } from "./numbers/floats";
3
+ export { s8, s16, s32, s64 } from "./numbers/sints";
4
+ export { u8, u16, u32, u64 } from "./numbers/uints";
5
+ export { array } from "./containers/array";
6
+ export { fastObject } from "./containers/fastObject";
7
+ export { object } from "./containers/object";
8
+ export { list } from "./containers/list";
9
+ export { sizedBuffer } from "./containers/sizedbuffer";
10
+ export { string } from "./values/string";
11
+ export { buffer } from "./values/buffer";
12
+ export { byteLiteral } from "./values/byteliteral";
13
+ export { pipe } from "./transforms/pipe";
14
+ export { positionOffset } from "./transforms/readOffset";
15
+ export { transform } from "./transforms/transform";
@@ -0,0 +1,3 @@
1
+ import type { Serializer } from "../../types";
2
+ export declare function u64Bigint(endian?: "little" | "big"): Serializer<number | bigint, bigint>;
3
+ export declare function s64Bigint(endian?: "little" | "big"): Serializer<number | bigint, bigint>;
@@ -0,0 +1,37 @@
1
+ const checkValue = (value, start, end) => {
2
+ if (value < start || value >= end) {
3
+ throw new Error("Out of Range");
4
+ }
5
+ };
6
+ export function u64Bigint(endian = "little") {
7
+ return {
8
+ size: 8,
9
+ write: (ctx, value) => {
10
+ checkValue(value, 0n, 2n ** 64n);
11
+ ctx.alloc(8);
12
+ ctx.view.setBigUint64(ctx.offset, BigInt(value), endian === "little");
13
+ ctx.offset += 8;
14
+ },
15
+ read: (ctx) => {
16
+ const value = ctx.view.getBigUint64(ctx.offset, endian === "little");
17
+ ctx.offset += 8;
18
+ return value;
19
+ },
20
+ };
21
+ }
22
+ export function s64Bigint(endian = "little") {
23
+ return {
24
+ size: 8,
25
+ write: (ctx, value) => {
26
+ checkValue(value, -(2n ** 63n), 2n ** 63n);
27
+ ctx.alloc(8);
28
+ ctx.view.setBigInt64(ctx.offset, BigInt(value), endian === "little");
29
+ ctx.offset += 8;
30
+ },
31
+ read: (ctx) => {
32
+ const value = ctx.view.getBigInt64(ctx.offset, endian === "little");
33
+ ctx.offset += 8;
34
+ return value;
35
+ },
36
+ };
37
+ }
@@ -0,0 +1,3 @@
1
+ import type { Serializer } from "../../types";
2
+ export declare function f32(endian?: "little" | "big"): Serializer<number>;
3
+ export declare function f64(endian?: "little" | "big"): Serializer<number>;
@@ -0,0 +1,30 @@
1
+ export function f32(endian = "little") {
2
+ return {
3
+ size: 4,
4
+ write: (ctx, value) => {
5
+ ctx.alloc(4);
6
+ ctx.view.setFloat32(ctx.offset, value, endian === "little");
7
+ ctx.offset += 4;
8
+ },
9
+ read: (ctx) => {
10
+ const value = ctx.view.getFloat32(ctx.offset, endian === "little");
11
+ ctx.offset += 4;
12
+ return value;
13
+ },
14
+ };
15
+ }
16
+ export function f64(endian = "little") {
17
+ return {
18
+ size: 8,
19
+ write: (ctx, value) => {
20
+ ctx.alloc(8);
21
+ ctx.view.setFloat64(ctx.offset, value, endian === "little");
22
+ ctx.offset += 8;
23
+ },
24
+ read: (ctx) => {
25
+ const value = ctx.view.getFloat64(ctx.offset, endian === "little");
26
+ ctx.offset += 8;
27
+ return value;
28
+ },
29
+ };
30
+ }
@@ -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,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,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,4 @@
1
+ export function pipe(type, ...pipeline) {
2
+ //@ts-ignore
3
+ return pipeline.reduce((v, func) => func(v), type);
4
+ }
@@ -0,0 +1,2 @@
1
+ import type { Serializer } from "../../types";
2
+ export declare function positionOffset<T>(delta: number): (type: Serializer<T>) => Serializer<T>;
@@ -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,2 @@
1
+ import type { Serializer } from "../../types";
2
+ export declare function transform<T>(callback: (value: T) => T): (type: Serializer<T>) => Serializer<T>;
@@ -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,2 @@
1
+ import type { Serializer } from "../../types";
2
+ export declare function buffer(size: number): Serializer<ArrayBuffer>;
@@ -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,2 @@
1
+ import type { Serializer } from "../../types";
2
+ export declare function byteLiteral(bytes: number[]): Serializer<number[]>;
@@ -0,0 +1,20 @@
1
+ export function byteLiteral(bytes) {
2
+ const length = bytes.length;
3
+ return {
4
+ size: bytes.length,
5
+ read: (ctx) => {
6
+ const arr = new Uint8Array(ctx.view.buffer);
7
+ for (let i = 0; i < length; i++) {
8
+ if (arr[ctx.offset + i] !== bytes[i]) {
9
+ throw new Error("Invalid Value");
10
+ }
11
+ }
12
+ ctx.offset += length;
13
+ return bytes;
14
+ },
15
+ write(ctx) {
16
+ new Uint8Array(ctx.view.buffer).set(bytes, ctx.offset);
17
+ ctx.offset += length;
18
+ },
19
+ };
20
+ }
@@ -0,0 +1,2 @@
1
+ import type { Serializer } from "../../types";
2
+ export declare function string(length: Serializer<number>): Serializer<string>;
@@ -0,0 +1,21 @@
1
+ export function string(length) {
2
+ const { read: readLength, write: writeLength } = length;
3
+ const encoder = new TextEncoder();
4
+ const decoder = new TextDecoder();
5
+ return {
6
+ write: (ctx, value) => {
7
+ const bytes = encoder.encode(value);
8
+ writeLength(ctx, bytes.byteLength);
9
+ ctx.alloc(bytes.byteLength);
10
+ const arr = new Uint8Array(ctx.view.buffer);
11
+ arr.set(bytes, ctx.offset);
12
+ ctx.offset += bytes.byteLength;
13
+ },
14
+ read: (ctx) => {
15
+ const length = readLength(ctx);
16
+ const section = ctx.buffer.slice(ctx.offset, ctx.offset + length);
17
+ ctx.offset += length;
18
+ return decoder.decode(section);
19
+ },
20
+ };
21
+ }
@@ -0,0 +1,4 @@
1
+ export type { InferInput as Infer, InferInput, InferOutput, ReaderContext, WriterContext, Serializer, } from "./types";
2
+ export * from "./datatypes";
3
+ export { write, createdWriterContext } from "./write";
4
+ export { read, createReaderContext } from "./read";
@@ -0,0 +1,3 @@
1
+ export * from "./datatypes";
2
+ export { write, createdWriterContext } from "./write";
3
+ export { read, createReaderContext } from "./read";
@@ -0,0 +1,7 @@
1
+ import type { Serializer } from "./types";
2
+ export declare function read<T>(serializer: Serializer<T>, buffer: ArrayBuffer): T;
3
+ export declare function createReaderContext(buffer: ArrayBuffer): {
4
+ offset: number;
5
+ buffer: ArrayBuffer;
6
+ view: DataView<ArrayBuffer>;
7
+ };
@@ -0,0 +1,10 @@
1
+ export function read(serializer, buffer) {
2
+ return serializer.read(createReaderContext(buffer));
3
+ }
4
+ export function createReaderContext(buffer) {
5
+ return {
6
+ offset: 0,
7
+ buffer,
8
+ view: new DataView(buffer),
9
+ };
10
+ }
@@ -0,0 +1,18 @@
1
+ export type Serializer<TIn, TOut = TIn> = {
2
+ size?: number | undefined;
3
+ write: (ctx: WriterContext, value: TIn) => void;
4
+ read: (ctx: ReaderContext) => TOut;
5
+ };
6
+ export interface WriterContext {
7
+ buffer: ArrayBuffer;
8
+ view: DataView;
9
+ offset: number;
10
+ alloc: (length: number) => void;
11
+ }
12
+ export interface ReaderContext {
13
+ buffer: ArrayBuffer;
14
+ view: DataView;
15
+ offset: number;
16
+ }
17
+ export type InferInput<T> = T extends Serializer<infer V> ? V : never;
18
+ export type InferOutput<T> = T extends Serializer<any, infer V> ? V : never;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,3 @@
1
+ import type { WriterContext, Serializer } from "./types";
2
+ export declare function write<T>(serializer: Serializer<T>, value: T): ArrayBuffer;
3
+ export declare function createdWriterContext(type: Serializer<any>): WriterContext;
@@ -0,0 +1,41 @@
1
+ export function write(serializer, value) {
2
+ const ctx = createdWriterContext(serializer);
3
+ serializer.write(ctx, value);
4
+ if (ctx.buffer.byteLength === ctx.offset) {
5
+ return ctx.buffer;
6
+ }
7
+ else {
8
+ return ctx.buffer.transfer(ctx.offset);
9
+ }
10
+ }
11
+ export function createdWriterContext(type) {
12
+ if (type.size) {
13
+ let buffer = new ArrayBuffer(type.size);
14
+ const view = new DataView(buffer);
15
+ return {
16
+ offset: 0,
17
+ buffer,
18
+ view,
19
+ alloc: Function.prototype,
20
+ };
21
+ }
22
+ else {
23
+ let bufferLength = 64;
24
+ let buffer = new ArrayBuffer(bufferLength);
25
+ const view = new DataView(buffer);
26
+ return {
27
+ offset: 0,
28
+ buffer,
29
+ view,
30
+ alloc(length) {
31
+ if (length < 0)
32
+ return;
33
+ while (this.offset + length >= bufferLength) {
34
+ bufferLength = this.buffer.byteLength * 2;
35
+ this.buffer = this.buffer.transfer(bufferLength);
36
+ this.view = new DataView(this.buffer);
37
+ }
38
+ },
39
+ };
40
+ }
41
+ }
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.1",
6
+ "version": "1.0.2",
7
7
  "author": "Ben Brady",
8
8
  "private": false,
9
9
  "publishConfig": {"access": "public"},
@@ -34,9 +34,9 @@
34
34
  "files": [
35
35
  "LICENSE",
36
36
  "README.md",
37
- "./dist/*.d.ts",
38
- "./dist/*.js.map",
39
- "./dist/*.js"
37
+ "./dist/**/*.d.ts",
38
+ "./dist/**/*.js.map",
39
+ "./dist/**/*.js"
40
40
  ],
41
41
 
42
42
  "scripts": {