@chr33s/pdf-restructure 5.0.0

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 (93) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +323 -0
  3. package/dist/array.d.ts +15 -0
  4. package/dist/array.js +95 -0
  5. package/dist/array.js.map +1 -0
  6. package/dist/base.d.ts +4 -0
  7. package/dist/base.js +16 -0
  8. package/dist/base.js.map +1 -0
  9. package/dist/bitfield.d.ts +11 -0
  10. package/dist/bitfield.js +37 -0
  11. package/dist/bitfield.js.map +1 -0
  12. package/dist/boolean.d.ts +10 -0
  13. package/dist/boolean.js +18 -0
  14. package/dist/boolean.js.map +1 -0
  15. package/dist/buffer.d.ts +11 -0
  16. package/dist/buffer.js +31 -0
  17. package/dist/buffer.js.map +1 -0
  18. package/dist/decode-stream.d.ts +26 -0
  19. package/dist/decode-stream.js +84 -0
  20. package/dist/decode-stream.js.map +1 -0
  21. package/dist/encode-stream.d.ts +19 -0
  22. package/dist/encode-stream.js +137 -0
  23. package/dist/encode-stream.js.map +1 -0
  24. package/dist/enum.d.ts +11 -0
  25. package/dist/enum.js +25 -0
  26. package/dist/enum.js.map +1 -0
  27. package/dist/index.d.ts +17 -0
  28. package/dist/index.js +18 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/lazy-array.d.ts +22 -0
  31. package/dist/lazy-array.js +75 -0
  32. package/dist/lazy-array.js.map +1 -0
  33. package/dist/number.d.ts +51 -0
  34. package/dist/number.js +76 -0
  35. package/dist/number.js.map +1 -0
  36. package/dist/optional.d.ts +14 -0
  37. package/dist/optional.js +34 -0
  38. package/dist/optional.js.map +1 -0
  39. package/dist/pointer.d.ts +28 -0
  40. package/dist/pointer.js +160 -0
  41. package/dist/pointer.js.map +1 -0
  42. package/dist/reserved.d.ts +12 -0
  43. package/dist/reserved.js +23 -0
  44. package/dist/reserved.js.map +1 -0
  45. package/dist/string.d.ts +14 -0
  46. package/dist/string.js +123 -0
  47. package/dist/string.js.map +1 -0
  48. package/dist/struct.d.ts +15 -0
  49. package/dist/struct.js +93 -0
  50. package/dist/struct.js.map +1 -0
  51. package/dist/utils.d.ts +13 -0
  52. package/dist/utils.js +45 -0
  53. package/dist/utils.js.map +1 -0
  54. package/dist/versioned-struct.d.ts +18 -0
  55. package/dist/versioned-struct.js +129 -0
  56. package/dist/versioned-struct.js.map +1 -0
  57. package/package.json +47 -0
  58. package/src/array.ts +113 -0
  59. package/src/base.ts +17 -0
  60. package/src/bitfield.ts +46 -0
  61. package/src/boolean.ts +24 -0
  62. package/src/buffer.ts +40 -0
  63. package/src/decode-stream.ts +97 -0
  64. package/src/encode-stream.ts +161 -0
  65. package/src/enum.ts +32 -0
  66. package/src/index.ts +17 -0
  67. package/src/lazy-array.ts +91 -0
  68. package/src/number.ts +88 -0
  69. package/src/optional.ts +46 -0
  70. package/src/pointer.ts +204 -0
  71. package/src/reserved.ts +29 -0
  72. package/src/string.ts +154 -0
  73. package/src/struct.ts +127 -0
  74. package/src/utils.ts +55 -0
  75. package/src/versioned-struct.ts +174 -0
  76. package/test/array.test.ts +95 -0
  77. package/test/bitfield.test.ts +52 -0
  78. package/test/boolean.test.ts +35 -0
  79. package/test/buffer.test.ts +49 -0
  80. package/test/decode-stream.test.ts +104 -0
  81. package/test/encode-stream.test.ts +111 -0
  82. package/test/enum.test.ts +30 -0
  83. package/test/lazy-array.test.ts +70 -0
  84. package/test/number.test.ts +222 -0
  85. package/test/optional.test.ts +105 -0
  86. package/test/pointer.test.ts +248 -0
  87. package/test/reserved.test.ts +28 -0
  88. package/test/string.test.ts +114 -0
  89. package/test/struct.test.ts +164 -0
  90. package/test/versioned-struct.test.ts +462 -0
  91. package/tsconfig.json +9 -0
  92. package/tsconfig.typecheck.json +14 -0
  93. package/vitest.config.ts +12 -0
