Function: serializeAstmRecords()
serializeAstmRecords(
input,d?):string
Serialize a whole ASTM message (or a bare record list) to a spec-clean,
CR-terminated record stream: the inverse of parseAstmRecords.
Emit is conservative: the canonical H|\^& delimiters, every embedded
delimiter re-escaped, each record closed with a CR. A message parsed with
non-canonical delimiters is normalized to the canonical set on emit: every
record, M and S included, so the emitted stream is in one delimiter set and
re-parsing it recovers every field. Passing d explicitly emits against that set
instead, and the header declares it. Normalization replaces the four delimiter
roles; a header declaration carrying characters beyond the three that hold a
role keeps them, on this path as on any other, rather than being truncated.
d is checked before anything is written. Each of the four separators must be
exactly one character, none may be a record terminator, and no two may share a
character: otherwise the emitted bytes cannot be read back as the records that
produced them, and emit has no warning channel with which to say so. A set that
fails is an AstmSerializeError with code ASTM_EMIT_INVALID_DELIMITERS.
This is stricter than the parser, which reads some sets it cannot reverse, so
serializeAstmRecords(msg, msg.delimiters) can refuse a message that parsed:
in exactly the cases where it used to emit a stream that read back wrong.
And each record is checked against the set it is being written with. Those
three conditions read the set alone, so they cannot see that field = R
escapes an R record's own type letter away. Every record's emitted line is
therefore checked to start with the letter the record models, and one that does
not is ASTM_EMIT_TYPE_LETTER_COLLISION rather than a stream that reads back as
different records. What neither check promises is that every field lands where
it did: an escape sequence whose body is a delimiter is an opaque atom, so that
delimiter never becomes a boundary, and the parse side reports that
(ASTM_UNKNOWN_ESCAPE_SEQUENCE) rather than emit refusing it.
Parameters
input
AstmMessage | readonly AstmRecord[]
A parsed AstmMessage or a list of AstmRecords.
d?
Delimiters = CANONICAL_DELIMITERS
The delimiters to emit against; defaults to the canonical H|\^& set.
Returns
string
The serialized record stream (CR after every record).
Throws
AstmSerializeError when a component contains an unencodable CR/LF
(ASTM_EMIT_UNENCODABLE_VALUE), when d fails one of the three conditions
readback requires (ASTM_EMIT_INVALID_DELIMITERS), or when a record's type
letter would not be the first character of its own emitted line
(ASTM_EMIT_TYPE_LETTER_COLLISION). The last of the three fires on the
default canonical path as well: it compares each record against the set
being emitted with, so a record read under a different set can carry a type
letter the canonical set escapes away. Omitting d is not a way around it.
Example
import { parseAstmRecords, serializeAstmRecords } from "@cosyte/astm";
const raw = "H|\\^&\rP|1\rR|1|^^^687|28.6|U/L||N||F\rL|1\r";
serializeAstmRecords(parseAstmRecords(raw)); // === raw