@kduma-oss/pcf 0.0.1

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 (57) hide show
  1. package/README.md +116 -0
  2. package/dist/consts.d.ts +42 -0
  3. package/dist/consts.d.ts.map +1 -0
  4. package/dist/consts.js +44 -0
  5. package/dist/consts.js.map +1 -0
  6. package/dist/container.d.ts +124 -0
  7. package/dist/container.d.ts.map +1 -0
  8. package/dist/container.js +441 -0
  9. package/dist/container.js.map +1 -0
  10. package/dist/crc.d.ts +15 -0
  11. package/dist/crc.d.ts.map +1 -0
  12. package/dist/crc.js +62 -0
  13. package/dist/crc.js.map +1 -0
  14. package/dist/entry.d.ts +44 -0
  15. package/dist/entry.d.ts.map +1 -0
  16. package/dist/entry.js +118 -0
  17. package/dist/entry.js.map +1 -0
  18. package/dist/errors.d.ts +56 -0
  19. package/dist/errors.d.ts.map +1 -0
  20. package/dist/errors.js +88 -0
  21. package/dist/errors.js.map +1 -0
  22. package/dist/hash.d.ts +59 -0
  23. package/dist/hash.d.ts.map +1 -0
  24. package/dist/hash.js +151 -0
  25. package/dist/hash.js.map +1 -0
  26. package/dist/header.d.ts +20 -0
  27. package/dist/header.d.ts.map +1 -0
  28. package/dist/header.js +38 -0
  29. package/dist/header.js.map +1 -0
  30. package/dist/index.d.ts +42 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +42 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/node-storage.d.ts +24 -0
  35. package/dist/node-storage.d.ts.map +1 -0
  36. package/dist/node-storage.js +52 -0
  37. package/dist/node-storage.js.map +1 -0
  38. package/dist/storage.d.ts +35 -0
  39. package/dist/storage.d.ts.map +1 -0
  40. package/dist/storage.js +66 -0
  41. package/dist/storage.js.map +1 -0
  42. package/dist/table.d.ts +28 -0
  43. package/dist/table.d.ts.map +1 -0
  44. package/dist/table.js +48 -0
  45. package/dist/table.js.map +1 -0
  46. package/package.json +60 -0
  47. package/src/consts.ts +50 -0
  48. package/src/container.ts +575 -0
  49. package/src/crc.ts +69 -0
  50. package/src/entry.ts +152 -0
  51. package/src/errors.ts +124 -0
  52. package/src/hash.ts +165 -0
  53. package/src/header.ts +50 -0
  54. package/src/index.ts +68 -0
  55. package/src/node-storage.ts +75 -0
  56. package/src/storage.ts +85 -0
  57. package/src/table.ts +67 -0
