Skip to main content

Writer

Struct Writer 

Source
pub struct Writer { /* private fields */ }
Expand description

Accumulates the bytes of one sample.

Implementations§

Source§

impl Writer

Source

pub fn new(endianness: Endianness) -> Self

A writer in the given byte order.

Source

pub fn recording_padding(self) -> Self

The same writer, keeping a record of every span of alignment padding it emits.

The record is the answer §7.4.1’s alignment rules give for this type under this key: Writer::align_to is the one place the walk emits a byte that carries no value, so the spans it notes are the fill positions of the plan and not an observation about the octets that came out. Two byte-shifting rewrites happen after the fact — Writer::promote_pid inserts eight octets and shorten_emheader removes four — and both move the spans above them, so the record stays in the finished stream’s coordinates.

Off by default and allocating only when asked for.

Source

pub fn padding_spans(&self) -> &[(usize, usize)]

The recorded padding spans as (offset, length), in the finished stream’s coordinates and in ascending order.

Empty when Writer::recording_padding was not asked for, which is indistinguishable from a stream with no padding. A caller that needs to tell the two apart asks for the record.

Source

pub const fn is_recording_padding(&self) -> bool

Whether this writer is keeping the record.

Source

pub const fn with_wchar_framing(self, framing: WcharFraming) -> Self

The same writer framing a scalar Char16 another way.

A preset and not a patch, like every other with_* here: the framing and the width are separate because CORBA makes them separate — omniORB and TAO write the same framing over two octets and four.

Source

pub const fn wchar_framing(&self) -> WcharFraming

The Char16 framing in force.

Source

pub const fn with_wstring_unit_order(self, order: WstringUnitOrder) -> Self

The same writer ordering wide code units another way.

Source

pub const fn wstring_unit_order(&self) -> WstringUnitOrder

The wide code-unit order in force.

Source

pub const fn with_wchar_width(self, width: WcharWidth) -> Self

The same writer putting a Char16 on the wire at another width.

Set it from zerodds_ast_layout::WstringLengthPolicy::character_width, which is the same source the layout plan sized the member from. A writer wider than its plan writes a member the plan did not reserve room for and every offset after it is wrong.

Source

pub const fn wchar_width(&self) -> WcharWidth

The Char16 width in force.

Source

pub const fn with_short_length_codes(self, shorten: bool) -> Self

The same writer shortening an LC4 header whose member turned out to be 1, 2, 4 or 8 bytes long.

Set it from zerodds_ast_layout::LengthCodePolicy::short_code_where_it_fits. The plan already picks a short code for every member whose type fixes the size; this is the other half, for a sequence or a map whose length is in the value. Fast DDS makes the same choice the same way — its sequence<short> of two elements is eight bytes and goes out as 02000030, where three elements would be ten and go out as LC4.

Source

pub const fn short_length_codes(&self) -> bool

Whether an LC4 header is shortened when its member fits a code.

Source

pub const fn with_pl_cdr1_framing(self, framing: PlCdr1Framing) -> Self

The same writer framing a PL_CDR1 parameter list another way.

Source

pub const fn pl_cdr1_framing(&self) -> PlCdr1Framing

The framing in force.

Source

pub const fn with_minimal_member_trailing_octet(self, on: bool) -> Self

The writer, set to append (or not) the RTI/CoreDX minimal-member trailing octet. See Writer::minimal_member_trailing_octet.

Source

pub const fn minimal_member_trailing_octet(&self) -> bool

Whether this writer appends the RTI/CoreDX minimal-member trailing octet (XTypes 1.3 §7.3.4.5; docs/omg-xtypes-issues.md §C2).

Source

pub fn with_max_align(endianness: Endianness, max_align: usize) -> Self

A writer whose alignment is capped at max_align.

Four for XCDR2, eight for XCDR1 — take it from zerodds_ast_layout::Encoding::max_alignment rather than writing a number here.

Source

pub fn appending(endianness: Endianness, max_align: usize, out: Vec<u8>) -> Self

A writer that appends to out, with its alignment cap at max_align and alignment counted from where out ends.

For an encoder handed a buffer to fill: a writer of its own grows from empty and its bytes are then copied over, and for a 1 kB sample that was four reallocations and a copy per write (measured on the Linux test host). Counting from out’s end makes the bytes the same as a fresh writer’s whose bytes were appended to out. Self::finish hands out back with the sample behind what it held.

Source

