@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,662 @@
1
+ /**
2
+ * The write half of XCDR, implemented from DDS-XTypes 1.3 §7.4.
3
+ *
4
+ * The fifth independent runtime beside `crates/wire`, `runtime/c`,
5
+ * `runtime/cpp`, `runtime/java` and `runtime/python`. None of them
6
+ * calls another, and that is the point: a difference between two of
7
+ * them is a finding about the clause, not about a shared bug.
8
+ *
9
+ * What TypeScript decides differently from the others:
10
+ *
11
+ * - a `number` is an IEEE 754 binary64, so every integer narrower than
12
+ * 2^53 is one and everything wider is a `bigint`. The boundary is the
13
+ * type's, not the wire's — `long long` is a `bigint` because a
14
+ * binary64 cannot hold every `i64`, and `long` is a `number` because
15
+ * it can hold every `i32`;
16
+ * - a range check happens at the point of the write. In Rust an `i16`
17
+ * is an `i16` and the compiler has refused the value already; here
18
+ * `70000` is as much a `number` as `7` is, and `& 0xffff` would put
19
+ * `4464` on the wire and report success;
20
+ * - a `long double` never becomes a `number`. Sixteen octets in and
21
+ * sixteen octets out; a binary64 would drop sixty bits of the
22
+ * significand at the assignment.
23
+ */
24
+ import { Endianness } from "./endianness.js";
25
+ import { FixedDigitCount, ParameterRole, WcharFraming, WcharWidth, WstringLengthPolicy, WstringUnitOrder } from "./policy.js";
26
+ /** The parameter id that introduces the extended form. §7.4.1.2.2. */
27
+ export declare const PID_EXTENDED = 16129;
28
+ /** The parameter id that ends a parameter list. §7.4.1.2.4. */
29
+ export declare const PID_LIST_END = 16130;
30
+ /**
31
+ * The highest member id a short parameter header can carry.
32
+ *
33
+ * §7.4.1.2.2 gives the range as 0 to 0x3F00 *inclusive*, and
34
+ * PID_EXTENDED is one above it.
35
+ */
36
+ export declare const PID_SHORT_MAX_ID = 16128;
37
+ /** The implementation-extension flag of a parameter id. */
38
+ export declare const PID_IMPL_EXTENSION = 32768;
39
+ /** The must-understand flag of a parameter id. */
40
+ export declare const PID_MUST_UNDERSTAND = 16384;
41
+ /** How many octets a KeyHash holder has. RTPS 2.5 §9.6.3.3. */
42
+ export declare const KEY_HASH_LEN = 16;
43
+ /**
44
+ * Where a framing may put flags.
45
+ *
46
+ * Wider than `ParameterRole` in `policy.ts`, which is what a
47
+ * *generated codec* names: a sentinel and an extended marker are the
48
+ * framing's own parameters and no member is ever one.
49
+ */
50
+ export type FlagPosition = "member" | "sentinel" | "extended-marker";
51
+ /** Where a framing puts its flags on a parameter id. */
52
+ export interface PidFlags {
53
+ readonly member: number;
54
+ readonly sentinel: number;
55
+ readonly extendedMarker: number;
56
+ }
57
+ /** No flags anywhere, which is Fast DDS's framing. */
58
+ export declare const PID_FLAGS_NONE: PidFlags;
59
+ /** The name `PidFlagPolicy::Bare` gives {@link PID_FLAGS_NONE}. */
60
+ export declare const PID_FLAGS_BARE: PidFlags;
61
+ /**
62
+ * A bare member id, the must-understand bit on the sentinel and on the
63
+ * extended marker. Cyclone DDS and RTI Connext 7.7. The default.
64
+ *
65
+ * Measured, on `struct-mutable` and `annotation-hashid-implicit` under
66
+ * XCDR1: both write `7f02` for the sentinel and `7f01` for the extended
67
+ * marker — the must-understand bit alone. The implementation-extension
68
+ * bit is **not** on either of them, and a runtime that also set it wrote
69
+ * `ff02` and `ff01`, which is what OpenDDS writes for the marker and
70
+ * nobody writes for the sentinel.
71
+ */
72
+ export declare const PID_FLAGS_SENTINEL_MUST_UNDERSTAND: PidFlags;
73
+ /**
74
+ * Both flags on every member id whatever the member declared, a bare
75
+ * sentinel, and both on the extended marker. OpenDDS.
76
+ *
77
+ * `annotation-hashid-implicit` is `ff010008 0343172c 00000004`: both
78
+ * flags on the marker, and a **bare** `eMemberHeader` behind it for a
79
+ * member that declares nothing.
80
+ */
81
+ export declare const PID_FLAGS_IMPL_EXTENSION_ON_MEMBERS: PidFlags;
82
+ /** The flags a framing puts on a parameter in `role`. */
83
+ export declare function pidFlagsAt(flags: PidFlags, role: FlagPosition): number;
84
+ /**
85
+ * The parts of PL_CDR1 framing a plan cannot answer.
86
+ *
87
+ * Every field is a measured divergence between implementations, not a
88
+ * reading of the clause: §7.4.1.2 leaves the padding of a declared
89
+ * length open, and the flags a vendor puts on every id are its own.
90
+ */
91
+ export interface PlCdr1Framing {
92
+ /** Which flags ride on every parameter id, by role. */
93
+ readonly pidFlags: PidFlags;
94
+ /**
95
+ * The highest id written in the short form. `writePid` refuses an id
96
+ * above it: §7.4.1.2.2 reserves the range above for the protocol's
97
+ * own parameters.
98
+ */
99
+ readonly shortMaxId: number;
100
+ /** Whether a declared length covers the value's trailing padding. */
101
+ readonly padsDeclaredLength: boolean;
102
+ /** The same, for an `@optional` member outside a `@mutable` type. */
103
+ readonly padsOptionalLength: boolean;
104
+ /** Whether a member's own must-understand reaches its id. */
105
+ readonly memberMustUnderstand: boolean;
106
+ /**
107
+ * Whether the parameter that just ended writes its own trailing
108
+ * padding to the next four-byte boundary. Every header writer aligns
109
+ * itself, so the two readings only part at the end of the stream:
110
+ * RTI pads after a final `@optional` parameter, Fast DDS does not.
111
+ */
112
+ readonly padAfterValue: boolean;
113
+ }
114
+ /** The framing every field of which is the specification's reading. */
115
+ export declare const PL_CDR1_DEFAULT: PlCdr1Framing;
116
+ /**
117
+ * What `writeDheader` hands back, to be given to `finishDheader`.
118
+ *
119
+ * A `@final` aggregate has none, and the walk still declares one and
120
+ * finishes it — so the absence is a value of this type rather than
121
+ * `undefined`. `at` below zero is that absence; `finishDheader`
122
+ * ignores it. The alternative is `DHeader | undefined` in every
123
+ * generated signature and a null check at every finish, for a case the
124
+ * layout plan already decided.
125
+ */
126
+ export interface DHeader {
127
+ readonly at: number;
128
+ }
129
+ /** The DHEADER a `@final` aggregate does not write. */
130
+ export declare function noDheader(): DHeader;
131
+ /** What `writeEmheader` hands back. */
132
+ export interface EmHeader {
133
+ /** Where the NEXTINT is, or `undefined` where the code carries it. */
134
+ readonly nextInt: number | undefined;
135
+ /** Where the header word is, so a short code can rewrite it. */
136
+ readonly word: number;
137
+ /**
138
+ * The code the header was written with, so that `finishEmheader` can
139
+ * hold the member's value to the length the code declares. Codes 0 to
140
+ * 3 are lengths; anything else declares nothing of its own.
141
+ */
142
+ readonly lengthCode: number;
143
+ }
144
+ /** What `writePid` and `writePidExtended` hand back. */
145
+ export interface Pid {
146
+ readonly at: number;
147
+ readonly extended: boolean;
148
+ readonly savedOrigin: number;
149
+ /**
150
+ * What the parameter frames.
151
+ *
152
+ * A {@link ParameterRole} and not a {@link FlagPosition}: whether the
153
+ * declared length covers the value's trailing padding is answered
154
+ * differently for an `@optional` member outside a `@mutable` type than
155
+ * for a member of one, and {@link Writer.finishPid} needs the answer
156
+ * after the value has been written. A header that carried the flag
157
+ * position instead had no way to reach `padsOptionalLength` at all,
158
+ * so every `@optional` under XCDR1 took the member's padding rule.
159
+ */
160
+ readonly role: ParameterRole;
161
+ readonly pid: number;
162
+ readonly mustUnderstand: boolean;
163
+ }
164
+ /**
165
+ * An IDL `long double`, as the sixteen octets it is.
166
+ *
167
+ * Declared here beside {@link Writer.writeF128} and `Reader.readF128`,
168
+ * the two operations that traffic in it, rather than in `float128.ts`
169
+ * with the decimal converter. The converter answers a `Uint8Array` and
170
+ * needs no name for the wrapper; a reader that had to import the
171
+ * wrapper from a third module would be one more edge for no gain.
172
+ */
173
+ export interface Float128 {
174
+ /** The sixteen octets, in the order the wire carries them. */
175
+ readonly octets: Uint8Array;
176
+ }
177
+ export declare class Writer {
178
+ readonly order: Endianness;
179
+ readonly plCdr1: PlCdr1Framing;
180
+ shortLengthCodes: boolean;
181
+ private out;
182
+ private origin;
183
+ private readonly maxAlignment;
184
+ /**
185
+ * A writer in `order` whose alignment is capped at `maxAlign`.
186
+ *
187
+ * Four for XCDR2, eight for XCDR1. §7.4.1: `ALIGN(N)` aligns to
188
+ * `MIN(N, XCDR.maxalign)`. A writer that did not know this padded an
189
+ * eight-octet primitive to eight under XCDR2 and put four octets on
190
+ * the wire that no peer expects.
191
+ */
192
+ constructor(order: Endianness, maxAlign?: number, plCdr1?: PlCdr1Framing, shortLengthCodes?: boolean);
193
+ /** The alignment cap in force. */
194
+ get maxAlign(): number;
195
+ /** How many octets have been written. */
196
+ position(): number;
197
+ /** The octets written so far. */
198
+ finish(): Uint8Array;
199
+ /** Pad to `align`, counted from the stream's origin. */
200
+ alignTo(align: number): void;
201
+ /**
202
+ * Move the alignment origin to the current position.
203
+ *
204
+ * `ElementPadding::Packed` is HDDS's measured departure from XTypes 1.3
205
+ * §7.4.1, which counts every element's alignment from the encapsulation:
206
+ * each collection element and each aggregate value counts its own
207
+ * alignment from its own first octet instead. `array-1d-struct-final` is
208
+ * `01000000 0200 03000000 0400 77`, the second `Cell`'s `long` at offset
209
+ * six where the clause puts it at eight, and `typedef-of-struct` is the
210
+ * same inside two `@final` members.
211
+ *
212
+ * Returns the origin displaced, for {@link finishPackedElement}.
213
+ */
214
+ beginPackedElement(): number;
215
+ /** Restore the origin {@link beginPackedElement} displaced. */
216
+ finishPackedElement(saved: number): void;
217
+ private refuse;
218
+ private check;
219
+ private checkBig;
220
+ private raw;
221
+ /** An integer of `width` octets, in the stream's order. */
222
+ private writeInt;
223
+ /**
224
+ * An integer of `width` octets in a named order, with no alignment.
225
+ *
226
+ * The order is an argument because two forms fix it against the
227
+ * stream: CORBA's length-prefixed `wchar` and the `wstring` unit
228
+ * orders. Everything else goes through {@link writeInt}.
229
+ */
230
+ private rawInt;
231
+ /** `boolean`, one octet, 0 or 1. */
232
+ writeBool(value: boolean): void;
233
+ /** `octet` and `uint8`. */
234
+ writeU8(value: number): void;
235
+ /** `int8`. */
236
+ writeI8(value: number): void;
237
+ /**
238
+ * `char`, one octet.
239
+ *
240
+ * A code point above 255 is refused rather than truncated: a `char`
241
+ * field holding `ä` from a UTF-8 source is a mistake worth stopping
242
+ * on, and `0xe4` is a different character.
243
+ */
244
+ writeChar(value: string): void;
245
+ /**
246
+ * `wchar`, at `width` octets and in the shape `framing` gives it.
247
+ *
248
+ * Two octets under Table 31 and for seven of the nine measured
249
+ * implementations; four under RTI's XCDR1, under TAO and under
250
+ * `rosidl_typesupport_fastrtps_c`. The width is an argument of its
251
+ * own and not a reading of the `wstring` policy, because
252
+ * `rmw_cyclonedds_cpp` writes two here and four inside a `wstring`.
253
+ *
254
+ * The BMP restriction of §7.2.2.2.1.2.5 is a property of the type
255
+ * and not of the width: the four-octet form zero-extends a code
256
+ * unit, it does not carry a code point.
257
+ *
258
+ * `order` reaches only the length-prefixed form: a scalar cannot
259
+ * carry a byte order mark, so anything but the stream's order means
260
+ * CORBA's default, which is big-endian.
261
+ */
262
+ writeWchar(value: string, width?: WcharWidth, framing?: WcharFraming, order?: WstringUnitOrder): void;
263
+ /** `short`. */
264
+ writeI16(value: number): void;
265
+ /** `unsigned short`. */
266
+ writeU16(value: number): void;
267
+ /** `long`. */
268
+ writeI32(value: number): void;
269
+ /** `unsigned long`. */
270
+ writeU32(value: number): void;
271
+ /** `long long`, which is a `bigint` because a binary64 is not one. */
272
+ writeI64(value: bigint): void;
273
+ /** `unsigned long long`. */
274
+ writeU64(value: bigint): void;
275
+ /**
276
+ * The Cyclone union overlay: the low `octets` of `pattern`, written
277
+ * as one unsigned integer of that width in the stream's byte order.
278
+ *
279
+ * A discriminator carrying a label the `union-labels` dialect axis
280
+ * says selects nothing makes the peer fall through to `default:` and
281
+ * serialise its one C union storage *as that arm* — the selected
282
+ * member's octets, reinterpreted. The pattern is the `bigint` whose
283
+ * little-endian bytes are the selected member's little-endian
284
+ * storage octets, zero-extended; the `bitPattern*` functions
285
+ * produce it.
286
+ */
287
+ writeUnionOverlay(pattern: bigint, octets: number): void;
288
+ /**
289
+ * `float`, a binary32.
290
+ *
291
+ * The value is rounded once, here, and not by the caller: a `number`
292
+ * is a binary64 and the narrowing is part of writing the field.
293
+ */
294
+ writeF32(value: number): void;
295
+ /** `double`, a binary64. */
296
+ writeF64(value: number): void;
297
+ /**
298
+ * `long double`, as the sixteen octets it is.
299
+ *
300
+ * The octets arrive in the order the wire carries them for a
301
+ * little-endian stream, which is how `ZdFloat128` holds them, and are
302
+ * reversed for a big-endian one. A `number` never appears: a binary64
303
+ * would drop sixty bits of the significand.
304
+ */
305
+ writeF128(value: Float128): void;
306
+ /**
307
+ * `string`: a four-octet length that **includes** the terminator,
308
+ * then the octets, then a NUL. §7.4.1.1.1.
309
+ */
310
+ writeString(value: string): void;
311
+ /**
312
+ * A bounded `string`: the same bytes {@link writeString} writes. The
313
+ * bound is a promise about the source and not a difference on the
314
+ * wire, so this is the only place it can be enforced — refused rather
315
+ * than cut at a character boundary, which would put a sample on the
316
+ * wire nobody wrote. The bound counts octets, which is what a
317
+ * `string<N>` bound counts for every measured implementation.
318
+ */
319
+ writeStringBounded(value: string, bound: number): void;
320
+ /**
321
+ * A bounded `wstring`, as {@link writeStringBounded} is to
322
+ * {@link writeString}. The bound counts UTF-16 code units, not
323
+ * characters and not octets, whatever `policy` puts on the wire.
324
+ */
325
+ writeWstringBounded(value: string, bound: number, policy: WstringLengthPolicy, order: WstringUnitOrder): void;
326
+ /**
327
+ * The count check every bounded `sequence` makes before a byte of it
328
+ * is written. Table 17 makes `O2.length <= T1.length` the condition
329
+ * for constructing a `sequence<T, N>`, and the wire carries no bound
330
+ * to compare against: a sender whose count already exceeds its own
331
+ * declaration has written a value of a type nobody declared.
332
+ */
333
+ checkSequenceBound(actual: number, bound: number): void;
334
+ /**
335
+ * The count check every bounded `map` makes before a byte of it is
336
+ * written. Its own message and not {@link checkSequenceBound}'s: the
337
+ * unit is an entry and not an element, per XTypes 1.3 §7.4.1.1.4's
338
+ * map-as-a-sequence-of-pairs equivalence.
339
+ */
340
+ checkMapBound(actual: number, bound: number): void;
341
+ /**
342
+ * `wstring`: a four-octet **octet** count, then UTF-16 code units.
343
+ *
344
+ * No BOM and no terminator — §7.4.1.1.2 forbids both outright. The
345
+ * order the units go out in is the stream's, which the encapsulation
346
+ * identifier already announced.
347
+ *
348
+ * The specification cell of {@link writeWstringUtf8}, kept as a
349
+ * method of its own because it is the one every reader of this file
350
+ * looks for.
351
+ */
352
+ writeWstring(value: string): void;
353
+ /**
354
+ * A `wstring` in the form `policy` and `order` name.
355
+ *
356
+ * {@link WstringLengthPolicy.Specification} is a four-octet octet
357
+ * count and then UTF-16 code units. No BOM and no terminator —
358
+ * §7.4.1.1.2 forbids both outright: "The UTF-16 representation … shall
359
+ * not include a Byte Order Mark (BOM). The representation shall also
360
+ * not include any terminating NUL character(s)."
361
+ *
362
+ * The count is of **octets** under that policy and not of characters:
363
+ * §7.4.1.1.2 says "This is twice the number of characters in the
364
+ * string", with the clause's own rationale being that a code point
365
+ * outside the Basic Multilingual Plane takes two units and an octet
366
+ * count still reaches the end. So `"𝄞"` is a length of four.
367
+ *
368
+ * A TypeScript `string` already holds UTF-16 code units, which is the
369
+ * one thing this column gets for free — `charCodeAt` is the unit and
370
+ * `codePointAt` the character, and the two differ exactly where the
371
+ * policies do.
372
+ */
373
+ writeWstringUtf8(value: string, policy: WstringLengthPolicy, order: WstringUnitOrder): void;
374
+ /**
375
+ * A `wstring` whose characters go out as their own UTF-8 octets.
376
+ *
377
+ * `WstringCodeUnits::Utf8` is the measured departure of one product's
378
+ * generated serialiser: XTypes 1.3 Table 31 gives a `wstring`'s code unit
379
+ * as `Char16` and §7.4.1.1.2 makes the length "twice the number of
380
+ * characters", so the clause has no UTF-8 form at all. The declared length
381
+ * is the UTF-8 octet count and only C2 — the terminator — still reaches
382
+ * the wire. `wstring-member` is `04 00 00 00 61 62 63 00` for `"abc"`:
383
+ * three octets, a NUL, and the four declares both.
384
+ */
385
+ writeWstringUtf8Octets(value: string, policy: WstringLengthPolicy): void;
386
+ /**
387
+ * A bounded UTF-8-octet `wstring`. The bound still counts UTF-16 code
388
+ * units, which is what a `wstring<N>` bound means, while the wire carries
389
+ * the UTF-8 octets.
390
+ */
391
+ writeWstringUtf8OctetsBounded(value: string, bound: number, policy: WstringLengthPolicy): void;
392
+ /**
393
+ * Refuses a `wstring<N>` value longer than its bound. The bound counts
394
+ * UTF-16 code units, whatever form the wire carries.
395
+ */
396
+ private checkWstringBound;
397
+ /** One `wstring` code unit, at its width and in its order. */
398
+ private writeWstringUnit;
399
+ /**
400
+ * `fixed<digits, scale>` as packed BCD. [CDR] §9.3.2.8.
401
+ *
402
+ * DDS-XTypes 1.3 does not carry the type at all — §7.2.2 has no
403
+ * fixed-point kind and §7.4.3.5.3 has no rule whose left-hand side
404
+ * matches one — so the form is CORBA's, which is where an IDL `fixed`
405
+ * came from and the only wire definition it has.
406
+ *
407
+ * The value arrives as a `string` because a `number` is a binary64 and
408
+ * `fixed<31, 2>` is exactly the case a binary64 cannot carry. It is
409
+ * not parsed through anything either: a parser that accepted an
410
+ * exponent or normalised a scale would change the digit count, which
411
+ * is the measured axis {@link FixedDigitCount} names.
412
+ *
413
+ * Aligned to one. [CDR] §9.3.2.8 gives a fixed-point value an
414
+ * alignment of one octet, so a `fixed` never pads.
415
+ */
416
+ writeFixed(value: string, digits: number, scale: number, count: FixedDigitCount): void;
417
+ /**
418
+ * The BCD nibbles of `text` under `fixed<digits, scale>`.
419
+ *
420
+ * [CDR] §9.3.2.8: digit nibbles most-significant first, then a sign
421
+ * nibble — `0xc` for positive or zero, `0xd` for negative — with a
422
+ * leading zero nibble prepended when the nibble count is odd so the
423
+ * nibbles pair up.
424
+ *
425
+ * Neither half is padded in the direction that would lose a digit: a
426
+ * value too long for its integer part or its fraction is one this type
427
+ * cannot represent, and is refused.
428
+ *
429
+ * How many digits go out is {@link FixedDigitCount}: the clause gives
430
+ * the packing and says nothing about the count, and the four
431
+ * implementations that write a `fixed` split two and two.
432
+ */
433
+ private fixedNibbles;
434
+ /** A DHEADER: a four-octet length of what follows. §7.4.3.5.3. */
435
+ writeDheader(): DHeader;
436
+ /**
437
+ * Patch a DHEADER with the length of what followed it.
438
+ *
439
+ * A header from {@link noDheader} is not there and is ignored, which
440
+ * is what lets a generated codec write the same two lines for a
441
+ * `@final` aggregate and an `@appendable` one.
442
+ */
443
+ finishDheader(header: DHeader): void;
444
+ /**
445
+ * An XCDR2 EMHEADER: the member id, its length code and the
446
+ * must-understand flag in one 32-bit word. §7.4.3.4.2.
447
+ *
448
+ * The length code is the layout plan's decision and arrives here as
449
+ * a number; this runtime does not choose one.
450
+ *
451
+ * LC0 through LC3 carry the length in the code itself. LC4 is
452
+ * followed by a NEXTINT. LC5 through LC7 also have one, and
453
+ * §7.4.3.4.2 says it "shall be reused also as part of the serialized
454
+ * member", so no placeholder is reserved for them: the member's own
455
+ * leading word lands in that position and *is* the NEXTINT.
456
+ */
457
+ writeEmheader(memberId: number, lengthCode: number, mustUnderstand: boolean): EmHeader;
458
+ /**
459
+ * Patch an EMHEADER's NEXTINT with the length of what followed.
460
+ *
461
+ * Under {@link shortLengthCodes} an LC4 header whose member turned
462
+ * out to be 1, 2, 4 or 8 octets instead loses its NEXTINT and states
463
+ * the length in the code, which is what Fast DDS does.
464
+ */
465
+ finishEmheader(header: EmHeader): void;
466
+ /**
467
+ * Remove an LC4 header's NEXTINT and raise its length code.
468
+ *
469
+ * Every octet of the member's value is unchanged and only its
470
+ * position moves, which is safe for one reason and only under XCDR2:
471
+ * MAXALIGN is four there, so the value began at a four-aligned
472
+ * offset with the NEXTINT in front of it and begins at a four-aligned
473
+ * offset without it.
474
+ */
475
+ private shortenEmheader;
476
+ /**
477
+ * A PL_CDR1 parameter header, short form: `[id:u16][length:u16]`.
478
+ *
479
+ * `mustUnderstand` is bit 14 of the id. §7.4.1.2.2: the flag "shall
480
+ * be set if and only if the must_understand property of the member is
481
+ * set to true".
482
+ */
483
+ writePid(pid: number, role?: ParameterRole, mustUnderstand?: boolean): Pid;
484
+ /**
485
+ * A PL_CDR1 parameter header, extended form.
486
+ *
487
+ * `[PID_EXTENDED][8][id:u32][length:u32]`, required when the id
488
+ * reaches the reserved range or the value is longer than `0xFFFF`.
489
+ * §7.4.1.2.
490
+ */
491
+ writePidExtended(pid: number, role?: ParameterRole, mustUnderstand?: boolean): Pid;
492
+ /**
493
+ * Start a parameter's value, returning the origin it replaces.
494
+ *
495
+ * "Each element, or parameter, within a parameter list data
496
+ * structure is simply a CDR-encapsulated block of data" — §7.4.1.2.
497
+ * A block counts alignment from its own start, so an eight-octet
498
+ * member at the head of one is already aligned and takes no padding
499
+ * inside its own length.
500
+ */
501
+ private beginParameterValue;
502
+ /**
503
+ * Patch a parameter header with its value's length.
504
+ *
505
+ * The declared length covers the value's trailing padding or stops at
506
+ * the value, depending on the framing — and which of the two framing
507
+ * flags answers is the header's own {@link Pid.role}, not an argument
508
+ * the caller has to remember. A generated codec calls
509
+ * `w.finishPid(h)`, exactly as the C and Java columns do; a runtime
510
+ * that took the answer as a defaulted parameter never reached
511
+ * `padsOptionalLength` at all.
512
+ *
513
+ * The padding itself starts the next parameter at a four-octet offset
514
+ * measured from the enclosing stream, so the origin goes back before
515
+ * it is written.
516
+ */
517
+ finishPid(header: Pid): void;
518
+ /**
519
+ * Rewrite a short parameter header as the extended form.
520
+ *
521
+ * §7.4.1.2.2's `ssize` is sixteen bits, and which values overrun it is
522
+ * a property of the sample rather than of the type. So the plan writes
523
+ * the short form for an unbounded member and the fallback lives here,
524
+ * where the length is known. Without it a value over 64 KiB had its
525
+ * length silently truncated to sixteen bits and the payload still
526
+ * looked well-formed — a reader would take the next parameter from
527
+ * inside this one.
528
+ *
529
+ * Eight octets are inserted between the header and the value. The
530
+ * value's own octets do not change: XCDR1's MAXALIGN is eight and the
531
+ * insertion is eight, so every offset inside it keeps its remainder.
532
+ */
533
+ private promotePid;
534
+ /** The `[PID_LIST_END][0]` that ends a parameter list. §7.4.1.2.4. */
535
+ writeSentinel(): void;
536
+ /**
537
+ * An enumerator, as the integer its bit bound calls for.
538
+ *
539
+ * §7.4.3.5.3 rule (5) is
540
+ * `XCDR << {O : ENUM_TYPE} = XCDR << {O.value : O.holder_type}`, and
541
+ * the ENUM_TYPE row of the same clause's table says "O.holder_type is
542
+ * either Int8, Int16 or Int32 depending on the value of the
543
+ * `@bit_bound` annotation". A **signed** holder: `@value(-1)` is the
544
+ * two's complement of one, so at the default bound it goes out as
545
+ * `ffffffff`.
546
+ *
547
+ * What fits is everything expressible in the bound's bits, signed or
548
+ * unsigned — `-2^(n-1) ..= 2^n - 1`. RTI Connext 7.7 accepts
549
+ * `@value(-1)` at the default bound and Cyclone accepts `@value(200)`
550
+ * under `@bit_bound(8)`; a signed-only range would reject the second
551
+ * and a wider one would accept values neither can express.
552
+ *
553
+ * §7.3.1.2.1.5 caps the bound itself at 1 to 32, so a bound outside
554
+ * that has no holder and is refused rather than widened.
555
+ *
556
+ * The bound comes **first**, which is the order the shared walk in
557
+ * `crates/lang-rules/src/emit/encode.rs` calls it in and the order
558
+ * `zdw_write_enum` and Java's `writeEnum` take. When both arguments
559
+ * were a `number` a swapped pair was a legal call that wrote a
560
+ * plausible octet — the Java column found exactly that, at run time.
561
+ *
562
+ * The value is a `bigint` and the bound a `number`, which is the same
563
+ * widened holder `zdw_write_enum`'s `int64_t` and Java's `long` are:
564
+ * the walk casts the enumerator to `Scalar::Int64` before the call, so
565
+ * the two arguments now have different types and a swap does not
566
+ * compile.
567
+ */
568
+ writeEnum(bitBound: number, value: bigint): void;
569
+ /**
570
+ * A bitmask, as the unsigned integer its bit bound calls for.
571
+ *
572
+ * §7.4.3.5.3 rule (6) writes `O.value` as `O.holder_type`, and Table
573
+ * 33 of §7.4.1.1.3.2 gives the holder: `UInt8` for a bound of 1 to 8,
574
+ * `UInt16` to 16, `UInt32` to 32 and `UInt64` to 64. The same clause
575
+ * fixes the direction — "Bit indexes are counted from zero starting at
576
+ * the least-significant bit of the full byte size of the bitmask" — so
577
+ * bit `n` is `1 << n` whatever the holder's width.
578
+ *
579
+ * A bit at or past the bound is refused: the clause says those bits
580
+ * "are not considered to be part of the bitmask", so setting one would
581
+ * put a value on the wire no peer must read back.
582
+ *
583
+ * The value is a `bigint` at every bound and not only at 64, because
584
+ * the caller is a generated codec that casts once. The bound comes
585
+ * first, as it does for {@link writeEnum}.
586
+ */
587
+ writeBitmask(bitBound: number, bits: bigint): void;
588
+ /**
589
+ * One bitfield, shifted into the accumulator a bitset packs into.
590
+ *
591
+ * The counterpart of `zdw_bitfield` and of Java's `Writer.bitfield`.
592
+ * A method of the writer and not a free function, because the shared
593
+ * walk emits it as a call on the writer — `call_expr` in
594
+ * `crates/lang-rules/src/emit/encode.rs` is `T::runtime("w", …)` — and
595
+ * a free function of that name would be a second `bitfield` the
596
+ * generated code never reaches.
597
+ *
598
+ * A value wider than the field is refused rather than masked: masking
599
+ * would put a different number on the wire than the caller asked for,
600
+ * and the caller would never find out.
601
+ */
602
+ bitfield(value: bigint, width: number, position: number): bigint;
603
+ /**
604
+ * A bitset, as the anchor integer its bitfields pack into.
605
+ *
606
+ * DDS-XTypes 1.3 has no serialisation rule for a bitset — §7.4.3.5.3
607
+ * runs from rule (1) to rule (30) and no left-hand side matches one.
608
+ * How wide the anchor is comes from the layout planner and arrives
609
+ * here as a count of **octets**, not of bits: `zerodds_ast_layout`'s
610
+ * `Extent::Sized` is an octet count and the shared walk passes it
611
+ * through. A runtime that read it as a bit count answered "8" for an
612
+ * eight-octet anchor and wrote one octet where the plan said eight.
613
+ */
614
+ writeBitset(anchorOctets: number, bits: bigint): void;
615
+ private patch;
616
+ private read;
617
+ /**
618
+ * The holder as a KeyHash, zero-padded to sixteen octets.
619
+ *
620
+ * For a holder of sixteen octets or fewer. DDSI-RTPS 2.5 §9.6.3.8.
621
+ */
622
+ zeroPadded(): Uint8Array;
623
+ /**
624
+ * The MD5 of the holder, for one longer than sixteen octets.
625
+ *
626
+ * MD5 because DDSI-RTPS 2.5 §9.6.3.8 names it, not as a security claim:
627
+ * the KeyHash identifies an instance and is not a signature.
628
+ */
629
+ md5(): Uint8Array;
630
+ }
631
+ /**
632
+ * The MD5 a KeyHash is made of. RFC 1321.
633
+ *
634
+ * Hand-rolled rather than a call into a platform digest, for the same
635
+ * reason `runtime/csharp`'s `Md5.cs` gives and not `runtime/java`'s: this
636
+ * runtime is isomorphic (Node, a browser, `runtime/typescript`'s own WASM
637
+ * bridge in `wasm.ts`), and the Web Crypto API a browser exposes has no
638
+ * MD5 at all — `SubtleCrypto.digest` supports only the SHA family — so
639
+ * there is no single platform primitive to call from every environment
640
+ * this package runs in, unlike Java's `MessageDigest` or even C#'s
641
+ * FIPS-mode-sensitive one. `WireSelfTest`'s Java and C# counterparts check
642
+ * RFC 1321's own test vectors; `against-recorded-values.ts` does the same
643
+ * here, so the arithmetic is asserted and not assumed.
644
+ *
645
+ * Not a security primitive here and not used as one: the specification
646
+ * names MD5 for this, and a different digest would produce hashes that no
647
+ * other vendor agrees with. DDSI-RTPS 2.5 §9.6.3.8.
648
+ */
649
+ export declare function md5(input: Uint8Array): Uint8Array;
650
+ /**
651
+ * The low `octets` of `value`'s two's-complement bits, zero-extended —
652
+ * {@link Writer.writeUnionOverlay}'s pattern for an integer, character,
653
+ * enumeration or bitmask arm. The mask is the function: `-2` in four
654
+ * octets has to come out `0x00000000fffffffen`.
655
+ */
656
+ export declare function bitPatternInt(value: bigint, octets: number): bigint;
657
+ /** One octet, 0 or 1 — the boolean overlay pattern. */
658
+ export declare function bitPatternBool(value: boolean): bigint;
659
+ /** The IEEE 754 binary32 bits, zero-extended. */
660
+ export declare function bitPatternF32(value: number): bigint;
661
+ /** The IEEE 754 binary64 bits. */
662
+ export declare function bitPatternF64(value: number): bigint;