package/dist/entry.js ADDED
@@ -0,0 +1,118 @@
1
+ /**
2
+ * The fixed 141-byte partition entry (spec section 5.2).
3
+ */
4
+ import { ENTRY_SIZE, HASH_FIELD_SIZE, LABEL_SIZE, NIL_UID, TYPE_RESERVED, } from "./consts.js";
5
+ import { PcfError } from "./errors.js";
6
+ import { HashAlgo, hashAlgoFromId, hashAlgoId } from "./hash.js";
7
+ /** Serialise an entry to its on-disk 141-byte layout. */
8
+ export function entryToBytes(e) {
9
+ const b = new Uint8Array(ENTRY_SIZE);
10
+ const view = new DataView(b.buffer);
11
+ view.setUint32(0, e.partitionType >>> 0, true);
12
+ b.set(e.uid, 4);
13
+ b.set(e.label, 20);
14
+ view.setBigUint64(52, e.startOffset, true);
15
+ view.setBigUint64(60, e.maxLength, true);
16
+ view.setBigUint64(68, e.usedBytes, true);
17
+ b[76] = hashAlgoId(e.dataHashAlgo);
18
+ b.set(e.dataHash, 77);
19
+ return b;
20
+ }
21
+ /** Parse an entry from its on-disk 141-byte layout. */
22
+ export function entryFromBytes(b) {
23
+ const view = new DataView(b.buffer, b.byteOffset, b.byteLength);
24
+ const partitionType = view.getUint32(0, true);
25
+ const uid = b.slice(4, 20);
26
+ const label = b.slice(20, 52);
27
+ const startOffset = view.getBigUint64(52, true);
28
+ const maxLength = view.getBigUint64(60, true);
29
+ const usedBytes = view.getBigUint64(68, true);
30
+ const dataHashAlgo = hashAlgoFromId(b[76]);
31
+ const dataHash = b.slice(77, 77 + HASH_FIELD_SIZE);
32
+ return {
33
+ partitionType,
34
+ uid,
35
+ label,
36
+ startOffset,
37
+ maxLength,
38
+ usedBytes,
39
+ dataHashAlgo,
40
+ dataHash,
41
+ };
42
+ }
43
+ /**
44
+ * Apply the conformance checks a reader must run on a live entry
45
+ * (spec C5, C6, C7).
46
+ */
47
+ export function validateEntry(e) {
48
+ if (e.partitionType === TYPE_RESERVED) {
49
+ throw PcfError.reservedType();
50
+ }
51
+ if (bytesEqual(e.uid, NIL_UID)) {
52
+ throw PcfError.nilUid();
53
+ }
54
+ if (e.usedBytes > e.maxLength) {
55
+ throw PcfError.usedExceedsMax();
56
+ }
57
+ decodeLabel(e.label); // validates label bytes
58
+ }
59
+ /** Free bytes remaining in a partition (`max_length - used_bytes`). */
60
+ export function freeBytes(e) {
61
+ return e.usedBytes > e.maxLength ? 0n : e.maxLength - e.usedBytes;
62
+ }
63
+ /** Decode an entry's label as a string (reads up to the first NUL). */
64
+ export function entryLabelString(e) {
65
+ return decodeLabel(e.label);
66
+ }
67
+ /** Build a 32-byte label field from a string (spec section 10). */
68
+ export function encodeLabel(s) {
69
+ // Labels are ASCII (0x01..0x7F); reject anything that is not.
70
+ const out = new Uint8Array(LABEL_SIZE);
71
+ let n = 0;
72
+ for (const ch of s) {
73
+ const code = ch.codePointAt(0);
74
+ if (code === 0 || code >= 0x80) {
75
+ throw PcfError.invalidLabel();
76
+ }
77
+ if (n >= LABEL_SIZE) {
78
+ throw PcfError.invalidLabel();
79
+ }
80
+ out[n] = code;
81
+ n++;
82
+ }
83
+ return out;
84
+ }
85
+ /**
86
+ * Decode a 32-byte label field: read until the first NUL or 32 bytes,
87
+ * rejecting any byte >= 0x80 (spec section 10).
88
+ */
89
+ export function decodeLabel(label) {
90
+ let end = LABEL_SIZE;
91
+ for (let i = 0; i < LABEL_SIZE; i++) {
92
+ const c = label[i];
93
+ if (c === 0) {
94
+ end = i;
95
+ break;
96
+ }
97
+ if (c >= 0x80) {
98
+ throw PcfError.invalidLabel();
99
+ }
100
+ }
101
+ let s = "";
102
+ for (let i = 0; i < end; i++) {
103
+ s += String.fromCharCode(label[i]);
104
+ }
105
+ return s;
106
+ }
107
+ function bytesEqual(a, b) {
108
+ if (a.length !== b.length) {
109
+ return false;
110
+ }
111
+ for (let i = 0; i < a.length; i++) {
112
+ if (a[i] !== b[i]) {
113
+ return false;
114
+ }
115
+ }
116
+ return true;
117
+ }
118
+ //# sourceMappingURL=entry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entry.js","sourceRoot":"","sources":["../src/entry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Error type shared across the library (mirrors the reference `Error` enum).
3
+ */
4
+ /** Discriminant identifying which kind of {@link PcfError} occurred. */
5
+ export declare enum PcfErrorKind {
6
+ /** Underlying I/O failure. */
7
+ Io = "Io",
8
+ /** The file does not begin with the PCF magic. */
9
+ BadMagic = "BadMagic",
10
+ /** The file's major version is not implemented by this library. */
11
+ UnsupportedMajor = "UnsupportedMajor",
12
+ /** A hash-algorithm identifier is not in the registry. */
13
+ UnknownHashAlgo = "UnknownHashAlgo",
14
+ /** A live entry used the reserved type `0x00000000`. */
15
+ ReservedType = "ReservedType",
16
+ /** A live entry used the NIL UID. */
17
+ NilUid = "NilUid",
18
+ /** `used_bytes` exceeded `max_length` for an entry. */
19
+ UsedExceedsMax = "UsedExceedsMax",
20
+ /** A label byte was outside the permitted range (>= 0x80), or too long. */
21
+ InvalidLabel = "InvalidLabel",
22
+ /** A table block failed hash verification. */
23
+ TableHashMismatch = "TableHashMismatch",
24
+ /** A partition's data failed hash verification. */
25
+ DataHashMismatch = "DataHashMismatch",
26
+ /** An in-place update supplied more data than the partition's reservation. */
27
+ DataTooLarge = "DataTooLarge",
28
+ /** No partition with the requested UID exists. */
29
+ NotFound = "NotFound",
30
+ /** An attempt was made to add a partition whose UID already exists. */
31
+ DuplicateUid = "DuplicateUid"
32
+ }
33
+ /** All ways a PCF operation can fail. */
34
+ export declare class PcfError extends Error {
35
+ /** The kind of failure. */
36
+ readonly kind: PcfErrorKind;
37
+ /**
38
+ * Optional numeric detail (e.g. the unsupported major version or the unknown
39
+ * hash-algorithm id), preserved for the variants that carry one.
40
+ */
41
+ readonly value?: number;
42
+ constructor(kind: PcfErrorKind, message: string, value?: number);
43
+ static badMagic(): PcfError;
44
+ static unsupportedMajor(v: number): PcfError;
45
+ static unknownHashAlgo(id: number): PcfError;
46
+ static reservedType(): PcfError;
47
+ static nilUid(): PcfError;
48
+ static usedExceedsMax(): PcfError;
49
+ static invalidLabel(): PcfError;
50
+ static tableHashMismatch(): PcfError;
51
+ static dataHashMismatch(): PcfError;
52
+ static dataTooLarge(): PcfError;
53
+ static notFound(): PcfError;
54
+ static duplicateUid(): PcfError;
55
+ }
56
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,wEAAwE;AACxE,oBAAY,YAAY;IACtB,8BAA8B;IAC9B,EAAE,OAAO;IACT,kDAAkD;IAClD,QAAQ,aAAa;IACrB,mEAAmE;IACnE,gBAAgB,qBAAqB;IACrC,0DAA0D;IAC1D,eAAe,oBAAoB;IACnC,wDAAwD;IACxD,YAAY,iBAAiB;IAC7B,qCAAqC;IACrC,MAAM,WAAW;IACjB,uDAAuD;IACvD,cAAc,mBAAmB;IACjC,2EAA2E;IAC3E,YAAY,iBAAiB;IAC7B,8CAA8C;IAC9C,iBAAiB,sBAAsB;IACvC,mDAAmD;IACnD,gBAAgB,qBAAqB;IACrC,8EAA8E;IAC9E,YAAY,iBAAiB;IAC7B,kDAAkD;IAClD,QAAQ,aAAa;IACrB,uEAAuE;IACvE,YAAY,iBAAiB;CAC9B;AAED,yCAAyC;AACzC,qBAAa,QAAS,SAAQ,KAAK;IACjC,2BAA2B;IAC3B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B;;;OAGG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;gBAEZ,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;IAS/D,MAAM,CAAC,QAAQ,IAAI,QAAQ;IAI3B,MAAM,CAAC,gBAAgB,CAAC,CAAC,EAAE,MAAM,GAAG,QAAQ;IAQ5C,MAAM,CAAC,eAAe,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ;IAQ5C,MAAM,CAAC,YAAY,IAAI,QAAQ;IAO/B,MAAM,CAAC,MAAM,IAAI,QAAQ;IAIzB,MAAM,CAAC,cAAc,IAAI,QAAQ;IAOjC,MAAM,CAAC,YAAY,IAAI,QAAQ;IAI/B,MAAM,CAAC,iBAAiB,IAAI,QAAQ;IAOpC,MAAM,CAAC,gBAAgB,IAAI,QAAQ;IAOnC,MAAM,CAAC,YAAY,IAAI,QAAQ;IAO/B,MAAM,CAAC,QAAQ,IAAI,QAAQ;IAI3B,MAAM,CAAC,YAAY,IAAI,QAAQ;CAGhC"}
package/dist/errors.js ADDED
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Error type shared across the library (mirrors the reference `Error` enum).
3
+ */
4
+ /** Discriminant identifying which kind of {@link PcfError} occurred. */
5
+ export var PcfErrorKind;
6
+ (function (PcfErrorKind) {
7
+ /** Underlying I/O failure. */
8
+ PcfErrorKind["Io"] = "Io";
9
+ /** The file does not begin with the PCF magic. */
10
+ PcfErrorKind["BadMagic"] = "BadMagic";
11
+ /** The file's major version is not implemented by this library. */
12
+ PcfErrorKind["UnsupportedMajor"] = "UnsupportedMajor";
13
+ /** A hash-algorithm identifier is not in the registry. */
14
+ PcfErrorKind["UnknownHashAlgo"] = "UnknownHashAlgo";
15
+ /** A live entry used the reserved type `0x00000000`. */
16
+ PcfErrorKind["ReservedType"] = "ReservedType";
17
+ /** A live entry used the NIL UID. */
18
+ PcfErrorKind["NilUid"] = "NilUid";
19
+ /** `used_bytes` exceeded `max_length` for an entry. */
20
+ PcfErrorKind["UsedExceedsMax"] = "UsedExceedsMax";
21
+ /** A label byte was outside the permitted range (>= 0x80), or too long. */
22
+ PcfErrorKind["InvalidLabel"] = "InvalidLabel";
23
+ /** A table block failed hash verification. */
24
+ PcfErrorKind["TableHashMismatch"] = "TableHashMismatch";
25
+ /** A partition's data failed hash verification. */
26
+ PcfErrorKind["DataHashMismatch"] = "DataHashMismatch";
27
+ /** An in-place update supplied more data than the partition's reservation. */
28
+ PcfErrorKind["DataTooLarge"] = "DataTooLarge";
29
+ /** No partition with the requested UID exists. */
30
+ PcfErrorKind["NotFound"] = "NotFound";
31
+ /** An attempt was made to add a partition whose UID already exists. */
32
+ PcfErrorKind["DuplicateUid"] = "DuplicateUid";
33
+ })(PcfErrorKind || (PcfErrorKind = {}));
34
+ /** All ways a PCF operation can fail. */
35
+ export class PcfError extends Error {
36
+ /** The kind of failure. */
37
+ kind;
38
+ /**
39
+ * Optional numeric detail (e.g. the unsupported major version or the unknown
40
+ * hash-algorithm id), preserved for the variants that carry one.
41
+ */
42
+ value;
43
+ constructor(kind, message, value) {
44
+ super(message);
45
+ this.name = "PcfError";
46
+ this.kind = kind;
47
+ this.value = value;
48
+ // Restore the prototype chain when targeting older runtimes.
49
+ Object.setPrototypeOf(this, PcfError.prototype);
50
+ }
51
+ static badMagic() {
52
+ return new PcfError(PcfErrorKind.BadMagic, "bad magic: not a PCF file");
53
+ }
54
+ static unsupportedMajor(v) {
55
+ return new PcfError(PcfErrorKind.UnsupportedMajor, `unsupported major version ${v}`, v);
56
+ }
57
+ static unknownHashAlgo(id) {
58
+ return new PcfError(PcfErrorKind.UnknownHashAlgo, `unknown hash algorithm id ${id}`, id);
59
+ }
60
+ static reservedType() {
61
+ return new PcfError(PcfErrorKind.ReservedType, "reserved partition type used for a live entry");
62
+ }
63
+ static nilUid() {
64
+ return new PcfError(PcfErrorKind.NilUid, "NIL UID used for a live entry");
65
+ }
66
+ static usedExceedsMax() {
67
+ return new PcfError(PcfErrorKind.UsedExceedsMax, "used_bytes exceeds max_length");
68
+ }
69
+ static invalidLabel() {
70
+ return new PcfError(PcfErrorKind.InvalidLabel, "invalid label");
71
+ }
72
+ static tableHashMismatch() {
73
+ return new PcfError(PcfErrorKind.TableHashMismatch, "table block hash mismatch");
74
+ }
75
+ static dataHashMismatch() {
76
+ return new PcfError(PcfErrorKind.DataHashMismatch, "partition data hash mismatch");
77
+ }
78
+ static dataTooLarge() {
79
+ return new PcfError(PcfErrorKind.DataTooLarge, "data larger than partition reservation");
80
+ }
81
+ static notFound() {
82
+ return new PcfError(PcfErrorKind.NotFound, "partition not found");
83
+ }
84
+ static duplicateUid() {
85
+ return new PcfError(PcfErrorKind.DuplicateUid, "duplicate UID");
86
+ }
87
+ }
88
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
package/dist/hash.d.ts ADDED
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Hash-algorithm registry (spec section 8).
3
+ *
4
+ * Each hash field in the format is a fixed 64-byte field accompanied by a
5
+ * `u8` algorithm identifier. Digests are stored left-aligned and zero-padded;
6
+ * CRC values are stored as little-endian integers, left-aligned and
7
+ * zero-padded (spec section 8.2).
8
+ *
9
+ * Digests are provided by the audited `@noble/hashes` package; the CRC variants
10
+ * are implemented locally in {@link "./crc"}.
11
+ */
12
+ /**
13
+ * A hash algorithm from the PCF registry (spec section 8.1).
14
+ *
15
+ * The numeric value of each member is exactly its on-disk registry id, so
16
+ * `algo as number` yields the id byte.
17
+ */
18
+ export declare enum HashAlgo {
19
+ /** `0` — no verification. */
20
+ None = 0,
21
+ /** `1` — CRC-32/ISO-HDLC. */
22
+ Crc32 = 1,
23
+ /** `2` — CRC-32C (Castagnoli). */
24
+ Crc32c = 2,
25
+ /** `3` — CRC-64/XZ. */
26
+ Crc64 = 3,
27
+ /** `4` — MD5 (checksum use only). */
28
+ Md5 = 4,
29
+ /** `5` — SHA-1 (checksum use only). */
30
+ Sha1 = 5,
31
+ /** `16` — SHA-256 (default). */
32
+ Sha256 = 16,
33
+ /** `17` — SHA-512. */
34
+ Sha512 = 17,
35
+ /** `18` — BLAKE3. */
36
+ Blake3 = 18
37
+ }
38
+ /** Map a registry id byte to an algorithm (spec section 8.1). */
39
+ export declare function hashAlgoFromId(id: number): HashAlgo;
40
+ /** The registry id byte for an algorithm. */
41
+ export declare function hashAlgoId(algo: HashAlgo): number;
42
+ /** Number of significant bytes an algorithm writes into a hash field. */
43
+ export declare function digestLen(algo: HashAlgo): number;
44
+ /** Whether an algorithm performs any verification (everything but `None`). */
45
+ export declare function verifies(algo: HashAlgo): boolean;
46
+ /**
47
+ * Compute the full 64-byte hash field for `data` per spec section 8.2.
48
+ *
49
+ * Digest-producing algorithms write their digest starting at byte 0; CRCs write
50
+ * a little-endian integer of their width; all remaining bytes are 0x00.
51
+ * Algorithm `None` yields an all-zero field.
52
+ */
53
+ export declare function computeHashField(algo: HashAlgo, data: Uint8Array): Uint8Array;
54
+ /**
55
+ * Verify `data` against a stored 64-byte hash field. `None` always succeeds
56
+ * (no verification). Only the significant prefix is compared, per spec 8.2.
57
+ */
58
+ export declare function verifyHashField(algo: HashAlgo, data: Uint8Array, stored: Uint8Array): boolean;
59
+ //# sourceMappingURL=hash.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.d.ts","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAUH;;;;;GAKG;AACH,oBAAY,QAAQ;IAClB,6BAA6B;IAC7B,IAAI,IAAI;IACR,6BAA6B;IAC7B,KAAK,IAAI;IACT,kCAAkC;IAClC,MAAM,IAAI;IACV,uBAAuB;IACvB,KAAK,IAAI;IACT,qCAAqC;IACrC,GAAG,IAAI;IACP,uCAAuC;IACvC,IAAI,IAAI;IACR,gCAAgC;IAChC,MAAM,KAAK;IACX,sBAAsB;IACtB,MAAM,KAAK;IACX,qBAAqB;IACrB,MAAM,KAAK;CACZ;AAID,iEAAiE;AACjE,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ,CAKnD;AAED,6CAA6C;AAC7C,wBAAgB,UAAU,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAEjD;AAED,yEAAyE;AACzE,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,GAAG,MAAM,CAmBhD;AAED,8EAA8E;AAC9E,wBAAgB,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAEhD;AAiBD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,UAAU,GAAG,UAAU,CA+B7E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,UAAU,GACjB,OAAO,CAYT"}
package/dist/hash.js ADDED
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Hash-algorithm registry (spec section 8).
3
+ *
4
+ * Each hash field in the format is a fixed 64-byte field accompanied by a
5
+ * `u8` algorithm identifier. Digests are stored left-aligned and zero-padded;
6
+ * CRC values are stored as little-endian integers, left-aligned and
7
+ * zero-padded (spec section 8.2).
8
+ *
9
+ * Digests are provided by the audited `@noble/hashes` package; the CRC variants
10
+ * are implemented locally in {@link "./crc"}.
11
+ */
12
+ import { sha256, sha512 } from "@noble/hashes/sha2";
13
+ import { md5, sha1 } from "@noble/hashes/legacy";
14
+ import { blake3 } from "@noble/hashes/blake3";
15
+ import { HASH_FIELD_SIZE } from "./consts.js";
16
+ import { crc32, crc32c, crc64 } from "./crc.js";
17
+ import { PcfError } from "./errors.js";
18
+ /**
19
+ * A hash algorithm from the PCF registry (spec section 8.1).
20
+ *
21
+ * The numeric value of each member is exactly its on-disk registry id, so
22
+ * `algo as number` yields the id byte.
23
+ */
24
+ export var HashAlgo;
25
+ (function (HashAlgo) {
26
+ /** `0` — no verification. */
27
+ HashAlgo[HashAlgo["None"] = 0] = "None";
28
+ /** `1` — CRC-32/ISO-HDLC. */
29
+ HashAlgo[HashAlgo["Crc32"] = 1] = "Crc32";
30
+ /** `2` — CRC-32C (Castagnoli). */
31
+ HashAlgo[HashAlgo["Crc32c"] = 2] = "Crc32c";
32
+ /** `3` — CRC-64/XZ. */
33
+ HashAlgo[HashAlgo["Crc64"] = 3] = "Crc64";
34
+ /** `4` — MD5 (checksum use only). */
35
+ HashAlgo[HashAlgo["Md5"] = 4] = "Md5";
36
+ /** `5` — SHA-1 (checksum use only). */
37
+ HashAlgo[HashAlgo["Sha1"] = 5] = "Sha1";
38
+ /** `16` — SHA-256 (default). */
39
+ HashAlgo[HashAlgo["Sha256"] = 16] = "Sha256";
40
+ /** `17` — SHA-512. */
41
+ HashAlgo[HashAlgo["Sha512"] = 17] = "Sha512";
42
+ /** `18` — BLAKE3. */
43
+ HashAlgo[HashAlgo["Blake3"] = 18] = "Blake3";
44
+ })(HashAlgo || (HashAlgo = {}));
45
+ const KNOWN_IDS = new Set([0, 1, 2, 3, 4, 5, 16, 17, 18]);
46
+ /** Map a registry id byte to an algorithm (spec section 8.1). */
47
+ export function hashAlgoFromId(id) {
48
+ if (!KNOWN_IDS.has(id)) {
49
+ throw PcfError.unknownHashAlgo(id);
50
+ }
51
+ return id;
52
+ }
53
+ /** The registry id byte for an algorithm. */
54
+ export function hashAlgoId(algo) {
55
+ return algo;
56
+ }
57
+ /** Number of significant bytes an algorithm writes into a hash field. */
58
+ export function digestLen(algo) {
59
+ switch (algo) {
60
+ case HashAlgo.None:
61
+ return 0;
62
+ case HashAlgo.Crc32:
63
+ case HashAlgo.Crc32c:
64
+ return 4;
65
+ case HashAlgo.Crc64:
66
+ return 8;
67
+ case HashAlgo.Md5:
68
+ return 16;
69
+ case HashAlgo.Sha1:
70
+ return 20;
71
+ case HashAlgo.Sha256:
72
+ case HashAlgo.Blake3:
73
+ return 32;
74
+ case HashAlgo.Sha512:
75
+ return 64;
76
+ }
77
+ }
78
+ /** Whether an algorithm performs any verification (everything but `None`). */
79
+ export function verifies(algo) {
80
+ return algo !== HashAlgo.None;
81
+ }
82
+ function writeU32Le(field, value) {
83
+ field[0] = value & 0xff;
84
+ field[1] = (value >>> 8) & 0xff;
85
+ field[2] = (value >>> 16) & 0xff;
86
+ field[3] = (value >>> 24) & 0xff;
87
+ }
88
+ function writeU64Le(field, value) {
89
+ let v = value;
90
+ for (let i = 0; i < 8; i++) {
91
+ field[i] = Number(v & 0xffn);
92
+ v >>= 8n;
93
+ }
94
+ }
95
+ /**
96
+ * Compute the full 64-byte hash field for `data` per spec section 8.2.
97
+ *
98
+ * Digest-producing algorithms write their digest starting at byte 0; CRCs write
99
+ * a little-endian integer of their width; all remaining bytes are 0x00.
100
+ * Algorithm `None` yields an all-zero field.
101
+ */
102
+ export function computeHashField(algo, data) {
103
+ const field = new Uint8Array(HASH_FIELD_SIZE);
104
+ switch (algo) {
105
+ case HashAlgo.None:
106
+ break;
107
+ case HashAlgo.Crc32:
108
+ writeU32Le(field, crc32(data));
109
+ break;
110
+ case HashAlgo.Crc32c:
111
+ writeU32Le(field, crc32c(data));
112
+ break;
113
+ case HashAlgo.Crc64:
114
+ writeU64Le(field, crc64(data));
115
+ break;
116
+ case HashAlgo.Md5:
117
+ field.set(md5(data), 0);
118
+ break;
119
+ case HashAlgo.Sha1:
120
+ field.set(sha1(data), 0);
121
+ break;
122
+ case HashAlgo.Sha256:
123
+ field.set(sha256(data), 0);
124
+ break;
125
+ case HashAlgo.Sha512:
126
+ field.set(sha512(data), 0);
127
+ break;
128
+ case HashAlgo.Blake3:
129
+ field.set(blake3(data), 0);
130
+ break;
131
+ }
132
+ return field;
133
+ }
134
+ /**
135
+ * Verify `data` against a stored 64-byte hash field. `None` always succeeds
136
+ * (no verification). Only the significant prefix is compared, per spec 8.2.
137
+ */
138
+ export function verifyHashField(algo, data, stored) {
139
+ if (!verifies(algo)) {
140
+ return true;
141
+ }
142
+ const computed = computeHashField(algo, data);
143
+ const n = digestLen(algo);
144
+ for (let i = 0; i < n; i++) {
145
+ if (computed[i] !== stored[i]) {
146
+ return false;
147
+ }
148
+ }
149
+ return true;
150
+ }
151
+ //# sourceMappingURL=hash.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hash.js","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * The fixed 20-byte file header (spec section 4).
3
+ */
4
+ /** Parsed file header. */
5
+ export interface FileHeader {
6
+ /** Major format version. */
7
+ versionMajor: number;
8
+ /** Minor format version. */
9
+ versionMinor: number;
10
+ /** Absolute offset of the first table block. */
11
+ partitionTableOffset: bigint;
12
+ }
13
+ /** Serialise a header to its on-disk 20-byte layout. */
14
+ export declare function headerToBytes(h: FileHeader): Uint8Array;
15
+ /**
16
+ * Parse a header from its on-disk 20-byte layout, validating magic and major
17
+ * version (spec conformance checks C1, C2).
18
+ */
19
+ export declare function headerFromBytes(b: Uint8Array): FileHeader;
20
+ //# sourceMappingURL=header.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"header.d.ts","sourceRoot":"","sources":["../src/header.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,0BAA0B;AAC1B,MAAM,WAAW,UAAU;IACzB,4BAA4B;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,gDAAgD;IAChD,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED,wDAAwD;AACxD,wBAAgB,aAAa,CAAC,CAAC,EAAE,UAAU,GAAG,UAAU,CAQvD;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,UAAU,GAAG,UAAU,CAiBzD"}
package/dist/header.js ADDED
@@ -0,0 +1,38 @@
1
+ /**
2
+ * The fixed 20-byte file header (spec section 4).
3
+ */
4
+ import { HEADER_SIZE, MAGIC, VERSION_MAJOR } from "./consts.js";
5
+ import { PcfError } from "./errors.js";
6
+ /** Serialise a header to its on-disk 20-byte layout. */
7
+ export function headerToBytes(h) {
8
+ const b = new Uint8Array(HEADER_SIZE);
9
+ b.set(MAGIC, 0);
10
+ const view = new DataView(b.buffer);
11
+ view.setUint16(8, h.versionMajor, true);
12
+ view.setUint16(10, h.versionMinor, true);
13
+ view.setBigUint64(12, h.partitionTableOffset, true);
14
+ return b;
15
+ }
16
+ /**
17
+ * Parse a header from its on-disk 20-byte layout, validating magic and major
18
+ * version (spec conformance checks C1, C2).
19
+ */
20
+ export function headerFromBytes(b) {
21
+ if (b.length < HEADER_SIZE) {
22
+ throw PcfError.badMagic();
23
+ }
24
+ for (let i = 0; i < MAGIC.length; i++) {
25
+ if (b[i] !== MAGIC[i]) {
26
+ throw PcfError.badMagic();
27
+ }
28
+ }
29
+ const view = new DataView(b.buffer, b.byteOffset, b.byteLength);
30
+ const versionMajor = view.getUint16(8, true);
31
+ if (versionMajor !== VERSION_MAJOR) {
32
+ throw PcfError.unsupportedMajor(versionMajor);
33
+ }
34
+ const versionMinor = view.getUint16(10, true);
35
+ const partitionTableOffset = view.getBigUint64(12, true);
36
+ return { versionMajor, versionMinor, partitionTableOffset };
37
+ }
38
+ //# sourceMappingURL=header.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"header.js","sourceRoot":"","sources":["../src/header.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAYvC,wDAAwD;AACxD,MAAM,UAAU,aAAa,CAAC,CAAa;IACzC,MAAM,CAAC,GAAG,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IACtC,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAChB,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACxC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACzC,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC,CAAC,oBAAoB,EAAE,IAAI,CAAC,CAAC;IACpD,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,CAAa;IAC3C,IAAI,CAAC,CAAC,MAAM,GAAG,WAAW,EAAE,CAAC;QAC3B,MAAM,QAAQ,CAAC,QAAQ,EAAE,CAAC;IAC5B,CAAC;IACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YACtB,MAAM,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;IAChE,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC7C,IAAI,YAAY,KAAK,aAAa,EAAE,CAAC;QACnC,MAAM,QAAQ,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;IAChD,CAAC;IACD,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC9C,MAAM,oBAAoB,GAAG,IAAI,CAAC,YAAY,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IACzD,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,oBAAoB,EAAE,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * # `pcf` — Partitioned Container Format (TypeScript implementation)
3
+ *
4
+ * A language-agnostic binary container that stores multiple independent regions
5
+ * of bytes ("partitions") in a single file. This package mirrors the written
6
+ * specification (`PCF-spec-v1.0.txt`) and the Rust reference implementation
7
+ * field-for-field and favours auditability over performance.
8
+ *
9
+ * ## Layout at a glance
10
+ *
11
+ * ```text
12
+ * [ 20-byte header ] [ table block(s) ] [ partition data regions ]
13
+ * ```
14
+ *
15
+ * All integers are little-endian. Free space is derived as
16
+ * `maxLength - usedBytes`.
17
+ *
18
+ * ## Example
19
+ *
20
+ * ```ts
21
+ * import { Container, HashAlgo } from "pcf";
22
+ *
23
+ * const c = Container.create();
24
+ * const uid = new Uint8Array(16).fill(1);
25
+ * c.addPartition(0x10, uid, "notes", new TextEncoder().encode("hello world"), 64, HashAlgo.Sha256);
26
+ *
27
+ * c.verify();
28
+ * const entries = c.entries();
29
+ * console.log(new TextDecoder().decode(c.readPartitionData(entries[0]))); // "hello world"
30
+ * ```
31
+ */
32
+ export * from "./consts.js";
33
+ export { PcfError, PcfErrorKind } from "./errors.js";
34
+ export { HashAlgo, hashAlgoFromId, hashAlgoId, digestLen, verifies, computeHashField, verifyHashField, } from "./hash.js";
35
+ export { crc32, crc32c, crc64 } from "./crc.js";
36
+ export { type FileHeader, headerToBytes, headerFromBytes, } from "./header.js";
37
+ export { type PartitionEntry, entryToBytes, entryFromBytes, validateEntry, freeBytes, entryLabelString, encodeLabel, decodeLabel, } from "./entry.js";
38
+ export { type TableBlockHeader, tableHeaderToBytes, tableHeaderFromBytes, computeTableHash, } from "./table.js";
39
+ export { type Storage, MemoryStorage } from "./storage.js";
40
+ export { NodeFileStorage } from "./node-storage.js";
41
+ export { Container, type BlockView } from "./container.js";
42
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,cAAc,aAAa,CAAC;AAC5B,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,EACL,QAAQ,EACR,cAAc,EACd,UAAU,EACV,SAAS,EACT,QAAQ,EACR,gBAAgB,EAChB,eAAe,GAChB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAChD,OAAO,EACL,KAAK,UAAU,EACf,aAAa,EACb,eAAe,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,KAAK,cAAc,EACnB,YAAY,EACZ,cAAc,EACd,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,WAAW,EACX,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,KAAK,gBAAgB,EACrB,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,KAAK,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC"}