@@ -0,0 +1,462 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import {
3
+ DecodeStream,
4
+ EncodeStream,
5
+ Pointer,
6
+ String as StringT,
7
+ uint8,
8
+ VersionedStruct,
9
+ } from "../src/index.js";
10
+
11
+ describe("VersionedStruct", () => {
12
+ const baseStruct = new VersionedStruct(uint8, {
13
+ 0: {
14
+ name: new StringT(uint8, "ascii"),
15
+ age: uint8,
16
+ },
17
+ 1: {
18
+ name: new StringT(uint8, "utf8"),
19
+ age: uint8,
20
+ gender: uint8,
21
+ },
22
+ });
23
+
24
+ describe("decode", () => {
25
+ test("should get version from number type", () => {
26
+ // \x00\x05devon\x15
27
+ const stream0 = new DecodeStream(
28
+ new Uint8Array([0x00, 0x05, 0x64, 0x65, 0x76, 0x6f, 0x6e, 0x15]),
29
+ );
30
+ expect(baseStruct.decode(stream0)).to.deep.equal({
31
+ version: 0,
32
+ name: "devon",
33
+ age: 21,
34
+ });
35
+
36
+ // \x01\x0adevon 👍\x15\x00 in utf8
37
+ const stream1 = new DecodeStream(
38
+ new Uint8Array([
39
+ 0x01, 0x0a, 0x64, 0x65, 0x76, 0x6f, 0x6e, 0x20, 0xf0, 0x9f, 0x91, 0x8d, 0x15, 0x00,
40
+ ]),
41
+ );
42
+ expect(baseStruct.decode(stream1)).to.deep.equal({
43
+ version: 1,
44
+ name: "devon 👍",
45
+ age: 21,
46
+ gender: 0,
47
+ });
48
+ });
49
+
50
+ test("should throw for unknown version", () => {
51
+ // \x05\x05devon\x15
52
+ const stream = new DecodeStream(
53
+ new Uint8Array([0x05, 0x05, 0x64, 0x65, 0x76, 0x6f, 0x6e, 0x15]),
54
+ );
55
+ expect(() => baseStruct.decode(stream)).to.throw(/unknown version/i);
56
+ });
57
+
58
+ test("should support common header block", () => {
59
+ const struct = new VersionedStruct(uint8, {
60
+ header: {
61
+ age: uint8,
62
+ alive: uint8,
63
+ },
64
+ 0: {
65
+ name: new StringT(uint8, "ascii"),
66
+ },
67
+ 1: {
68
+ name: new StringT(uint8, "utf8"),
69
+ gender: uint8,
70
+ },
71
+ });
72
+
73
+ // \x00\x15\x01\x05devon
74
+ const stream0 = new DecodeStream(
75
+ new Uint8Array([0x00, 0x15, 0x01, 0x05, 0x64, 0x65, 0x76, 0x6f, 0x6e]),
76
+ );
77
+ expect(struct.decode(stream0)).to.deep.equal({
78
+ version: 0,
79
+ age: 21,
80
+ alive: 1,
81
+ name: "devon",
82
+ });
83
+
84
+ // \x01\x15\x01\x0adevon 👍\x00 in utf8
85
+ const stream1 = new DecodeStream(
86
+ new Uint8Array([
87
+ 0x01, 0x15, 0x01, 0x0a, 0x64, 0x65, 0x76, 0x6f, 0x6e, 0x20, 0xf0, 0x9f, 0x91, 0x8d, 0x00,
88
+ ]),
89
+ );
90
+ expect(struct.decode(stream1)).to.deep.equal({
91
+ version: 1,
92
+ age: 21,
93
+ alive: 1,
94
+ name: "devon 👍",
95
+ gender: 0,
96
+ });
97
+ });
98
+
99
+ test("should support parent version key", () => {
100
+ const struct = new VersionedStruct("version", {
101
+ 0: {
102
+ name: new StringT(uint8, "ascii"),
103
+ age: uint8,
104
+ },
105
+ 1: {
106
+ name: new StringT(uint8, "utf8"),
107
+ age: uint8,
108
+ gender: uint8,
109
+ },
110
+ });
111
+
112
+ // \x05devon\x15
113
+ const stream0 = new DecodeStream(new Uint8Array([0x05, 0x64, 0x65, 0x76, 0x6f, 0x6e, 0x15]));
114
+ expect(struct.decode(stream0, { version: 0 })).to.deep.equal({
115
+ version: 0,
116
+ name: "devon",
117
+ age: 21,
118
+ });
119
+
120
+ // \x0adevon 👍\x15\x00 in utf8
121
+ const stream1 = new DecodeStream(
122
+ new Uint8Array([
123
+ 0x0a, 0x64, 0x65, 0x76, 0x6f, 0x6e, 0x20, 0xf0, 0x9f, 0x91, 0x8d, 0x15, 0x00,
124
+ ]),
125
+ );
126
+ expect(struct.decode(stream1, { version: 1 })).to.deep.equal({
127
+ version: 1,
128
+ name: "devon 👍",
129
+ age: 21,
130
+ gender: 0,
131
+ });
132
+ });
133
+
134
+ test("should support sub versioned structs", () => {
135
+ const struct = new VersionedStruct(uint8, {
136
+ 0: {
137
+ name: new StringT(uint8, "ascii"),
138
+ age: uint8,
139
+ },
140
+ 1: new VersionedStruct(uint8, {
141
+ 0: {
142
+ name: new StringT(uint8),
143
+ },
144
+ 1: {
145
+ name: new StringT(uint8),
146
+ isDesert: uint8,
147
+ },
148
+ }),
149
+ });
150
+
151
+ // \x00\x05devon\x15
152
+ const stream0 = new DecodeStream(
153
+ new Uint8Array([0x00, 0x05, 0x64, 0x65, 0x76, 0x6f, 0x6e, 0x15]),
154
+ );
155
+ expect(struct.decode(stream0, { version: 0 })).to.deep.equal({
156
+ version: 0,
157
+ name: "devon",
158
+ age: 21,
159
+ });
160
+
161
+ // \x01\x00\x05pasta
162
+ const stream1 = new DecodeStream(
163
+ new Uint8Array([0x01, 0x00, 0x05, 0x70, 0x61, 0x73, 0x74, 0x61]),
164
+ );
165
+ expect(struct.decode(stream1, { version: 0 })).to.deep.equal({
166
+ version: 0,
167
+ name: "pasta",
168
+ });
169
+
170
+ // \x01\x01\x09ice cream\x01
171
+ const stream2 = new DecodeStream(
172
+ new Uint8Array([
173
+ 0x01, 0x01, 0x09, 0x69, 0x63, 0x65, 0x20, 0x63, 0x72, 0x65, 0x61, 0x6d, 0x01,
174
+ ]),
175
+ );
176
+ expect(struct.decode(stream2, { version: 0 })).to.deep.equal({
177
+ version: 1,
178
+ name: "ice cream",
179
+ isDesert: 1,
180
+ });
181
+ });
182
+
183
+ test("should support process hook", () => {
184
+ const struct = baseStruct;
185
+ struct.process = function process() {
186
+ (this as any).processed = true;
187
+ };
188
+
189
+ // \x00\x05devon\x15
190
+ const stream = new DecodeStream(
191
+ new Uint8Array([0x00, 0x05, 0x64, 0x65, 0x76, 0x6f, 0x6e, 0x15]),
192
+ );
193
+ expect(struct.decode(stream)).to.deep.equal({
194
+ version: 0,
195
+ name: "devon",
196
+ age: 21,
197
+ processed: true,
198
+ });
199
+ });
200
+ });
201
+
202
+ describe("size", () => {
203
+ test("should compute the correct size", () => {
204
+ expect(baseStruct.size({ version: 0, name: "devon", age: 21 })).to.equal(8);
205
+ expect(baseStruct.size({ version: 1, name: "devon 👍", age: 21, gender: 0 })).to.equal(14);
206
+ });
207
+
208
+ test("should throw for unknown version", () => {
209
+ expect(() => baseStruct.size({ version: 5, name: "devon", age: 21 })).to.throw(
210
+ /unknown version/i,
211
+ );
212
+ });
213
+
214
+ test("should support common header block", () => {
215
+ const struct = new VersionedStruct(uint8, {
216
+ header: {
217
+ age: uint8,
218
+ alive: uint8,
219
+ },
220
+ 0: {
221
+ name: new StringT(uint8, "ascii"),
222
+ },
223
+ 1: {
224
+ name: new StringT(uint8, "utf8"),
225
+ gender: uint8,
226
+ },
227
+ });
228
+
229
+ expect(struct.size({ version: 0, age: 21, alive: 1, name: "devon" })).to.equal(9);
230
+ expect(
231
+ struct.size({
232
+ version: 1,
233
+ age: 21,
234
+ alive: 1,
235
+ name: "devon 👍",
236
+ gender: 0,
237
+ }),
238
+ ).to.equal(15);
239
+ });
240
+
241
+ test("should compute the correct size with pointers", () => {
242
+ const struct = new VersionedStruct(uint8, {
243
+ 0: {
244
+ name: new StringT(uint8, "ascii"),
245
+ age: uint8,
246
+ },
247
+ 1: {
248
+ name: new StringT(uint8, "utf8"),
249
+ age: uint8,
250
+ ptr: new Pointer(uint8, new StringT(uint8)),
251
+ },
252
+ });
253
+
254
+ expect(struct.size({ version: 1, name: "devon", age: 21, ptr: "hello" })).to.equal(15);
255
+ });
256
+
257
+ test("should throw if no value is given", () => {
258
+ const struct = new VersionedStruct(uint8, {
259
+ 0: {
260
+ name: new StringT(4, "ascii"),
261
+ age: uint8,
262
+ },
263
+ 1: {
264
+ name: new StringT(4, "utf8"),
265
+ age: uint8,
266
+ gender: uint8,
267
+ },
268
+ });
269
+
270
+ expect(() => struct.size(undefined as any)).to.throw(/not a fixed size/i);
271
+ });
272
+ });
273
+
274
+ describe("encode", () => {
275
+ test("should encode objects to buffers", () => {
276
+ const value1 = { version: 0, name: "devon", age: 21 };
277
+ const value2 = { version: 1, name: "devon 👍", age: 21, gender: 0 };
278
+ const totalSize = baseStruct.size(value1) + baseStruct.size(value2);
279
+ const stream = new EncodeStream(new Uint8Array(totalSize));
280
+
281
+ baseStruct.encode(stream, value1);
282
+ baseStruct.encode(stream, value2);
283
+
284
+ // \x00\x05devon\x15\x01\x0adevon 👍\x15\x00
285
+ expect(stream.buffer).to.deep.equal(
286
+ new Uint8Array([
287
+ 0x00,
288
+ 0x05,
289
+ 0x64,
290
+ 0x65,
291
+ 0x76,
292
+ 0x6f,
293
+ 0x6e,
294
+ 0x15, // version 0
295
+ 0x01,
296
+ 0x0a,
297
+ 0x64,
298
+ 0x65,
299
+ 0x76,
300
+ 0x6f,
301
+ 0x6e,
302
+ 0x20,
303
+ 0xf0,
304
+ 0x9f,
305
+ 0x91,
306
+ 0x8d,
307
+ 0x15,
308
+ 0x00, // version 1
309
+ ]),
310
+ );
311
+ });
312
+
313
+ test("should throw for unknown version", () => {
314
+ const stream = new EncodeStream(new Uint8Array(100));
315
+ expect(() => baseStruct.encode(stream, { version: 5, name: "devon", age: 21 })).to.throw(
316
+ /unknown version/i,
317
+ );
318
+ });
319
+
320
+ test("should support common header block", () => {
321
+ const struct = new VersionedStruct(uint8, {
322
+ header: {
323
+ age: uint8,
324
+ alive: uint8,
325
+ },
326
+ 0: {
327
+ name: new StringT(uint8, "ascii"),
328
+ },
329
+ 1: {
330
+ name: new StringT(uint8, "utf8"),
331
+ gender: uint8,
332
+ },
333
+ });
334
+
335
+ const value1 = { version: 0, age: 21, alive: 1, name: "devon" };
336
+ const value2 = { version: 1, age: 21, alive: 1, name: "devon 👍", gender: 0 };
337
+ const totalSize = struct.size(value1) + struct.size(value2);
338
+ const stream = new EncodeStream(new Uint8Array(totalSize));
339
+
340
+ struct.encode(stream, value1);
341
+ struct.encode(stream, value2);
342
+
343
+ // \x00\x15\x01\x05devon\x01\x15\x01\x0adevon 👍\x00
344
+ expect(stream.buffer).to.deep.equal(
345
+ new Uint8Array([
346
+ 0x00,
347
+ 0x15,
348
+ 0x01,
349
+ 0x05,
350
+ 0x64,
351
+ 0x65,
352
+ 0x76,
353
+ 0x6f,
354
+ 0x6e, // version 0
355
+ 0x01,
356
+ 0x15,
357
+ 0x01,
358
+ 0x0a,
359
+ 0x64,
360
+ 0x65,
361
+ 0x76,
362
+ 0x6f,
363
+ 0x6e,
364
+ 0x20,
365
+ 0xf0,
366
+ 0x9f,
367
+ 0x91,
368
+ 0x8d,
369
+ 0x00, // version 1
370
+ ]),
371
+ );
372
+ });
373
+
374
+ test("should encode pointer data after structure", () => {
375
+ const struct = new VersionedStruct(uint8, {
376
+ 0: {
377
+ name: new StringT(uint8, "ascii"),
378
+ age: uint8,
379
+ },
380
+ 1: {
381
+ name: new StringT(uint8, "utf8"),
382
+ age: uint8,
383
+ ptr: new Pointer(uint8, new StringT(uint8)),
384
+ },
385
+ });
386
+
387
+ const value = { version: 1, name: "devon", age: 21, ptr: "hello" };
388
+ const stream = new EncodeStream(new Uint8Array(struct.size(value)));
389
+ struct.encode(stream, value);
390
+
391
+ // \x01\x05devon\x15\x09\x05hello
392
+ expect(stream.buffer).to.deep.equal(
393
+ new Uint8Array([
394
+ 0x01,
395
+ 0x05,
396
+ 0x64,
397
+ 0x65,
398
+ 0x76,
399
+ 0x6f,
400
+ 0x6e, // \x01\x05devon
401
+ 0x15, // age: 21
402
+ 0x09, // pointer offset
403
+ 0x05,
404
+ 0x68,
405
+ 0x65,
406
+ 0x6c,
407
+ 0x6c,
408
+ 0x6f, // \x05hello
409
+ ]),
410
+ );
411
+ });
412
+
413
+ test("should support preEncode hook", () => {
414
+ const struct = baseStruct;
415
+ struct.preEncode = function preEncode() {
416
+ (this as any).version = (this as any).gender != null ? 1 : 0;
417
+ };
418
+
419
+ const value1 = { name: "devon", age: 21 } as any;
420
+ const value2 = { name: "devon 👍", age: 21, gender: 0 } as any;
421
+ // Need to compute sizes after preEncode would set version
422
+ value1.version = 0;
423
+ value2.version = 1;
424
+ const totalSize = struct.size(value1) + struct.size(value2);
425
+ const stream = new EncodeStream(new Uint8Array(totalSize));
426
+
427
+ // Reset versions for encode to set them via preEncode
428
+ delete value1.version;
429
+ delete value2.version;
430
+ struct.encode(stream, value1);
431
+ struct.encode(stream, value2);
432
+
433
+ // \x00\x05devon\x15\x01\x0adevon 👍\x15\x00
434
+ expect(stream.buffer).to.deep.equal(
435
+ new Uint8Array([
436
+ 0x00,
437
+ 0x05,
438
+ 0x64,
439
+ 0x65,
440
+ 0x76,
441
+ 0x6f,
442
+ 0x6e,
443
+ 0x15, // version 0
444
+ 0x01,
445
+ 0x0a,
446
+ 0x64,
447
+ 0x65,
448
+ 0x76,
449
+ 0x6f,
450
+ 0x6e,
451
+ 0x20,
452
+ 0xf0,
453
+ 0x9f,
454
+ 0x91,
455
+ 0x8d,
456
+ 0x15,
457
+ 0x00, // version 1
458
+ ]),
459
+ );
460
+ });
461
+ });
462
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "../../tsconfig.json",
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "outDir": "dist"
6
+ },
7
+ "include": ["src/**/*"],
8
+ "exclude": ["dist", "node_modules", "test"]
9
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "noEmit": true,
5
+ "rootDir": "."
6
+ },
7
+ "include": [
8
+ "**/*.ts",
9
+ ],
10
+ "exclude": [
11
+ "dist",
12
+ "node_modules"
13
+ ]
14
+ }
@@ -0,0 +1,12 @@
1
+ import { defineConfig } from "vitest/config";
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ environment: "node",
6
+ include: ["test/**/*.test.ts"],
7
+ coverage: {
8
+ provider: "v8",
9
+ reporter: ["text", "lcov"],
10
+ },
11
+ },
12
+ });