pub fn continuing( endianness: Endianness, max_align: usize, prefix: Vec<u8>, ) -> Self

A writer that continues a stream whose first octets are prefix: it appends behind them and counts alignment from the start of prefix, not from where prefix ends (which is what Self::appending does).

For a value that is a member of a larger object whose earlier members were written by someone else — DDS-RPC 1.0 §7.5.1.1.6 puts the Call union behind a RequestHeader of variable length, and under XCDR1 the union’s 8-octet members align to the sample, not to the union. Self::finish hands back prefix with the value behind it.

Source

pub const fn max_align(&self) -> usize

The alignment cap in force.

Source

pub const fn endianness(&self) -> Endianness

The byte order this writer was given.

The counterpart of crate::reader::Reader::endianness, for the callers that have to put the order they are writing in into the stream — a CDR encapsulation opens with a byte-order octet that says which order its body is in.

Source

pub fn big_endian() -> Self

A big-endian writer, which is what a KeyHash holder is.

Source

pub fn little_endian() -> Self

A little-endian writer.

Source

pub fn as_bytes(&self) -> &[u8] ⓘ

The bytes written so far.

Source

pub fn finish(self) -> Vec<u8> ⓘ

The bytes, with the writer consumed.

Source

pub fn position(&self) -> usize

How many bytes have been written.

Source

pub fn align_to(&mut self, align: usize)

Pad to align, counted from the stream’s origin.

Source

pub fn begin_packed_element(&mut self) -> usize

Begin a collection element whose alignment is counted from its own first octet, returning the origin it replaced.

XTypes 1.3 §7.4.1 counts a value’s alignment from the encapsulation, so an element of an array or a sequence begins at the next multiple of its alignment and the collection pads between elements. zerodds_ast_layout::ElementPadding::Packed is the measured departure: the element begins where the previous one ended and its own members align from there. Resetting the origin here is the whole of it; Self::finish_packed_element puts the stream’s origin back so the collection’s tail aligns from the encapsulation again.

Source

pub fn finish_packed_element(&mut self, saved: usize)

Restore the stream origin a packed element displaced. The pair of Self::begin_packed_element.

Source

pub fn write_bool(&mut self, value: bool)

boolean, one byte, 0 or 1.

Source

pub fn write_u8(&mut self, value: u8)

octet and uint8.

Source

pub fn write_fixed( &mut self, text: &str, digits: u8, scale: u8, policy: FixedDigits, ) -> Result<(), WireError>

fixed<digits, scale>, as BCD — CORBA 3.3 part 2 §9.3.2.8.

The value arrives as a decimal string and not as a number, because a fixed<31, 2> is exactly what a f64 cannot carry: the type exists to hold a decimal exactly, and a binary float on the way in would defeat it before the first nibble.

Two nibbles to the byte, high first, sign last: 0xd negative, 0xc otherwise, zero included. A negative zero goes out positive, because there is one zero to write.

No DDS vendor generates code for fixed — Cyclone, Fast DDS and RTI emit nothing for it and OpenDDS does not compile it, measured across the corpus — so there is no vendor oracle here, only the clause and the twenty other columns of this project that already write it.

§Errors

WireError when the declaration is outside IDL rule (42)’s 31 digits, when scale exceeds digits, or when the text is not a decimal that fits fixed<digits, scale>. A value that does not fit is refused rather than truncated: a silently shortened decimal is the wrong number with no way to notice.

Source

pub fn write_i8(&mut self, value: i8)

int8.

Source

pub fn write_char(&mut self, value: char) -> Result<(), WireError>

char, one byte. DDS-XTypes 1.3 §7.4.1.1.1, Table 31.

§7.2.2.2.1.2.2 gives the whole rule: “This specification does not define an encoding for the CHAR_8_TYPE. The only constraint is that it shall be representable using 8 bits.” A code point above U+00FF is not, and no byte stands for it.

§Errors

WireError::OutOfRange above U+00FF. This used to be value as u32 as u8, which drops the high bits and puts a different character on the wire with nothing said.

Source

pub fn write_wchar( &mut self, value: char, position: WcharPosition, ) -> Result<(), WireError>

wchar: one UTF-16 code unit, at the width Writer::wchar_width names. DDS-XTypes 1.3 §7.4.1.1.1, Table 31 gives two bytes; WcharWidth carries the one measured implementation that writes four and where it does so.

