@cosyte/astm 0.0.14 → 0.0.15

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/dist/index.d.cts CHANGED
@@ -2042,7 +2042,10 @@ declare function attachComments(records: readonly AstmRecord[], warnings: AstmRe
2042
2042
  * set (a non-canonical source is normalized to `H|\^&` by default). Normalizing sets the
2043
2043
  * four delimiter **roles**; it does not delete a declaration's surplus characters, so a
2044
2044
  * canonically-declared header that arrived carrying surplus keeps it on the default path
2045
- * too.
2045
+ * too, **except where that surplus could not be read back as surplus, when all of it is
2046
+ * dropped** (see `declarationResidual` below). Emit re-encodes what it read, so bytes
2047
+ * can differ without anything being lost: `O&BRIEN` in a canonical stream goes out as
2048
+ * `O&E&BRIEN`.
2046
2049
  *
2047
2050
  * **One delimiter set for the whole stream.** Every record (including `H`, `M` and `S`)
2048
2051
  * is emitted against the delimiters being emitted with, and the header declares that same
@@ -2063,7 +2066,11 @@ declare function attachComments(records: readonly AstmRecord[], warnings: AstmRe
2063
2066
  * `H|\^&#` rather than losing the `#`. That holds on the **default** canonical path as
2064
2067
  * well as when a set is passed explicitly: the surplus of a canonically-declared header
2065
2068
  * survives normalization, because normalization is about the four roles and the surplus
2066
- * has none.
2069
+ * has none. It stops holding where the surplus itself could not be read back, and then
2070
+ * **the whole surplus is dropped, not the offending character alone**, on the default
2071
+ * path as much as any other: `declarationResidual` states which surpluses those are and
2072
+ * why an all-or-nothing drop is the only one of the available answers that invents
2073
+ * nothing.
2067
2074
  *
2068
2075
  * **Never break framing.** A component leaf that contains a record terminator
2069
2076
  * (`CR`/`LF`) cannot be escaped by the ASTM escape codec (only the four declared
@@ -2084,10 +2091,15 @@ declare function attachComments(records: readonly AstmRecord[], warnings: AstmRe
2084
2091
  * output, which is why they are refused at this one.
2085
2092
  *
2086
2093
  * **One position is not a modeled value and does not keep the byte:** the surplus
2087
- * of a header's delimiter declaration, where any control character is dropped
2094
+ * of a header's delimiter declaration, where a control character is dropped
2088
2095
  * silently (see `declarationResidual` below, where that disposition is argued and
2089
2096
  * where it long predates the frame-layer refusal). So "the record layer carries
2090
2097
  * these bytes" is a statement about values, not about every byte of every line.
2098
+ * Measured, one character at a time in the surplus of an otherwise spec-clean
2099
+ * `H|\^&` header: **31 of the 33 C0/`DEL` characters reach that rule and are
2100
+ * dropped**, with `warnings: []` and no error. The two that do not are `CR` and
2101
+ * `LF`, which never reach it at all, because they end the record while it is being
2102
+ * read and so are never part of any surplus the model carries.
2091
2103
  *
2092
2104
  * **Check the delimiter set before writing.** Three conditions are required for the
2093
2105
  * emitted bytes to read back as the records that produced them (each separator exactly
@@ -2166,10 +2178,12 @@ declare class AstmSerializeError extends Error {
2166
2178
  type AstmSerializeErrorCode = "ASTM_EMIT_UNENCODABLE_VALUE" | "ASTM_EMIT_INVALID_DELIMITERS" | "ASTM_EMIT_TYPE_LETTER_COLLISION";
2167
2179
  /**
2168
2180
  * Escape-encode one component leaf for spec-clean emit: the inverse of
2169
- * `decodeEscapes`. The **escape character itself is encoded first** (`&` → `&E&`)
2170
- * so a later delimiter substitution can never double-encode the `&` it just
2171
- * introduced; then the field / component / repeat delimiters map to their
2172
- * mnemonics.
2181
+ * `decodeEscapes`. Each character is read **once**, in one left-to-right pass, and
2182
+ * written either as itself or as a whole `escape` + mnemonic + `escape` triple
2183
+ * (`&` → `&E&`, the field / component / repeat delimiters → `&F&` / `&S&` / `&R&`).
2184
+ * Nothing this encoder writes is examined again, which is what makes it the exact
2185
+ * inverse of the decoder: the decoder reads the same output one token at a time,
2186
+ * so every triple it meets is a triple this encoder wrote.
2173
2187
  *
2174
2188
  * A `CR`/`LF` in the leaf has no escape mnemonic and would break framing, so it
2175
2189
  * is rejected with an {@link AstmSerializeError} rather than emitted raw, as is a
@@ -2199,7 +2213,11 @@ declare function encodeComponent(leaf: string, d: Delimiters, recordIndex?: numb
2199
2213
  * The header (`H`) is special-cased: its delimiter-definition field is emitted as
2200
2214
  * the **literal** declaration of `d`, never escaped, escaping it would corrupt the
2201
2215
  * very declaration a reader depends on, followed by any characters the modeled
2202
- * declaration carried beyond the three a reader takes its roles from. Manufacturer
2216
+ * declaration carried beyond the three a reader takes its roles from. Those surplus
2217
+ * characters are kept unless the surplus could not be read back as surplus, when
2218
+ * **all** of it is dropped: that covers a surplus carrying the field delimiter or
2219
+ * any control character, and it is silent, because emit has no warning channel.
2220
+ * Manufacturer
2203
2221
  * (`M`) and scientific (`S`) records are reproduced **byte-identically** from their
2204
2222
  * preserved `rawLine` when they are already in `d`, and re-encoded from their fields
2205
2223
  * when they are not, so their fields never collapse into one on the next read.
@@ -2234,7 +2252,11 @@ declare function serializeAstmRecord(record: AstmRecord, d?: Delimiters): string
2234
2252
  * re-parsing it recovers every field. Passing `d` explicitly emits against that set
2235
2253
  * instead, and the header declares it. Normalization replaces the four delimiter
2236
2254
  * **roles**; a header declaration carrying characters beyond the three that hold a
2237
- * role keeps them, on this path as on any other, rather than being truncated.
2255
+ * role keeps them, on this path as on any other, rather than being truncated. The
2256
+ * exception is a surplus that could not be read back as one, carrying the field
2257
+ * delimiter or any control character: there the **whole** surplus is dropped, on
2258
+ * every path including the default one, and silently, because emit returns a bare
2259
+ * string with no channel to say so.
2238
2260
  *
2239
2261
  * **`d` is checked before anything is written.** Each of the four separators must be
2240
2262
  * exactly one character, none may be a record terminator, and no two may share a
package/dist/index.d.ts CHANGED
@@ -2042,7 +2042,10 @@ declare function attachComments(records: readonly AstmRecord[], warnings: AstmRe
2042
2042
  * set (a non-canonical source is normalized to `H|\^&` by default). Normalizing sets the
2043
2043
  * four delimiter **roles**; it does not delete a declaration's surplus characters, so a
2044
2044
  * canonically-declared header that arrived carrying surplus keeps it on the default path
2045
- * too.
2045
+ * too, **except where that surplus could not be read back as surplus, when all of it is
2046
+ * dropped** (see `declarationResidual` below). Emit re-encodes what it read, so bytes
2047
+ * can differ without anything being lost: `O&BRIEN` in a canonical stream goes out as
2048
+ * `O&E&BRIEN`.
2046
2049
  *
2047
2050
  * **One delimiter set for the whole stream.** Every record (including `H`, `M` and `S`)
2048
2051
  * is emitted against the delimiters being emitted with, and the header declares that same
@@ -2063,7 +2066,11 @@ declare function attachComments(records: readonly AstmRecord[], warnings: AstmRe
2063
2066
  * `H|\^&#` rather than losing the `#`. That holds on the **default** canonical path as
2064
2067
  * well as when a set is passed explicitly: the surplus of a canonically-declared header
2065
2068
  * survives normalization, because normalization is about the four roles and the surplus
2066
- * has none.
2069
+ * has none. It stops holding where the surplus itself could not be read back, and then
2070
+ * **the whole surplus is dropped, not the offending character alone**, on the default
2071
+ * path as much as any other: `declarationResidual` states which surpluses those are and
2072
+ * why an all-or-nothing drop is the only one of the available answers that invents
2073
+ * nothing.
2067
2074
  *
2068
2075
  * **Never break framing.** A component leaf that contains a record terminator
2069
2076
  * (`CR`/`LF`) cannot be escaped by the ASTM escape codec (only the four declared
@@ -2084,10 +2091,15 @@ declare function attachComments(records: readonly AstmRecord[], warnings: AstmRe
2084
2091
  * output, which is why they are refused at this one.
2085
2092
  *
2086
2093
  * **One position is not a modeled value and does not keep the byte:** the surplus
2087
- * of a header's delimiter declaration, where any control character is dropped
2094
+ * of a header's delimiter declaration, where a control character is dropped
2088
2095
  * silently (see `declarationResidual` below, where that disposition is argued and
2089
2096
  * where it long predates the frame-layer refusal). So "the record layer carries
2090
2097
  * these bytes" is a statement about values, not about every byte of every line.
2098
+ * Measured, one character at a time in the surplus of an otherwise spec-clean
2099
+ * `H|\^&` header: **31 of the 33 C0/`DEL` characters reach that rule and are
2100
+ * dropped**, with `warnings: []` and no error. The two that do not are `CR` and
2101
+ * `LF`, which never reach it at all, because they end the record while it is being
2102
+ * read and so are never part of any surplus the model carries.
2091
2103
  *
2092
2104
  * **Check the delimiter set before writing.** Three conditions are required for the
2093
2105
  * emitted bytes to read back as the records that produced them (each separator exactly
@@ -2166,10 +2178,12 @@ declare class AstmSerializeError extends Error {
2166
2178
  type AstmSerializeErrorCode = "ASTM_EMIT_UNENCODABLE_VALUE" | "ASTM_EMIT_INVALID_DELIMITERS" | "ASTM_EMIT_TYPE_LETTER_COLLISION";
2167
2179
  /**
2168
2180
  * Escape-encode one component leaf for spec-clean emit: the inverse of
2169
- * `decodeEscapes`. The **escape character itself is encoded first** (`&` → `&E&`)
2170
- * so a later delimiter substitution can never double-encode the `&` it just
2171
- * introduced; then the field / component / repeat delimiters map to their
2172
- * mnemonics.
2181
+ * `decodeEscapes`. Each character is read **once**, in one left-to-right pass, and
2182
+ * written either as itself or as a whole `escape` + mnemonic + `escape` triple
2183
+ * (`&` → `&E&`, the field / component / repeat delimiters → `&F&` / `&S&` / `&R&`).
2184
+ * Nothing this encoder writes is examined again, which is what makes it the exact
2185
+ * inverse of the decoder: the decoder reads the same output one token at a time,
2186
+ * so every triple it meets is a triple this encoder wrote.
2173
2187
  *
2174
2188
  * A `CR`/`LF` in the leaf has no escape mnemonic and would break framing, so it
2175
2189
  * is rejected with an {@link AstmSerializeError} rather than emitted raw, as is a
@@ -2199,7 +2213,11 @@ declare function encodeComponent(leaf: string, d: Delimiters, recordIndex?: numb
2199
2213
  * The header (`H`) is special-cased: its delimiter-definition field is emitted as
2200
2214
  * the **literal** declaration of `d`, never escaped, escaping it would corrupt the
2201
2215
  * very declaration a reader depends on, followed by any characters the modeled
2202
- * declaration carried beyond the three a reader takes its roles from. Manufacturer
2216
+ * declaration carried beyond the three a reader takes its roles from. Those surplus
2217
+ * characters are kept unless the surplus could not be read back as surplus, when
2218
+ * **all** of it is dropped: that covers a surplus carrying the field delimiter or
2219
+ * any control character, and it is silent, because emit has no warning channel.
2220
+ * Manufacturer
2203
2221
  * (`M`) and scientific (`S`) records are reproduced **byte-identically** from their
2204
2222
  * preserved `rawLine` when they are already in `d`, and re-encoded from their fields
2205
2223
  * when they are not, so their fields never collapse into one on the next read.
@@ -2234,7 +2252,11 @@ declare function serializeAstmRecord(record: AstmRecord, d?: Delimiters): string
2234
2252
  * re-parsing it recovers every field. Passing `d` explicitly emits against that set
2235
2253
  * instead, and the header declares it. Normalization replaces the four delimiter
2236
2254
  * **roles**; a header declaration carrying characters beyond the three that hold a
2237
- * role keeps them, on this path as on any other, rather than being truncated.
2255
+ * role keeps them, on this path as on any other, rather than being truncated. The
2256
+ * exception is a surplus that could not be read back as one, carrying the field
2257
+ * delimiter or any control character: there the **whole** surplus is dropped, on
2258
+ * every path including the default one, and silently, because emit returns a bare
2259
+ * string with no channel to say so.
2238
2260
  *
2239
2261
  * **`d` is checked before anything is written.** Each of the four separators must be
2240
2262
  * exactly one character, none may be a record terminator, and no two may share a
package/dist/index.mjs CHANGED
@@ -1433,6 +1433,13 @@ function encodeComponent(leaf, d, recordIndex) {
1433
1433
  assertEmittableDelimiters(d, recordIndex);
1434
1434
  return encodeLeaf(leaf, d, recordIndex);
1435
1435
  }
1436
+ function escapeMnemonic(ch, d) {
1437
+ if (ch === d.escape) return "E";
1438
+ if (ch === d.field) return "F";
1439
+ if (ch === d.component) return "S";
1440
+ if (ch === d.repeat) return "R";
1441
+ return void 0;
1442
+ }
1436
1443
  function encodeLeaf(leaf, d, recordIndex) {
1437
1444
  if (leaf.includes("\r") || leaf.includes("\n")) {
1438
1445
  throw new AstmSerializeError(
@@ -1440,7 +1447,13 @@ function encodeLeaf(leaf, d, recordIndex) {
1440
1447
  recordIndex
1441
1448
  );
1442
1449
  }
1443
- return leaf.split(d.escape).join(d.escape + "E" + d.escape).split(d.field).join(d.escape + "F" + d.escape).split(d.component).join(d.escape + "S" + d.escape).split(d.repeat).join(d.escape + "R" + d.escape);
1450
+ let out = "";
1451
+ for (let i = 0; i < leaf.length; i += 1) {
1452
+ const ch = leaf.charAt(i);
1453
+ const mnemonic = escapeMnemonic(ch, d);
1454
+ out += mnemonic === void 0 ? ch : d.escape + mnemonic + d.escape;
1455
+ }
1456
+ return out;
1444
1457
  }
1445
1458
  function encodeField(repeats, d, recordIndex) {
1446
1459
  return repeats.map((rep) => rep.map((c) => encodeLeaf(c, d, recordIndex)).join(d.component)).join(d.repeat);
@@ -2356,7 +2369,7 @@ function concatBytes3(chunks) {
2356
2369
  }
2357
2370
 
2358
2371
  // src/index.ts
2359
- var VERSION = "0.0.14";
2372
+ var VERSION = "0.0.15";
2360
2373
 
2361
2374
  export { ALL_ASTM_WARNING_CODES, AMBIGUOUS_CODES, ACK as ASTM_ACK, ENQ as ASTM_ENQ, EOT as ASTM_EOT, NAK as ASTM_NAK, AstmAmbiguousStreamError, AstmFrameEncodeError, AstmFrameStrictError, AstmParseError, AstmProfileDefinitionError, AstmSerializeError, AstmStrictError, CANONICAL_DELIMITERS, FATAL_CODES, FRAME_WARNING_CODES, LIVD_WARNING_CODES, LTP_WARNING_CODES, SAFETY_CRITICAL_CODES, TOLERABLE_CODES, VERSION, WARNING_CODES, ambiguousMessageKind, ambiguousValueSplit, applyAstmProfile, applyAstmProfileToWarnings, applyLivd, astmDateToLocalISO, astmProfiles, attachComments, buildAstmMessage, classifyMessage, comments, commentsFor, composeAstmFrames, computeChecksum, decodeAstmFrames, decodeEscapes, deepFreeze, defineAstmProfile, defineLivdCatalog, delimitersRedeclared, detectFraming, encodeComponent, fieldScalar, fieldsUnseparated, frameBadChecksum, frameOversize, frameSequenceGap, frameUnterminated, getAstmProfile, getDefaultAstmProfile, interpretAbnormalFlag, interpretResultStatus, isNonStandard, isSafetyCriticalCode, listAstmProfiles, livdAmbiguousMapping, livdUnmappedCode, lookupLivdForRecord, ltpAmbiguousTransport, ltpFrameRejected, ltpInitialState, ltpReduce, ltpUnexpectedEvent, messages, nonStandardDelimiters, orders, orphanComment, parseAstmDate, parseAstmRecords, parseChecksumHex, parseFramedAstm, parseReferenceRange, partialTimestamp, patient, primaryCode, profileQuirkApplied, query, readDelimiters, recognizeUniversalTestId, resolveProfileTransport, results, serializeAstmRecord, serializeAstmRecords, serializeField, serializeFramedAstm, setDefaultAstmProfile, splitEscapeAware, toChecksumHex, tokenizeHeader, tokenizeRecord, undefinedAbnormalFlag, undefinedResultStatus, uninterpretedQueryStatus, unitsAbsent, unknownEscapeSequence, unknownRecordType, unpairedEscapeCharacter, unparseableReferenceRange, unreadableRedeclaration };
2362
2375
  //# sourceMappingURL=index.mjs.map