cesr-ts 0.2.3 → 0.3.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 (91) hide show
  1. package/README.md +31 -3
  2. package/esm/src/adapters/async-iterable.js +9 -9
  3. package/esm/src/annotate/annotator.js +18 -10
  4. package/esm/src/annotate/comments.js +3 -6
  5. package/esm/src/annotate/render.js +123 -24
  6. package/esm/src/bench/parser-benchmark.js +134 -0
  7. package/esm/src/core/bytes.js +6 -0
  8. package/esm/src/core/errors.js +24 -0
  9. package/esm/src/core/parser-attachment-collector.js +154 -0
  10. package/esm/src/core/parser-constants.js +74 -0
  11. package/esm/src/core/parser-deferred-frames.js +73 -0
  12. package/esm/src/core/parser-engine.js +128 -505
  13. package/esm/src/core/parser-frame-parser.js +643 -0
  14. package/esm/src/core/parser-policy.js +137 -0
  15. package/esm/src/core/parser-stream-state.js +62 -0
  16. package/esm/src/core/recovery-diagnostics.js +25 -0
  17. package/esm/src/index.js +4 -0
  18. package/esm/src/parser/attachment-fallback-policy.js +142 -0
  19. package/esm/src/parser/group-dispatch.js +547 -233
  20. package/esm/src/primitives/counter.js +4 -5
  21. package/esm/src/primitives/mapper.js +126 -45
  22. package/esm/src/primitives/matter.js +1 -1
  23. package/esm/src/router/router-stub.js +6 -6
  24. package/esm/src/serder/serder.js +44 -7
  25. package/esm/src/serder/smell.js +2 -1
  26. package/esm/src/tables/counter-version-registry.js +201 -0
  27. package/esm/src/version.js +2 -2
  28. package/package.json +3 -1
  29. package/types/_dnt.polyfills.d.ts +5 -0
  30. package/types/_dnt.polyfills.d.ts.map +1 -1
  31. package/types/src/adapters/async-iterable.d.ts +2 -2
  32. package/types/src/adapters/async-iterable.d.ts.map +1 -1
  33. package/types/src/adapters/effection.d.ts +2 -2
  34. package/types/src/adapters/effection.d.ts.map +1 -1
  35. package/types/src/annotate/annotator.d.ts.map +1 -1
  36. package/types/src/annotate/comments.d.ts.map +1 -1
  37. package/types/src/annotate/render.d.ts +8 -2
  38. package/types/src/annotate/render.d.ts.map +1 -1
  39. package/types/src/annotate/types.d.ts +2 -2
  40. package/types/src/annotate/types.d.ts.map +1 -1
  41. package/types/src/bench/parser-benchmark.d.ts +70 -0
  42. package/types/src/bench/parser-benchmark.d.ts.map +1 -0
  43. package/types/src/core/bytes.d.ts +6 -0
  44. package/types/src/core/bytes.d.ts.map +1 -1
  45. package/types/src/core/errors.d.ts +10 -0
  46. package/types/src/core/errors.d.ts.map +1 -1
  47. package/types/src/core/parser-attachment-collector.d.ts +51 -0
  48. package/types/src/core/parser-attachment-collector.d.ts.map +1 -0
  49. package/types/src/core/parser-constants.d.ts +30 -0
  50. package/types/src/core/parser-constants.d.ts.map +1 -0
  51. package/types/src/core/parser-deferred-frames.d.ts +38 -0
  52. package/types/src/core/parser-deferred-frames.d.ts.map +1 -0
  53. package/types/src/core/parser-engine.d.ts +53 -44
  54. package/types/src/core/parser-engine.d.ts.map +1 -1
  55. package/types/src/core/parser-frame-parser.d.ts +89 -0
  56. package/types/src/core/parser-frame-parser.d.ts.map +1 -0
  57. package/types/src/core/parser-policy.d.ts +27 -0
  58. package/types/src/core/parser-policy.d.ts.map +1 -0
  59. package/types/src/core/parser-stream-state.d.ts +30 -0
  60. package/types/src/core/parser-stream-state.d.ts.map +1 -0
  61. package/types/src/core/recovery-diagnostics.d.ts +59 -0
  62. package/types/src/core/recovery-diagnostics.d.ts.map +1 -0
  63. package/types/src/core/types.d.ts +61 -7
  64. package/types/src/core/types.d.ts.map +1 -1
  65. package/types/src/index.d.ts +4 -0
  66. package/types/src/index.d.ts.map +1 -1
  67. package/types/src/parser/attachment-fallback-policy.d.ts +78 -0
  68. package/types/src/parser/attachment-fallback-policy.d.ts.map +1 -0
  69. package/types/src/parser/group-dispatch.d.ts +85 -15
  70. package/types/src/parser/group-dispatch.d.ts.map +1 -1
  71. package/types/src/primitives/aggor.d.ts +2 -2
  72. package/types/src/primitives/aggor.d.ts.map +1 -1
  73. package/types/src/primitives/blinder.d.ts +2 -2
  74. package/types/src/primitives/blinder.d.ts.map +1 -1
  75. package/types/src/primitives/counter.d.ts.map +1 -1
  76. package/types/src/primitives/mapper.d.ts +44 -1
  77. package/types/src/primitives/mapper.d.ts.map +1 -1
  78. package/types/src/primitives/mediar.d.ts +2 -2
  79. package/types/src/primitives/mediar.d.ts.map +1 -1
  80. package/types/src/primitives/sealer.d.ts +2 -2
  81. package/types/src/primitives/sealer.d.ts.map +1 -1
  82. package/types/src/router/router-stub.d.ts +5 -5
  83. package/types/src/router/router-stub.d.ts.map +1 -1
  84. package/types/src/serder/serder.d.ts +2 -2
  85. package/types/src/serder/serder.d.ts.map +1 -1
  86. package/types/src/serder/serdery.d.ts +2 -2
  87. package/types/src/serder/serdery.d.ts.map +1 -1
  88. package/types/src/serder/smell.d.ts.map +1 -1
  89. package/types/src/tables/counter-version-registry.d.ts +90 -0
  90. package/types/src/tables/counter-version-registry.d.ts.map +1 -0
  91. package/types/src/version.d.ts +2 -2