§7.2.2.2.1.2.5: “The CHAR_16_TYPE shall be restricted to representing Unicode codepoints in the Basic Multilingual Plane. That is Unicode codepoints from 0x0000 to U+FFFF.” A code point above the BMP takes two UTF-16 code units and has no wchar. That is a property of the type and not of the width, so the four-byte form refuses it too: RTI zero-extends a code unit, it does not carry a code point.

position says whether this wchar is a member or a collection element. Under WcharFraming::GiopLengthPrefixedMemberOnly the two take different octets, and there is no default: a caller that could leave it out would take the member’s framing for an element, which is the shape of the defect that put the argument here. tao_idl writes 04 e4000000 for a wchar member of primitive-wchar and a bare e4000000 for the first element of array-1d-primitives.

§Errors

WireError::OutOfRange above U+FFFF, for the reason Writer::write_char gives at its own width.

Source

pub fn write_wchar_member(&mut self, value: char) -> Result<(), WireError>

Writer::write_wchar at the member position.

The generated codecs call this and Writer::write_wchar_element rather than passing a position along: a collection combinator takes Fn(&mut Writer, &char), and a two-argument method cannot be handed to one as a path without a closure that would hide which position it chose.

§Errors

As Writer::write_wchar.

Source

pub fn write_wchar_element(&mut self, value: &char) -> Result<(), WireError>

Writer::write_wchar at the collection-element position.

§Errors

As Writer::write_wchar.

Source

pub fn write_i16(&mut self, value: i16)

short.

Source

pub fn write_bitmask( &mut self, bit_bound: u16, bits: u64, ) -> Result<(), WireError>

A bitmask, in the holder Table 33 of XTypes 1.3 §7.4.1.1.3.2 gives for its @bit_bound.

The bound and not the language’s holder: @bit_bound(12) is a uint16_t in C and a u16 here, and the two octets it writes carry twelve bits that mean something and four that do not. The argument arrives from zerodds_ast_layout::plan::scalar_write, which is the same crossing every other column asks — the C runtime’s zdw_write_bitmask takes the same pair in the same order.

§Refused, not masked

A value with a bit set above the bound is refused rather than truncated to the bound. Masking would put a value on the wire nobody wrote and report success, and the peer would read a set the sender never held. runtime/c/src/writer.c refuses the same value with ZDW_RANGE.

§Errors

WireError::OutOfRange for a bound of zero or above 64, and for a value that does not fit the bound.

Source

pub fn write_bitset( &mut self, anchor_bytes: u32, bits: u64, ) -> Result<(), WireError>

A bitset, as the anchor integer its bitfields pack into.

The anchor width is the layout plan’s answer and arrives as a byte count, which is what zerodds_ast_layout::xcdr::plan gives as the type’s extent and what zdw_write_bitset takes.

XTypes 1.3 has no serialisation rule for a bitset — §7.4.3.5.3 runs from (1) to (30) and none matches one. What is implemented is the only reading under which an IDL bitset round-trips through the TypeObject of §7.3.4.6: positions run cumulatively from zero in declaration order, anonymous padding included. The C runtime carries the same paragraph.

§Errors

WireError::OutOfRange for an anchor that is not one, two, four or eight octets.

Source

pub fn bitfield( &mut self, value: u64, width: u32, position: u32, ) -> Result<u64, WireError>

One bitfield’s contribution to its bitset’s anchor: the value shifted to its position.

A value wider than the field is refused rather than masked. Masking would put a different value on the wire than the caller held and report success — the generated field is as wide as its holder and not as wide as its bitfield<N>, so bitfield<3> a is a u8 that can hold 200 and a bitset that can not. zdw_bitfield refuses the same value with ZDW_RANGE.

§Errors

WireError::OutOfRange for a width outside 1..=64, a field that runs past the sixty-fourth bit, or a value the width cannot hold.

Source

pub fn write_u16(&mut self, value: u16)

unsigned short.

Source

pub fn write_u16_little(&mut self, value: u16)

A 16-bit value in little-endian order whatever the stream’s order is, aligned to two like any other.

One caller and one reason: Cyclone DDS swaps a wstring’s length word for a big-endian stream and does not swap its code units. zerodds_ast_layout::WstringLengthPolicy::UnswappedUnits carries the measurement and the argument for reproducing it on request. Nothing else on the wire has this shape, and a member that used it without that reason would be a member no peer reads.

Source

pub fn write_u16_big(&mut self, value: u16)

A 16-bit value in big-endian order whatever the stream’s order is, aligned to two like any other.

