@zerodds/wire 0.0.0-stage → 1.0.0-rc.7

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.
@@ -0,0 +1,605 @@
1
+ /**
2
+ * The read half of XCDR, implemented from DDS-XTypes 1.3 §7.4.
3
+ *
4
+ * The mirror of `writer.ts` clause for clause and not by inversion of
5
+ * it: a reader written as "whatever undoes the writer" agrees with the
6
+ * writer about a misreading of the clause, and agreement between two
7
+ * halves of one column is the one thing that proves nothing.
8
+ *
9
+ * ## Two kinds of failure, and why they are not one
10
+ *
11
+ * A malformed *stream* throws. A length that runs past the end of the
12
+ * buffer is not a state a caller can carry on from, and
13
+ * {@link Truncated} against {@link ImpossibleLength} is the distinction
14
+ * that matters: the first says the stream is short, the second says the
15
+ * stream is lying. Allocating for a claimed length before checking it
16
+ * is how a reader turns a bad message into an out-of-memory.
17
+ *
18
+ * A refusal about the *type* sets {@link Status} and does not throw.
19
+ * The runtime owns the wire and the generated decoder owns the type,
20
+ * and this reader cannot see an integer that names no enumerator, a
21
+ * bitmask bit the declaration does not have, or a member that did not
22
+ * arrive. §7.2.2.7's DISCARD is a sample the receiver drops and carries
23
+ * on from, which is not a failure of the peer.
24
+ *
25
+ * ## What TypeScript decides differently from the other columns
26
+ *
27
+ * - `readChar` and `readWchar` answer with a one-character **string**,
28
+ * not with a code point. TypeScript has no character type, the
29
+ * materialiser declares a `char` member as `string`, and
30
+ * `Writer.writeChar` takes one; a reader answering with a `number`
31
+ * would be the only one of the three that did not.
32
+ * - `readU32` answers with a `number`, because 4294967295 is far below
33
+ * `Number.MAX_SAFE_INTEGER`. `readI64` and `readU64` answer with a
34
+ * `bigint`, because 2^63 is not.
35
+ * - `readEnum`, `readBitmask` and `readBitset` answer with a `bigint`
36
+ * whatever their bound. The generated decoder compares the answer
37
+ * against 64-bit patterns, and one comparison that mixed a `number`
38
+ * with a `bigint` is a `tsc` error rather than a wrong arm — which
39
+ * is the outcome this column wants.
40
+ * - `readF128` answers with the sixteen octets. A binary64 would drop
41
+ * sixty bits of the significand at the assignment.
42
+ */
43
+ import { Endianness } from "./endianness.js";
44
+ import { FixedDigitCount, ParameterRole, Status, WcharFraming, WcharWidth, WstringLengthPolicy, WstringUnitOrder } from "./policy.js";
45
+ import { Float128, PlCdr1Framing } from "./writer.js";
46
+ /**
47
+ * The low fourteen bits of a short parameter id, which are the id.
48
+ *
49
+ * §7.4.1.2.2 puts `FLAG_IMPL_EXTENSION` at bit 15 and the
50
+ * must-understand flag at bit 14; everything below them is the
51
+ * identifier.
52
+ */
53
+ export declare const PID_ID_MASK = 16383;
54
+ /**
55
+ * `PID_IGNORE`. §7.4.1.2.2: "All consumers of this Data Representation
56
+ * shall ignore this parameter" — with no exception for the
57
+ * must-understand bit above it.
58
+ *
59
+ * Declared here and not in `writer.ts` because no writer in this tree
60
+ * emits one. It is a parameter a *peer* sends, so only the reader has
61
+ * anything to do with it.
62
+ */
63
+ export declare const PID_IGNORE = 16131;
64
+ /**
65
+ * Everything a two-pass read has to put back.
66
+ *
67
+ * One caller: a `map` under `rule-15-omits`, where a delimited map
68
+ * states no entry count and the entries are read once to count them and
69
+ * again into storage sized from that count. TypeScript allocates its own
70
+ * values, so there is no heap mark to carry — the cursor, the stream
71
+ * origin and the status are the whole of it.
72
+ *
73
+ * The status is part of it deliberately. A refusal made during the
74
+ * counting pass is a refusal about bytes that are about to be read
75
+ * again, and carrying it forward would refuse the sample twice.
76
+ */
77
+ export interface ReaderMark {
78
+ readonly at: number;
79
+ readonly origin: number;
80
+ readonly status: Status;
81
+ }
82
+ /** An EMHEADER as read. §7.4.3.4.2. */
83
+ export interface EmHeaderRead {
84
+ /** The 28-bit member id. */
85
+ readonly memberId: number;
86
+ /** The length code, 0 to 7. */
87
+ readonly lengthCode: number;
88
+ /** Whether the writer set the member's must-understand flag. */
89
+ readonly mustUnderstand: boolean;
90
+ /** The NEXTINT, for the codes that carry one. */
91
+ readonly nextInt: number;
92
+ /** Whether there was a NEXTINT at all. */
93
+ readonly hasNextInt: boolean;
94
+ /**
95
+ * How many octets the member occupies after the header word, NEXTINT
96
+ * included where there is one.
97
+ *
98
+ * What a reader skipping an unknown member advances by, and what a
99
+ * reader of a known one checks itself against. §7.4.3.4.2: codes 0 to
100
+ * 3 state a size of one, two, four or eight octets outright; code 4 is
101
+ * followed by a NEXTINT holding the member's length; and codes 5, 6
102
+ * and 7 have a NEXTINT that is *also* the member's own leading word,
103
+ * so the member spans that word plus the length it states, times one,
104
+ * four or eight.
105
+ */
106
+ readonly extent: number;
107
+ }
108
+ /** A PL_CDR1 parameter header as read. §7.4.1.2. */
109
+ export interface PidRead {
110
+ /** The member id, with the flag bits taken off. */
111
+ readonly pid: number;
112
+ /** The declared length. */
113
+ readonly length: number;
114
+ /** Whether this is the `PID_LIST_END` sentinel. */
115
+ readonly end: boolean;
116
+ /** Whether the writer set the member's must-understand flag. */
117
+ readonly mustUnderstand: boolean;
118
+ /**
119
+ * Whether the writer set `FLAG_IMPL_EXTENSION`.
120
+ *
121
+ * §7.4.1.2.2: the parameter is the writing implementation's own, and a
122
+ * user-defined member "will never set the FLAG_IMPL_EXTENSION bit".
123
+ * Masking it off with the rest would make a vendor-private parameter
124
+ * indistinguishable from the member with the same low fourteen bits.
125
+ */
126
+ readonly implExtension: boolean;
127
+ /**
128
+ * Whether the short-form id is inside §7.4.1.2.2's reserved range,
129
+ * which no member id occupies.
130
+ */
131
+ readonly reserved: boolean;
132
+ /** `PID_IGNORE`, which every consumer shall ignore. */
133
+ readonly ignore: boolean;
134
+ /** Which of §7.4.1.2's two roles the caller read it in. */
135
+ readonly role: ParameterRole;
136
+ /** The stream origin the parameter's value block replaced. */
137
+ readonly savedOrigin: number;
138
+ /**
139
+ * Where the parameter's value starts — the first octet after the
140
+ * header.
141
+ *
142
+ * Carried on the header rather than worked out again at the finish,
143
+ * because working it out again needs two things at once that are not
144
+ * both still there: the enclosing origin has been put back by then,
145
+ * and the header's own width is four octets or twelve depending on a
146
+ * form the finish can only guess at from the values it reads.
147
+ *
148
+ * `runtime/java` reconstructs it as `savedOrigin + headerOctets` and
149
+ * that is only the value start for the *first* parameter of a list:
150
+ * the enclosing origin does not move between parameters, so the
151
+ * second parameter's used length comes out as its offset from the
152
+ * start of the whole list. Measured on
153
+ * `tests/interop-results/struct-mutable/zerodds-rust/pl-cdr1.le.bin`,
154
+ * where the second member's 8 octets are computed as 16 and the
155
+ * sample is refused OUT_OF_RANGE.
156
+ */
157
+ readonly valueAt: number;
158
+ }
159
+ /**
160
+ * Whether a parameter can be one of the reading type's members.
161
+ *
162
+ * False for a vendor-private parameter, for a reserved id and for
163
+ * `PID_IGNORE`. All three are legal for a peer to send and none of them
164
+ * is a member, so all three take the unknown-parameter path — skipped,
165
+ * or the sample discarded when the writer set must-understand.
166
+ * §7.4.1.2.2, §7.2.2.4.4.4.6.
167
+ *
168
+ * A free function and not a method, because the generated decoder calls
169
+ * it without a receiver.
170
+ */
171
+ export declare function pidIsUserMember(header: PidRead): boolean;
172
+ /**
173
+ * How many octets `text` is as UTF-8, which is what a `string<N>` bound
174
+ * counts: `string<5>` is `char[6]` in the C mapping of every measured
175
+ * DDS implementation, so a five-scalar value of ten octets is one no
176
+ * peer can hold.
177
+ */
178
+ export declare function utf8Octets(text: string): number;
179
+ /**
180
+ * How many UTF-16 code units `text` is, which is what a `wstring<N>`
181
+ * bound counts. A surrogate pair is two, which is what `String.length`
182
+ * already answers.
183
+ */
184
+ export declare function utf16Units(text: string): number;
185
+ /**
186
+ * The same value in a `number`, whatever holder it arrived in.
187
+ *
188
+ * The generated decoder's narrowings are `as` in every other column and
189
+ * `as` is *erased* here: `zd_bits as number` on a `bigint` is a `tsc`
190
+ * error, and where it is not — `x as unknown as number` — it would put
191
+ * a `bigint` in a `number` field and every later comparison would be
192
+ * false. So the three coercions below are real conversions, and the
193
+ * TypeScript backend emits a call to one where the other columns emit a
194
+ * cast.
195
+ *
196
+ * A one-character string answers with its code point, which is what the
197
+ * narrowing means where the source is a `char`.
198
+ */
199
+ export declare function zdNumber(value: number | bigint | string | boolean): number;
200
+ /** The same value in a `bigint`. See {@link zdNumber}. */
201
+ export declare function zdBigInt(value: number | bigint | string | boolean): bigint;
202
+ /**
203
+ * The same value as a one-character `string`, which is what an IDL
204
+ * `char` and `wchar` are here.
205
+ *
206
+ * A value that is already a string is itself; a number or a `bigint` is
207
+ * the character its code point names. `String(65)` would be `"65"`,
208
+ * which is two characters and a different value.
209
+ */
210
+ export declare function zdChar(value: number | bigint | string): string;
211
+ export declare class Reader {
212
+ readonly order: Endianness;
213
+ readonly plCdr1: PlCdr1Framing;
214
+ private readonly bytes;
215
+ private at;
216
+ private origin;
217
+ private readonly maxAlignment;
218
+ private state;
219
+ /**
220
+ * A reader over `data` in `order`, capped at `maxAlign`.
221
+ *
222
+ * Four for XCDR2, eight for XCDR1 — {@link Writer}'s counterpart.
223
+ * §7.4.1: `ALIGN(N)` aligns to `MIN(N, XCDR.maxalign)`. A reader that
224
+ * skipped padding the writer never wrote reads the wrong octets from
225
+ * the second member on.
226
+ *
227
+ * `plCdr1` is the writer's framing, and the reader needs two things
228
+ * out of it. Under a framing that puts `FLAG_IMPL_EXTENSION` on every
229
+ * member id — OpenDDS writes `c0010004` for `@id(1) long a` — the flag
230
+ * no longer tells a vendor-private parameter from a user member. And
231
+ * §7.4.1.2.2 stops the short form's ids at `0x3F00` inclusive while
232
+ * one measured implementation carries the whole low fourteen bits, so
233
+ * a reader holding the clause's threshold as a constant reports
234
+ * `@id(16383)` as a reserved parameter and drops the member.
235
+ */
236
+ constructor(data: Uint8Array, order: Endianness, maxAlign?: number, plCdr1?: PlCdr1Framing);
237
+ /** The alignment cap in force. */
238
+ get maxAlign(): number;
239
+ /**
240
+ * Whether a refusal has been made, so every later read does nothing.
241
+ *
242
+ * The generated decoder carries on to the end of the type rather than
243
+ * returning early — that is what lets one `if` at the top of the
244
+ * caller decide what to do with the sample — and a read that consumed
245
+ * octets after a refusal would leave the cursor somewhere no writer
246
+ * put it, which the trailing-octet check at the top would then report
247
+ * as a second, invented, fault.
248
+ */
249
+ private stopped;
250
+ /** How the read is going. */
251
+ readerStatus(): Status;
252
+ /** Refuse the stream from outside the runtime. The first refusal sticks. */
253
+ readerRefuse(refusal: Status): void;
254
+ /**
255
+ * Take back a {@link Status.Discarded}, and only that one.
256
+ *
257
+ * A member whose own `@try_construct` is `USE_DEFAULT` but which also
258
+ * carries an explicit `@default` cannot be answered inside the type's
259
+ * decoder: the decoder knows Table 9's value for the type and not the
260
+ * literal the member's declaration gave it, and §7.2.2.4.4.4.9 puts
261
+ * the literal first. So the call site asks for DISCARD, and where it
262
+ * gets one it clears it and assigns the literal.
263
+ *
264
+ * Every other status stays: a truncated stream is not a narrowing.
265
+ */
266
+ readerClearDiscard(): boolean;
267
+ /** Where it is. The generated decoder's name for {@link position}. */
268
+ readerPosition(): number;
269
+ /** How many octets are left. */
270
+ readerRemaining(): number;
271
+ /**
272
+ * Move the alignment origin to the current position.
273
+ *
274
+ * The read-side pair of the writer's `beginPackedElement`, for
275
+ * `ElementPadding::Packed`. Returns the origin displaced.
276
+ */
277
+ readerBeginPackedElement(): number;
278
+ /** Restore the origin {@link readerBeginPackedElement} displaced. */
279
+ readerFinishPackedElement(saved: number): void;
280
+ /**
281
+ * Move the cursor forward to `target`, which is never backwards.
282
+ *
283
+ * A framing word pointing behind the cursor means the reader has
284
+ * already read past what it framed, and seeking back would paper over
285
+ * it: the member would be read twice and the sample would come back
286
+ * plausible.
287
+ */
288
+ readerSkipTo(target: number): void;
289
+ /** The cursor, the origin and the status, to be put back later. */
290
+ readerSave(): ReaderMark;
291
+ /** Put back what {@link readerSave} took. */
292
+ readerRestore(mark: ReaderMark): void;
293
+ /** Where it is. */
294
+ position(): number;
295
+ /** How many octets are left. */
296
+ remaining(): number;
297
+ /** Skip padding to `align`, counted from the stream's origin. */
298
+ alignTo(align: number): void;
299
+ /** Step over `count` octets, refusing to step past the end. */
300
+ skip(count: number): void;
301
+ /** Move to an absolute offset inside the buffer. */
302
+ seek(target: number): void;
303
+ /**
304
+ * Advance over `count` octets and answer where they started.
305
+ *
306
+ * A negative count is refused rather than treated as zero: it can only
307
+ * come from a length field this reader computed wrongly, and a zero
308
+ * there would carry on reading at an offset nothing wrote.
309
+ */
310
+ private take;
311
+ /**
312
+ * An integer of `width` octets in the stream's order, as a `bigint`.
313
+ *
314
+ * A `bigint` throughout and narrowed by the caller, because the eight-
315
+ * octet case does not fit a `number` and a second code path for it
316
+ * would be the one place the two widths could disagree about a sign.
317
+ */
318
+ private readInt;
319
+ /** {@link readInt} in a stated order rather than the stream's. */
320
+ private rawInt;
321
+ /**
322
+ * `boolean`.
323
+ *
324
+ * An octet that is neither 0 nor 1 is a stream that disagrees with its
325
+ * own type, and is refused rather than coerced: `!!octet` would turn
326
+ * every one of the 254 impossible values into `true` and say nothing.
327
+ */
328
+ readBool(): boolean;
329
+ /** `octet` and `uint8`. */
330
+ readU8(): number;
331
+ /** `int8`. */
332
+ readI8(): number;
333
+ /**
334
+ * `char`, one octet, as the one-character string it is here.
335
+ *
336
+ * The octet is a code point in `[0, 255]` and not a UTF-8 lead: an IDL
337
+ * `char` is one octet and §7.4.1.1.1 gives it no encoding of its own,
338
+ * so `0xE4` is U+00E4 and not the first half of anything.
339
+ */
340
+ readChar(): string;
341
+ /**
342
+ * `wchar`, at `width` octets and in `framing`'s shape.
343
+ *
344
+ * The four-octet form is RTI Connext's under XCDR1, where the high
345
+ * sixteen bits are padding around one UTF-16 code unit. A value that
346
+ * uses them is refused rather than narrowed: narrowing would return a
347
+ * character the peer never sent.
348
+ *
349
+ * {@link WcharFraming.GiopLengthPrefixed} is CORBA 3.3 part 2
350
+ * §9.3.1.6's GIOP 1.2 form, which all three ORBs write. The octet
351
+ * count is checked against the configured code-set width rather than
352
+ * believed: a stream whose first octet says `0xE4` — which is what a
353
+ * bare two-octet `wchar` looks like read this way — would otherwise
354
+ * consume 228 octets of whatever followed and return a character
355
+ * assembled out of the next four members.
356
+ */
357
+ readWchar(width?: WcharWidth, framing?: WcharFraming, order?: WstringUnitOrder): string;
358
+ /** `short`. */
359
+ readI16(): number;
360
+ /** `unsigned short`. */
361
+ readU16(): number;
362
+ /** `long`. */
363
+ readI32(): number;
364
+ /**
365
+ * `unsigned long`, as a `number`.
366
+ *
367
+ * 4294967295 is far below `Number.MAX_SAFE_INTEGER`, so unlike the
368
+ * Java column nothing has to widen and unlike the C column nothing
369
+ * comes back negative.
370
+ */
371
+ readU32(): number;
372
+ /** `long long`, which is a `bigint` because a binary64 is not one. */
373
+ readI64(): bigint;
374
+ /**
375
+ * `unsigned long long`, as the value and not as a pattern.
376
+ *
377
+ * Where the Java column has to hand back `-1L` for
378
+ * `0xFFFFFFFFFFFFFFFF` because it has nothing wider than a `long`, a
379
+ * `bigint` holds 18446744073709551615 as itself.
380
+ */
381
+ readU64(): bigint;
382
+ /** `float`, a binary32. */
383
+ readF32(): number;
384
+ /** `double`, a binary64. */
385
+ readF64(): number;
386
+ /**
387
+ * `long double`: all sixteen octets, as the writer's counterpart holds
388
+ * them.
389
+ *
390
+ * The octets come back in the order a little-endian stream carries
391
+ * them, which is what {@link Writer.writeF128} takes; a big-endian
392
+ * stream's are reversed on the way in. Reading the first eight as a
393
+ * `double` and skipping the rest would decode every value a binary64
394
+ * cannot hold as a different number and say nothing.
395
+ */
396
+ readF128(): Float128;
397
+ /** A 16-bit value little-endian whatever the stream's order is. */
398
+ readU16Little(): number;
399
+ /** A 16-bit value big-endian whatever the stream's order is. */
400
+ readU16Big(): number;
401
+ /** A 32-bit value little-endian whatever the stream's order is. */
402
+ readU32Little(): number;
403
+ /** A 32-bit value big-endian whatever the stream's order is. */
404
+ readU32Big(): number;
405
+ /**
406
+ * `string`: a four-octet length that includes the terminator, then the
407
+ * octets, then a NUL. §7.4.1.1.1.
408
+ *
409
+ * A declared length of zero is impossible rather than empty: the count
410
+ * includes the terminator, so the shortest honest frame states one.
411
+ * A length past the end is {@link ImpossibleLength} and not
412
+ * {@link Truncated} — the stream is not short, the field is lying, and
413
+ * a reader that allocated for it first would be the vector.
414
+ */
415
+ readString(): string;
416
+ /**
417
+ * A `string` the reader materialises itself.
418
+ *
419
+ * `runtime/c` takes it out of a heap the caller set, because an
420
+ * embedded target decides where memory comes from. TypeScript has one
421
+ * answer to that question and this is it; the name is kept so that one
422
+ * walk names one operation in both columns.
423
+ */
424
+ readStringAlloc(): string;
425
+ /**
426
+ * A `wstring`, in whichever length convention the policy names.
427
+ *
428
+ * `runtime/c` converts to UTF-8 because that is what its
429
+ * `const char *` holds, and its name carries it. A TypeScript `string`
430
+ * is UTF-16 already and {@link readWstring} is the whole of the
431
+ * operation.
432
+ */
433
+ readWstringUtf8(policy: WstringLengthPolicy, order: WstringUnitOrder): string;
434
+ /**
435
+ * The inverse of `Writer.writeWstringUtf8Octets`.
436
+ *
437
+ * `WstringCodeUnits::Utf8`: the declared length is the UTF-8 octet count,
438
+ * and the terminator `policy` asks for is the last of those octets. A count
439
+ * the stream cannot hold, a missing or an interior NUL, or an ill-formed
440
+ * UTF-8 sequence is refused, never a replacement character or a truncated
441
+ * value.
442
+ */
443
+ readWstringUtf8Octets(policy: WstringLengthPolicy): string;
444
+ /**
445
+ * A `wstring`, in the form `policy` and `order` name.
446
+ *
447
+ * Under {@link WstringLengthPolicy.Specification} the count is octets
448
+ * and not characters — §7.4.1.1.2 — so a count the code-unit width
449
+ * does not divide is a stream no encoder produced and is refused
450
+ * rather than rounded down: rounding would leave the remainder in the
451
+ * stream and put every later member at the wrong offset.
452
+ *
453
+ * The form is never inferred from the stream. The cells are not
454
+ * separable: a Fast DDS `"ab"` followed by a `long` is byte-identical
455
+ * to a specification `"a"` followed by the same `long`, differing only
456
+ * in padding no clause fixes. Choosing between them would mean letting
457
+ * the length field — the one field a hostile peer controls — decide
458
+ * how much is read.
459
+ */
460
+ readWstring(policy: WstringLengthPolicy, order: WstringUnitOrder): string;
461
+ /**
462
+ * `count` `wstring` characters of `width` octets, as UTF-16 units.
463
+ *
464
+ * The whole run is checked against what is left **before** the first
465
+ * unit is read, because a count is what a hostile peer controls: the
466
+ * check is the difference between refusing a frame and reading 4·2^32
467
+ * octets of whatever follows.
468
+ *
469
+ * The four-octet width is RTI's XCDR1 form, where a character is a
470
+ * code unit zero-extended. A value above `0xFFFF` there is not a form
471
+ * this reader knows how to narrow, so it is refused rather than
472
+ * truncated — truncating is the defect this whole policy exists
473
+ * because of.
474
+ */
475
+ private readWstringUnits;
476
+ /**
477
+ * `text` cut to at most `octets` UTF-8 octets, never inside a
478
+ * character.
479
+ *
480
+ * Table 11: "The order of the characters in the string ... is
481
+ * preserved", so this is a prefix. A character that would straddle the
482
+ * bound is left out whole: a peer holding `char[octets + 1]` cannot
483
+ * store half of one either, and half a UTF-8 sequence is not text.
484
+ */
485
+ trimUtf8(text: string, octets: number): string;
486
+ /**
487
+ * `text` cut to at most `units` UTF-16 code units, never between the
488
+ * halves of a surrogate pair.
489
+ */
490
+ trimUtf16(text: string, units: number): string;
491
+ /**
492
+ * `fixed<digits, scale>`, as the decimal string the writer took.
493
+ *
494
+ * The mirror of `Writer.writeFixed`: `ceil((digits + 1) / 2)` octets
495
+ * of BCD, digits most-significant first, sign nibble last.
496
+ *
497
+ * The leading zeros go, because the BCD field is `digits` wide
498
+ * whatever the value: the nibbles for `0.01` in a `fixed<5, 2>` spell
499
+ * `00001`, and returning `"000.01"` would put a decimal on the read
500
+ * side that the write side would never produce from the same value.
501
+ * A negative zero loses its sign for the same reason: `-0.00` and
502
+ * `0.00` are one value, and the sign nibble is the only place they
503
+ * differ.
504
+ *
505
+ * Under {@link FixedDigitCount.ValuePrecision} the field's end is read
506
+ * out of the octets: [CDR] §9.3.2.8 makes a digit `0` to `9` and a
507
+ * sign `0xa` upwards, and the nibble count is even by construction, so
508
+ * the field ends at the first octet whose **low** nibble is a sign. A
509
+ * field that never presents one within the sixteen octets of the
510
+ * widest `fixed` IDL admits is refused.
511
+ */
512
+ readFixed(digits: number, scale: number, count: FixedDigitCount): string;
513
+ /**
514
+ * An enumerator's holder, **sign-extended from its holder's width**.
515
+ *
516
+ * §7.4.3.5.3 rule (5) makes the holder signed: `@value(200)` under a
517
+ * bound of eight goes out as `c8`, and that octet read as the type
518
+ * says is `-56`. `@value(-1)` and `@value(255)` are the same octet and
519
+ * nothing in the stream separates them — which one was meant is a
520
+ * question about the *type*, and the generated decoder answers it by
521
+ * comparing this against each declared enumerator's own pattern, taken
522
+ * the same way.
523
+ *
524
+ * The Java column had this unsigned while its walk compared against
525
+ * the signed pattern, and every `@bit_bound(8)` enumerator above 127
526
+ * matched no arm at all — the sample came back discarded rather than
527
+ * wrong, which is why it took a corpus run to find. The sign extension
528
+ * is from the *holder's* width and not from the bound: `@bit_bound(5)`
529
+ * still occupies an octet, and rule (5) makes the octet signed.
530
+ */
531
+ readEnum(bitBound: number): bigint;
532
+ /** A bitmask's holder. Table 33 of §7.4.1.1.3.2. */
533
+ readBitmask(bitBound: number): bigint;
534
+ /** A bitset's anchor integer, of the width the planner sized. */
535
+ readBitset(anchorOctets: number): bigint;
536
+ /**
537
+ * A sequence's element count, refusing one the stream cannot hold.
538
+ *
539
+ * An element is one octet or more, so a stream with fewer octets left
540
+ * than elements claimed cannot be honest about it. Allocating for it
541
+ * is how a reader turns a bad message into an out-of-memory — and in
542
+ * this column `new Array(n)` for a claimed 4294967295 is exactly that.
543
+ */
544
+ readSequenceLength(): number;
545
+ /** A DHEADER: the length the members that follow occupy. §7.4.3.5.3. */
546
+ readDheader(): number;
547
+ /**
548
+ * An EMHEADER, unpacked into its parts and the NEXTINT it carries.
549
+ *
550
+ * Codes 5 to 7 report the NEXTINT they read, but the reader is put
551
+ * back before it: §7.4.3.4.2 says that word "shall be reused also as
552
+ * part of the serialized member", so it is the member's own leading
553
+ * length and the member's decoder has to see it.
554
+ */
555
+ readEmheader(): EmHeaderRead;
556
+ /** A PL_CDR1 parameter header in the {@link ParameterRole.Member} role. */
557
+ readPid(): PidRead;
558
+ /**
559
+ * A PL_CDR1 parameter header, in whichever form it was written.
560
+ *
561
+ * `role` is the caller's, not the stream's: the octets are the same
562
+ * octets and only what the declared length means differs. §7.4.1.2.
563
+ */
564
+ readPidAs(role: ParameterRole): PidRead;
565
+ /**
566
+ * End a parameter's value and step to the next header.
567
+ *
568
+ * The padding to four follows the value and is outside the declared
569
+ * length, so the next parameter is found by alignment and not by
570
+ * adding the length — which is what lets one reader take RTI's
571
+ * rounded-up length and Fast DDS's exact one.
572
+ *
573
+ * The declared length is checked against the configured framing rather
574
+ * than believed: a length belonging to the other convention is a
575
+ * stream this reader was pointed at with the wrong framing, and
576
+ * reading on would put every later member at an offset no writer
577
+ * produced. Both readings are accepted where they coincide, which is
578
+ * every value already a multiple of four.
579
+ */
580
+ finishPidRead(header: PidRead): void;
581
+ /**
582
+ * Step over a member this reader does not know.
583
+ *
584
+ * The whole point of the length code, and the reason §7.4.3.4.2 gives
585
+ * one to every mutable member: a reader of an older type has to be
586
+ * able to walk past what it does not have a field for.
587
+ */
588
+ skipMember(header: EmHeaderRead): void;
589
+ /**
590
+ * Start reading a parameter's value, answering with the origin it
591
+ * replaces. The reader's half of the writer's parameter block.
592
+ */
593
+ beginParameterValue(): number;
594
+ /** End a parameter's value and step over its trailing padding. */
595
+ finishParameterValue(savedOrigin: number): void;
596
+ /**
597
+ * `length` octets from `from` as UTF-8, refusing anything that is not.
598
+ *
599
+ * `fatal: true` is the whole of it: without it `TextDecoder` replaces
600
+ * every malformed sequence with U+FFFD and answers a string that is
601
+ * the right length and the wrong text, which is precisely the silent
602
+ * substitution {@link NotUtf8} exists to prevent.
603
+ */
604
+ private decodeUtf8;
605
+ }