@@ -0,0 +1,154 @@
1
+ import { parseAttachmentGroup } from "../parser/attachment-parser.js";
2
+ import { sniff } from "../parser/cold-start.js";
3
+ import { ColdStartError, ShortageError } from "./errors.js";
4
+ import { isAttachmentDomain } from "./parser-constants.js";
5
+ /**
6
+ * Parses and appends attachment groups for both:
7
+ * - normal trailing-attachment collection after frame start parse
8
+ * - pending-frame continuation after shortage pauses
9
+ */
10
+ export class AttachmentCollector {
11
+ constructor(options) {
12
+ Object.defineProperty(this, "frameBoundaryPolicy", {
13
+ enumerable: true,
14
+ configurable: true,
15
+ writable: true,
16
+ value: void 0
17
+ });
18
+ Object.defineProperty(this, "attachmentVersionFallbackPolicy", {
19
+ enumerable: true,
20
+ configurable: true,
21
+ writable: true,
22
+ value: void 0
23
+ });
24
+ Object.defineProperty(this, "recoveryDiagnosticObserver", {
25
+ enumerable: true,
26
+ configurable: true,
27
+ writable: true,
28
+ value: void 0
29
+ });
30
+ Object.defineProperty(this, "isFrameBoundaryAhead", {
31
+ enumerable: true,
32
+ configurable: true,
33
+ writable: true,
34
+ value: void 0
35
+ });
36
+ this.frameBoundaryPolicy = options.frameBoundaryPolicy;
37
+ this.attachmentVersionFallbackPolicy =
38
+ options.attachmentVersionFallbackPolicy;
39
+ this.recoveryDiagnosticObserver = options.recoveryDiagnosticObserver;
40
+ this.isFrameBoundaryAhead = options.isFrameBoundaryAhead;
41
+ }
42
+ /**
43
+ * Collect attachments from the current stream head until a frame boundary
44
+ * (including `msg` message-domain frame start) or shortage pause is reached.
45
+ */
46
+ collectTrailingAttachments(input, version, streamVersion, seed = []) {
47
+ const attachments = [...seed];
48
+ let offset = 0;
49
+ while (offset < input.length) {
50
+ const nextCold = sniff(input.slice(offset));
51
+ if (nextCold === "msg") {
52
+ break;
53
+ }
54
+ if (nextCold === "ano") {
55
+ offset = this.consumeLeadingAno(input, offset);
56
+ continue;
57
+ }
58
+ if (!isAttachmentDomain(nextCold)) {
59
+ throw new ColdStartError(`Unsupported attachment cold code ${nextCold}`);
60
+ }
61
+ try {
62
+ if (this.isFrameBoundaryAhead(input.slice(offset), streamVersion, nextCold)) {
63
+ break;
64
+ }
65
+ const { group, consumed } = parseAttachmentGroup(input.slice(offset), version, nextCold, {
66
+ versionFallbackPolicy: this.attachmentVersionFallbackPolicy,
67
+ onRecoveryDiagnostic: this.recoveryDiagnosticObserver,
68
+ });
69
+ attachments.push(group);
70
+ offset += consumed;
71
+ if (this.frameBoundaryPolicy.shouldStopAfterAttachmentGroupCollection()) {
72
+ break;
73
+ }
74
+ }
75
+ catch (error) {
76
+ if (error instanceof ShortageError) {
77
+ return {
78
+ attachments,
79
+ consumed: offset,
80
+ pausedForShortage: true,
81
+ };
82
+ }
83
+ throw error;
84
+ }
85
+ }
86
+ return {
87
+ attachments,
88
+ consumed: offset,
89
+ pausedForShortage: false,
90
+ };
91
+ }
92
+ /**
93
+ * Resume attachment parsing for a pending top-level frame.
94
+ *
95
+ * Emits no events directly; parser orchestration decides when to emit pending.
96
+ */
97
+ resumePendingFrame(input, pendingFrame, version, streamVersion) {
98
+ if (input.length === 0) {
99
+ return { consumed: 0, emitPending: false, shouldContinue: false };
100
+ }
101
+ let offset = 0;
102
+ const nextCold = sniff(input.slice(offset));
103
+ if (nextCold === "ano") {
104
+ offset = this.consumeLeadingAno(input, offset);
105
+ return {
106
+ consumed: offset,
107
+ emitPending: false,
108
+ shouldContinue: offset < input.length,
109
+ };
110
+ }
111
+ if (nextCold === "msg") {
112
+ return { consumed: 0, emitPending: true, shouldContinue: true };
113
+ }
114
+ if (!isAttachmentDomain(nextCold)) {
115
+ throw new ColdStartError(`Unsupported pending-frame continuation cold code ${nextCold}`);
116
+ }
117
+ if (this.isFrameBoundaryAhead(input.slice(offset), streamVersion, nextCold)) {
118
+ return { consumed: 0, emitPending: true, shouldContinue: true };
119
+ }
120
+ const { group, consumed } = parseAttachmentGroup(input.slice(offset), version, nextCold, {
121
+ versionFallbackPolicy: this.attachmentVersionFallbackPolicy,
122
+ onRecoveryDiagnostic: this.recoveryDiagnosticObserver,
123
+ });
124
+ pendingFrame.attachments.push(group);
125
+ offset += consumed;
126
+ if (this.frameBoundaryPolicy.shouldEmitPendingAfterAttachmentResume()) {
127
+ return { consumed: offset, emitPending: true, shouldContinue: false };
128
+ }
129
+ if (offset >= input.length) {
130
+ return { consumed: offset, emitPending: false, shouldContinue: false };
131
+ }
132
+ const afterCold = sniff(input.slice(offset));
133
+ if (afterCold === "ano") {
134
+ offset = this.consumeLeadingAno(input, offset);
135
+ return {
136
+ consumed: offset,
137
+ emitPending: false,
138
+ shouldContinue: offset < input.length,
139
+ };
140
+ }
141
+ if (afterCold === "msg") {
142
+ return { consumed: offset, emitPending: true, shouldContinue: true };
143
+ }
144
+ return { consumed: offset, emitPending: false, shouldContinue: true };
145
+ }
146
+ /** Fast-forward consecutive annotation separator bytes from a local offset. */
147
+ consumeLeadingAno(input, start) {
148
+ let offset = start;
149
+ while (offset < input.length && sniff(input.slice(offset)) === "ano") {
150
+ offset += 1;
151
+ }
152
+ return offset;
153
+ }
154
+ }
@@ -0,0 +1,74 @@
1
+ import { CtrDexV2 } from "../tables/counter-codex.js";
2
+ /** Default parser version context when no explicit selector is present. */
3
+ export const DEFAULT_VERSION = { major: 2, minor: 0 };
4
+ /** Native map-body counter codes that permit interleaved label parsing. */
5
+ export const MAP_BODY_CODES = new Set([
6
+ CtrDexV2.MapBodyGroup,
7
+ CtrDexV2.BigMapBodyGroup,
8
+ ]);
9
+ /** Counter code for stream or nested genus-version selector tokens. */
10
+ export const GENUS_VERSION_CODE = CtrDexV2.KERIACDCGenusVersion;
11
+ const FRAME_BOUNDARY_COUNTER_NAMES = new Set([
12
+ "BodyWithAttachmentGroup",
13
+ "BigBodyWithAttachmentGroup",
14
+ "NonNativeBodyGroup",
15
+ "BigNonNativeBodyGroup",
16
+ "FixBodyGroup",
17
+ "BigFixBodyGroup",
18
+ "MapBodyGroup",
19
+ "BigMapBodyGroup",
20
+ "GenericGroup",
21
+ "BigGenericGroup",
22
+ "KERIACDCGenusVersion",
23
+ ]);
24
+ /** True when counter begins a top-level frame boundary domain. */
25
+ export function isFrameBoundaryCounter(counter) {
26
+ return FRAME_BOUNDARY_COUNTER_NAMES.has(counter.name);
27
+ }
28
+ /** Counter names supported as frame starts in CESR-native domain. */
29
+ export const FRAME_START_GROUP_NAMES = new Set([
30
+ "BodyWithAttachmentGroup",
31
+ "BigBodyWithAttachmentGroup",
32
+ "NonNativeBodyGroup",
33
+ "BigNonNativeBodyGroup",
34
+ "FixBodyGroup",
35
+ "BigFixBodyGroup",
36
+ "MapBodyGroup",
37
+ "BigMapBodyGroup",
38
+ "GenericGroup",
39
+ "BigGenericGroup",
40
+ ]);
41
+ /** Wrapper counters whose payload encloses one full body+attachments frame. */
42
+ export const BODY_WITH_ATTACHMENT_GROUP_NAMES = new Set([
43
+ "BodyWithAttachmentGroup",
44
+ "BigBodyWithAttachmentGroup",
45
+ ]);
46
+ /** Non-native body counters whose payload is a texter-wrapped message body. */
47
+ export const NON_NATIVE_BODY_GROUP_NAMES = new Set([
48
+ "NonNativeBodyGroup",
49
+ "BigNonNativeBodyGroup",
50
+ ]);
51
+ /** Native body counters (fixed-field or map-body forms). */
52
+ export const NATIVE_BODY_GROUP_NAMES = new Set([
53
+ "FixBodyGroup",
54
+ "BigFixBodyGroup",
55
+ "MapBodyGroup",
56
+ "BigMapBodyGroup",
57
+ ]);
58
+ /** Generic counters whose payload contains one or more enclosed frames. */
59
+ export const GENERIC_GROUP_NAMES = new Set([
60
+ "GenericGroup",
61
+ "BigGenericGroup",
62
+ ]);
63
+ /** Domain-sensitive token size helper (qb64 vs qb2). */
64
+ export function tokenSize(token, cold) {
65
+ return cold === "bny" ? token.fullSizeB2 : token.fullSize;
66
+ }
67
+ /** Domain-sensitive counter unit (quadlet count for txt, triplet count for bny). */
68
+ export function quadletUnit(cold) {
69
+ return cold === "bny" ? 3 : 4;
70
+ }
71
+ /** Attachment parsing domains supported by the parser. */
72
+ export function isAttachmentDomain(cold) {
73
+ return cold === "txt" || cold === "bny";
74
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Manages deferred frame emission lifecycle for parser orchestration.
3
+ *
4
+ * Contract reminder:
5
+ * - `pendingFrame` is older than any `queuedFrames`.
6
+ * - flush order must preserve stream encounter order.
7
+ */
8
+ export class DeferredFrameLifecycle {
9
+ constructor() {
10
+ Object.defineProperty(this, "pendingFrame", {
11
+ enumerable: true,
12
+ configurable: true,
13
+ writable: true,
14
+ value: null
15
+ });
16
+ Object.defineProperty(this, "queuedFrames", {
17
+ enumerable: true,
18
+ configurable: true,
19
+ writable: true,
20
+ value: []
21
+ });
22
+ }
23
+ /** Current pending top-level frame continuation, if any. */
24
+ get pending() {
25
+ return this.pendingFrame;
26
+ }
27
+ /** Whether enclosed deferred frames are queued for emission. */
28
+ hasQueued() {
29
+ return this.queuedFrames.length > 0;
30
+ }
31
+ /** Store a pending top-level frame continuation. */
32
+ setPending(frame, version) {
33
+ this.pendingFrame = { frame, version };
34
+ }
35
+ /** Clear pending top-level frame continuation state. */
36
+ clearPending() {
37
+ this.pendingFrame = null;
38
+ }
39
+ /** Append enclosed frames parsed from one bounded GenericGroup payload. */
40
+ enqueueQueued(frames) {
41
+ if (frames.length === 0) {
42
+ return;
43
+ }
44
+ this.queuedFrames.push(...frames);
45
+ }
46
+ /** Emit next queued enclosed frame (FIFO) when no pending frame remains. */
47
+ shiftQueued() {
48
+ return this.queuedFrames.shift();
49
+ }
50
+ /**
51
+ * Flush deferred frames in normative order: pending first, queued next.
52
+ * Buffer-remainder shortage handling is outside this collaborator.
53
+ */
54
+ flushDeferred() {
55
+ const out = [];
56
+ if (this.pendingFrame) {
57
+ out.push({ type: "frame", frame: this.pendingFrame.frame });
58
+ this.pendingFrame = null;
59
+ }
60
+ while (this.queuedFrames.length > 0) {
61
+ const frame = this.queuedFrames.shift();
62
+ if (frame) {
63
+ out.push({ type: "frame", frame });
64
+ }
65
+ }
66
+ return out;
67
+ }
68
+ /** Clear all deferred frame lifecycle state. */
69
+ reset() {
70
+ this.pendingFrame = null;
71
+ this.queuedFrames = [];
72
+ }
73
+ }