The counterpart of Writer::write_u16_little on the other side of the same axis. Both omniORB and JacORB decode a wstring’s code units as UTF-16 big-endian whatever the stream says — the OMG code-set rule for a GIOP 1.2 wstring that carries no byte-order mark — so this is the form a wstring written for an ORB takes in a little-endian stream.

Source

pub fn write_u32_little(&mut self, value: u32)

A 32-bit value in little-endian order whatever the stream’s order is.

A four-octet transmission code set crossed with a fixed unit order: reachable as --wstring-length specification-wide-units --wstring-units byte-order-mark and by no dialect, because no measured implementation writes wide units in a fixed order. It exists so that two orthogonal settings have an answer for every combination rather than a hole one of them falls into.

Source

pub fn write_u32_big(&mut self, value: u32)

A 32-bit value in big-endian order whatever the stream’s order is. The counterpart of Writer::write_u32_little.

Source

pub fn write_i32(&mut self, value: i32)

long.

Source

pub fn write_u32(&mut self, value: u32)

unsigned long.

Source

pub fn write_i64(&mut self, value: i64)

long long.

Source

pub fn write_u64(&mut self, value: u64)

unsigned long long.

Source

pub fn write_f32(&mut self, value: f32)

float.

Source

pub fn write_f64(&mut self, value: f64)

double.

Source

pub fn write_f128(&mut self, value: Float128)

long double: sixteen bytes of IEEE 754 binary128.

CORBA 3.3 part 2 §9.3.1.3 with Figure 9.2 gives the layout — one sign bit, a fifteen-bit exponent, a 112-bit fraction — and shows the two byte orders as the whole sixteen bytes reversed, not two eight-byte halves swapped in place. DDS-XTypes 1.3 Table 31 gives the alignment: eight, capped to four by MAXALIGN under XCDR2, which is what Writer::align_to already does.

This used to take an f64 and write it followed by eight zero bytes, because Rust has no stable f128. That was the right length and the wrong value in every column and it reported success; zerodds_float128::Float128 carries the value instead. Nothing here computes with it — a wire runtime never needs to.

Source

pub fn write_string(&mut self, value: &str)

A string: a four-byte length including the terminator, the bytes, then a NUL. DDS-XTypes 1.3 §7.4.1.1.

The length counts the terminator, which is the one place XCDR differs from every other length-prefixed encoding.

Source

pub fn write_string_bounded( &mut self, value: &str, bound: usize, ) -> Result<(), WireError>

A bounded string.

The same bytes as an unbounded one: the bound is a promise about the source, not a difference on the wire. It is checked here rather than trusted, because a value that overruns its bound is one no peer expected.

The bound counts octets, which is what string<N> means to every peer that has to hold the value — char[N + 1] in the C mapping of all four DDS implementations, fixed_string<N> in Fast DDS’s.

§Refused, not truncated

This truncated at a character boundary and reported nothing, which is AL-14 of docs/wire-feature-inventory.md: acceptable only while nothing called it. Something does now — the generated codec emits write_string_bounded for every bounded string member — and a writer that truncated would put a value on the wire nobody wrote. §7.2.2.7’s TRIM is a read-side behaviour and belongs to the receiver’s bound, not the sender’s; wire-probe/src/encode.rs::write_string refuses the same values (D6), so the two columns now agree.

§Errors

WireError::OutOfRange for a value longer than the bound.

Source

pub fn write_wstring( &mut self, value: &str, policy: WstringLengthPolicy, order: WstringUnitOrder, position: WirePosition, ) -> Result<(), WireError>

A wstring: a four-octet length, then UTF-16 code units, in the cell policy and order name.

XTypes 1.3 §7.4.3.5.3 rule (4) writes O.ssize as a UInt32 and then the Char16 units, annotated “No NUL” against rule (3)’s “includes NUL” for a narrow string. What O.ssize counts is settled in §7.4.1.1.2: “The serialized length of an object of type String<Char16> shall be the number of bytes in the CDR buffer taken by the String<Char16> characters. This is twice the number of characters in the string” — code units, not characters, so a "𝄞" is a length of four and not of one or two. The same clause forbids the two things a UTF-16 encoder would otherwise emit: “The UTF-16 representation … shall not include a Byte Order Mark (BOM). The representation shall also not include any terminating NUL character(s).”

That is one cell of eight. WstringLengthPolicy carries the other seven and the runs that measured five of them, and WstringUnitOrder carries the fourth axis. Both arrive as arguments, resolved from zerodds_ast_layout::LayoutKey, for the reason MapDelimiter arrives as the choice between Writer::write_map and Writer::write_delimited_map: a default in the runtime would be a second place the wire format lives, and the two places would disagree the first time either moved.

position says whether this wstring is reached as a member or as a collection element. The nine measured implementations answer both alike, so it changes nothing today — and it is the argument that keeps that a measurement rather than an assumption, the way Writer::write_wchar’s position is the argument that caught tao_idl writing two different framings.

§Errors

WireError::OutOfRange for a code point outside the Basic Multilingual Plane under a character count over two-octet units — the WstringLengthPolicy::CHARACTER_COUNT cell. Fast CDR counts wcslen characters and then writes each four-octet wchar_t as two octets, so U+1D11E leaves as d11e, which is U+D11E, a Hangul syllable and a well-formed code point. The peer reads a different character and has nothing to object to, and the sender left no trace in the bytes. Reproducing a vendor’s length convention is a policy; reproducing a data loss no reader can see is not.

The refusal is on the pair (characters, two octets) and not on a named form: it is the narrow unit that loses the high bits, so WstringLengthPolicy::ROS_TYPE_SUPPORT — a character count over four-octet units — carries the surrogate pair intact and is not refused.

Source

pub fn write_wstring_bounded( &mut self, value: &str, bound: usize, policy: WstringLengthPolicy, order: WstringUnitOrder, position: WirePosition, ) -> Result<(), WireError>

A bounded wstring.

The same octets as an unbounded one of the same length: the bound is a promise about the source, not a difference on the wire.

The bound counts UTF-16 code units, which is what wstring<N> means to every peer that has to hold the value — an N-unit buffer in all four DDS implementations’ mappings, and what §7.4.1.1.2’s own count is in. Counting Unicode scalar values instead would accept a five-character value of six code units that no peer can hold; counting octets would make the same declaration mean two different capacities under C3’s two widths.

The terminator WstringTerminator::Present adds is not counted against the bound. wstring<5> names a capacity of five characters and RTI’s XCDR1 form writes six units for five characters; counting the terminator would refuse a value the declaration admits.

§Errors

WireError::OutOfRange for a value longer than the bound, refused and not truncated for the reason Writer::write_string_bounded gives — §7.2.2.7’s TRIM is a read-side behaviour and belongs to the receiver’s bound. And whatever Writer::write_wstring refuses.

Source

pub fn write_wstring_utf8( &mut self, value: &str, policy: WstringLengthPolicy, position: WirePosition, ) -> Result<(), WireError>

A wstring whose characters go out as their own UTF-8 octets.

The write side of WstringCodeUnits::Utf8, the measured departure of one product’s generated serialiser: XTypes 1.3 Table 31 gives a wstring’s code unit as Char16 and §7.4.1.1.2 makes the length “twice the number of characters”, so the clause has no UTF-8 form at all. The length is the UTF-8 octet count plus C2’s terminator when the cell carries one: under this value C1 and C3 have nothing to say, because there is no fixed-width code unit for a character count to count and no width for an octet count to multiply by.

The order axis is not consulted: UTF-8 octets have no byte order of their own.

§Errors

WireError::OutOfRange for an octet count that does not fit the UInt32 length field, refused rather than written wrapped — a length that names a prefix of its own content is the silent class, and the peer would read every following member from inside this one.

Source

pub fn write_wstring_utf8_bounded( &mut self, value: &str, bound: usize, policy: WstringLengthPolicy, position: WirePosition, ) -> Result<(), WireError>

A bounded wstring whose characters go out as UTF-8 octets.

The same octets as the unbounded one of the same length; the bound is a promise about the source and counts UTF-16 code units, as Writer::write_wstring_bounded does, because that is what wstring<N> means to a peer whatever the content’s encoding.

§Errors

WireError::OutOfRange for a value longer than the bound, and whatever Writer::write_wstring_utf8 refuses.

Source

pub fn write_dheader(&mut self) -> DHeader

A DHEADER: a four-byte length the members that follow occupy.

Written as a placeholder and patched when the members are done, because the length is not known until then.

Source

pub fn finish_dheader(&mut self, header: DHeader)

Patch a DHEADER with the length of what followed it.

A DHEADER is a UInt32 and “O.ssize is constrained to being smaller than 4 Giga Bytes” (XTypes 1.3 §7.4.3.4.1): an object past that has no DHEADER. This form has no way to return the error, so it records it: the placeholder stays unpatched, Self::deferred_error returns the error and Self::finish_checked and Self::check_deferred refuse the stream. A caller that can return an error uses Self::try_finish_dheader and gets it at the call.

Source

pub fn deferred_error(&self) -> Option<&WireError>

The first error an infallible framing call met, if one did.

Set by Self::finish_dheader for an object of 4 GiB or more.

Source

pub fn check_deferred(&self) -> Result<(), WireError>

Self::deferred_error as a result.

§Errors

The first error an infallible framing call met.

Source

pub fn finish_checked(self) -> Result<Vec<u8>, WireError>

The bytes, refused when an infallible framing call met an error.

§Errors

Self::deferred_error’s error.

Source

pub fn try_finish_dheader(&mut self, header: DHeader) -> Result<(), WireError>

Self::finish_dheader, refusing a length a UInt32 does not hold.

§Errors

WireError::OutOfRange when the members that followed the DHEADER occupy 4 GiB or more (XTypes 1.3 §7.4.3.4.1). The buffer is left as it was, with the placeholder unpatched, for the caller to discard.

Source

pub fn write_emheader( &mut self, member_id: u32, length_code: u8, must_understand: bool, ) -> Result<EmHeader, WireError>

An XCDR2 EMHEADER: the member id, its length code and the must-understand flag in one 32-bit word.

The length code is the layout plan’s decision and arrives here as a number; this crate does not choose one. XTypes 1.3 §7.4.3.4.2.

§Errors

WireError::OutOfRange for a member id above E_MEMBER_ID_MASK. §7.2.2.4.4.4.4 runs the ids from 0 to 0x0FFFFFFF and §7.4.3.4.2 leaves them the low 28 bits of the word. This used to be member_id & 0x0FFF_FFFF, which writes a well-formed header for a member the caller did not name — the peer reads the wrong member and nothing at either end says so.

Source

pub fn finish_emheader(&mut self, header: EmHeader) -> Result<(), WireError>

Patch an EMHEADER’s NEXTINT with the length of what followed.

Under Writer::short_length_codes it may instead delete the NEXTINT and put the length in the code, which is what Fast DDS does for a member whose serialized size turns out to be 1, 2, 4 or 8 bytes. See Writer::with_short_length_codes.

§Errors

WireError::OutOfRange when the member written under a code of 0 to 3 is not the length that code declares. §7.4.3.4.2 makes the code be the length there — 1, 2, 4 or 8 octets — so a value of another size misdeclares it and the reader’s skip lands inside data. Codes 4 to 7 carry a NEXTINT and declare nothing of their own, so they cannot be wrong that way.

Source

pub fn write_pid( &mut self, pid: u16, role: ParameterRole, must_understand: bool, ) -> Result<Pid, WireError>

A PL_CDR1 parameter header, short form: [id:u16][length:u16].

role says what the length field will count when Writer::finish_pid patches it; see ParameterRole.

must_understand is bit 14 of the id. §7.4.1.2.2: the flag “shall be set if and only if the must_understand property of the member is set to true”. A member declared @must_understand whose header does not say so goes out looking skippable, and a peer that does not know it skips it.

§Errors

WireError::OutOfRange for an id above PlCdr1Framing::highest_short_id. §7.4.1.2.2 gives the short form the ids 0 to that value inclusive and reserves what is above it for the protocol’s own parameters — PID_EXTENDED is 0x3F01 itself — so such an id takes Writer::write_pid_extended or it does not go out. The field was read only by the reader until this check; the plan chooses the form and this is the floor under a caller that did not.

Source

pub fn write_pid_extended( &mut self, pid: u32, role: ParameterRole, must_understand: bool, ) -> Result<Pid, WireError>

A PL_CDR1 parameter header, extended form.

[PID_EXTENDED][8][id:u32][length:u32], required when the id reaches the reserved range or the value is longer than 0xFFFF, and used for every member under zerodds_ast_layout::PlCdr1HeaderPolicy::AlwaysExtended. XTypes 1.3 §7.4.1.2.

The marker carries the must-understand bit when the framing says so — Cyclone DDS writes 0x7f01, and its reader would not be misled by 0x3f01 either, but the bytes differ.

The member’s must-understand is a different bit in a different word: FLAG_2 of the 32-bit eMemberHeader, §7.4.1.2.1. Cyclone sets the marker’s bit on every parameter it writes and FLAG_2 only on the members that declare it — 017f0800 01000040 against 017f0800 02000000 in the same sample — so reading the member’s property off the marker would make every Cyclone parameter must-understand.

§Errors

WireError::OutOfRange for a member id above E_MEMBER_ID_MASK, for the reason Writer::write_emheader gives: the eMemberHeader of §7.4.1.2.1 has the same 28 bits, and masking aliases the parameter onto another member.

Source

pub fn finish_pid(&mut self, header: Pid)

Patch a parameter header with its value’s length.

The length field never counts the alignment padding inside the block: a parameter’s value is its own CDR-encapsulated block and counts alignment from its own start, XTypes 1.3 §7.4.1.2, which is why an eight-byte member at the head of one declares eight and not twelve. All three measured implementations agree on that.

Whether it counts the padding that follows the value is PlCdr1Framing::pads_declared_length, asked per ParameterRole: Cyclone and RTI round a @mutable member’s declared length up to four and Fast DDS stops at the value, and for an @optional member of a non-mutable type only RTI rounds.

An absent @optional member finishes here with nothing written between the header and this call, which declares the length of zero §7.4.1.2 asks for.

Source

pub fn write_sentinel(&mut self)

The PID_LIST_END sentinel a PL_CDR1 parameter list ends with.

A reader that stops at the last member it recognises instead of at the sentinel misreads whatever follows. The flags come from PlCdr1Framing::pid_flags asked at WirePosition::Sentinel, which is the only thing that decides them: PID_LIST_END is not a member and has no declaration of its own to carry.

Source

pub fn write_sequence<T, F: Fn(&mut Self, &T) -> Result<(), WireError>>( &mut self, values: &[T], element: F, ) -> Result<(), WireError>

A sequence: a four-byte count, then each element.

The element function is fallible, and every element function is, whether or not the element itself can refuse. Three of the four element kinds a collection can hold can — a char outside Latin-1 (§7.2.2.2.1.2.2), a wchar outside the BMP, and a nested aggregate whose own encode reaches one — and a second infallible overload beside this one would be a shape for the generator to pick between, one construct at a time. Ok(…) around an infallible write costs nothing and reads as what it is.

§Errors

Whatever the element function returns.

Source

pub fn write_array<T, F: Fn(&mut Self, &T) -> Result<(), WireError>>( &mut self, values: &[T], element: F, ) -> Result<(), WireError>

An array: each element, with no count.

The element count is in the type, not on the wire. XTypes 1.3 §7.4.3.5.

§Errors

As Writer::write_sequence.

Source

pub fn write_delimited_sequence<T, F: Fn(&mut Self, &T) -> Result<(), WireError>>( &mut self, values: &[T], element: F, ) -> Result<(), WireError>

A sequence behind a delimiter.

XTypes 1.3 §7.4.3.5 rule (12): under XCDR2 a sequence whose element type is not primitive carries a DHEADER ahead of the length. Which sequences those are is zerodds_ast_layout::collection_is_delimited, not a decision taken here.

§Errors

As Writer::write_sequence. The delimiter is patched before the error is returned only when there is no error: a refused element leaves a partial buffer, which the caller discards.

Source

pub fn write_delimited_array<T, F: Fn(&mut Self, &T) -> Result<(), WireError>>( &mut self, values: &[T], element: F, ) -> Result<(), WireError>

An array behind a delimiter. Rule (9), the array counterpart.

§Errors

As Writer::write_delimited_sequence.

Source

pub fn write_sequence_bounded<T, F: Fn(&mut Self, &T) -> Result<(), WireError>>( &mut self, values: &[T], bound: usize, element: F, ) -> Result<(), WireError>

A sequence<T, N>, whose count is checked against N.

The bytes are a plain sequence’s: Table 17’s O2.length <= T1.length is a property of the value, and the wire carries no bound to compare it with. Refused rather than written short, for the reason Writer::write_string_bounded gives — the receiver’s own sequence<T, N> has room for N, and a sender that wrote more has written a value of a type nobody declared.

§Errors

WireError::OutOfRange for more than bound elements, and whatever the element function returns.

Source

pub fn write_delimited_sequence_bounded<T, F: Fn(&mut Self, &T) -> Result<(), WireError>>( &mut self, values: &[T], bound: usize, element: F, ) -> Result<(), WireError>

A bounded sequence behind a delimiter. Rule (12).

§Errors

As Writer::write_sequence_bounded.

Source

pub fn write_map<M, K, V, FK, FV>( &mut self, entries: &M, key: FK, value: FV, ) -> Result<(), WireError>
where M: WireMap<K, V> + ?Sized, FK: Fn(&mut Self, &K) -> Result<(), WireError>, FV: Fn(&mut Self, &V) -> Result<(), WireError>,

A map: a four-byte entry count, then each entry’s key followed by its value.

§The count is entries and not halves

XTypes 1.3 §7.4.1.1.4 defines a map<K, V> by equivalence to a sequence<Entry> whose element is the pair, so the O.length that precedes it counts pairs. Two independent readings say the same:

  • the layout plan. zerodds_ast_layout::xcdr’s TypeKind::Map arm gives the map max(key, value, 4) alignment and one SEQUENCE_LENGTH_ALIGNMENT length word, not one per half;
  • a recorded foreign measurement. tests/interop-results/sources/vendor-corpus.tsv, case map-key-string under fastdds, XCDR1 big-endian, is 00000003 followed by three (string, long) pairs and then the ffffffff of the trailing long tail. Three entries, six halves, and the word on the wire is 3.
§The entries go out in the order the container holds them

This runtime takes a BTreeMap and walks it, so the order is ascending by key — which is what zerodds_ast_layout::MapEntryOrder::AscendingKey is defined as: what a binding that holds a map in an ordered container writes. The order is a property of the container the caller already chose, not a second decision taken here.

Whether a delimited map also carries this count is the one thing the specification says twice and differently — §7.4.1.1.4 against rule (15) of §7.4.3.5.3 — and it is the caller’s, through which of these four functions it calls. Fast DDS writes both, which is zerodds_wire_codec::value::MapLengthPolicy’s default and what Writer::write_delimited_map does.

§Errors

Whatever either half’s function returns.

Source

pub fn write_delimited_map<M, K, V, FK, FV>( &mut self, entries: &M, key: FK, value: FV, ) -> Result<(), WireError>
where M: WireMap<K, V> + ?Sized, FK: Fn(&mut Self, &K) -> Result<(), WireError>, FV: Fn(&mut Self, &V) -> Result<(), WireError>,

A map behind a delimiter.

XTypes 1.3 §7.4.3.5 rule (14) exempts a map from the DHEADER only when both halves are primitive, and rule (15) delimits every other map under XCDR2. Which maps those are is zerodds_ast_layout’s TypeLayout::needs_dheader, read through MapDelimiter, and not a decision taken here.

§Errors

As Writer::write_map.

Source

pub fn write_map_bounded<M, K, V, FK, FV>( &mut self, entries: &M, bound: usize, key: FK, value: FV, ) -> Result<(), WireError>
where M: WireMap<K, V> + ?Sized, FK: Fn(&mut Self, &K) -> Result<(), WireError>, FV: Fn(&mut Self, &V) -> Result<(), WireError>,

A map<K, V, N>, whose entry count is checked against N.

The bytes are a plain map’s, for the reason Writer::write_sequence_bounded gives: the wire carries no bound to compare with, so an over-long value is refused rather than written short.

§Errors

WireError::OutOfRange for more than bound entries, and whatever either half’s function returns.

Source

pub fn write_delimited_map_bounded<M, K, V, FK, FV>( &mut self, entries: &M, bound: usize, key: FK, value: FV, ) -> Result<(), WireError>
where M: WireMap<K, V> + ?Sized, FK: Fn(&mut Self, &K) -> Result<(), WireError>, FV: Fn(&mut Self, &V) -> Result<(), WireError>,

A bounded map behind a delimiter. Rule (15).

§Errors

As Writer::write_map_bounded.

Source

pub fn zero_padded(&self) -> [u8; 16]

The holder as a KeyHash, zero-padded to sixteen bytes.

For a holder of sixteen bytes or fewer. DDSI-RTPS 2.5 §9.6.3.8.

Source

pub fn md5(&self) -> [u8; 16]

The MD5 of the holder, for one longer than sixteen bytes.

Source

pub fn write_bytes(&mut self, bytes: &[u8])

bytes as they are, with no alignment and no length in front.

The counterpart of crate::reader::Reader::read_bytes, and the one way an already-encoded byte string goes into a stream: a CDR encapsulation built by a second writer, a GIOP request body whose type only the calling stub knows, the octets of a sequence<octet> behind their own length.

Trait Implementations§

Source§

impl Clone for Writer

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Writer

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.