Skip to main content

LayoutKey

Struct LayoutKey 

Source
pub struct LayoutKey {
Show 32 fields pub encoding: Encoding, pub endianness: Endianness, pub purpose: Purpose, pub length_codes: LengthCodePolicy, pub collection_delimiters: CollectionDelimiterPolicy, pub map_delimiter: MapDelimiter, pub wstring_length: WstringLengthPolicy, pub wchar_framing: WcharFraming, pub wchar_width: WcharWidth, pub wstring_unit_order: WstringUnitOrder, pub pl_cdr1_headers: PlCdr1HeaderPolicy, pub pid_flags: PidFlagPolicy, pub pl_cdr1_reading: PlCdr1Reading, pub must_understand: MustUnderstandPolicy, pub enum_holder: EnumHolderWidth, pub union_label: UnionLabelMatch, pub map_entries: MapEntryOrder, pub array_element_flattening: ArrayElementFlattening, pub enumerator_value: EnumeratorValue, pub union_framing: MutableUnionFraming, pub short_pid_range: ShortPidRange, pub fixed_digits: FixedDigitCount, pub default_extensibility: Extensibility, pub key_holder: KeyHolderExtensibility, pub key_holder_nesting: KeyHolderNesting, pub key_holder_order: KeyHolderOrder, pub key_holder_alignment: KeyHolderAlignment, pub defaulted_discriminator_member: DefaultedDiscriminatorMember, pub element_padding: ElementPadding, pub aggregate_delimiter: AggregateDelimiter, pub sequence_element_delimiter: SequenceElementDelimiter, pub wstring_code_units: WstringCodeUnits,
}
Expand description

What a layout is computed for.

Member offsets are invariant under endianness — byte order changes the bytes, not where they sit — so the cache shares offset computation between the two and consults the endianness only where it genuinely matters: the big-endian key holder and per-primitive byte order. Spec §7.

Fields§

§encoding: Encoding

Which encoding.

§endianness: Endianness

Which byte order.

§purpose: Purpose

Data or key holder.

§length_codes: LengthCodePolicy

How variable-length mutable members are framed.

§collection_delimiters: CollectionDelimiterPolicy

Which collections carry a delimiter under XCDR2.

§map_delimiter: MapDelimiter

Which of a map’s two halves decides whether the map is delimited.

§wstring_length: WstringLengthPolicy

How a wstring’s length is counted.

§wchar_framing: WcharFraming

How a scalar wchar is framed.

§wchar_width: WcharWidth

How wide a scalar wchar is, which is not the width of a wstring’s code units: rmw_cyclonedds_cpp writes two here and four there.

§wstring_unit_order: WstringUnitOrder

In what byte order a wstring’s code units go out.

§pl_cdr1_headers: PlCdr1HeaderPolicy

How a @mutable member is framed under XCDR1.

§pid_flags: PidFlagPolicy

What flags a PL_CDR1 parameter id carries, per position.

§pl_cdr1_reading: PlCdr1Reading

How tolerant a PL_CDR1 reader is of another framing.

§must_understand: MustUnderstandPolicy

Whether a member’s must_understand reaches the wire.

§enum_holder: EnumHolderWidth

How wide an enumeration’s holder is.

§union_label: UnionLabelMatch

Whether a negative case label of a narrow signed discriminator selects its branch.

§map_entries: MapEntryOrder

In what order a map’s entries go on the wire.

§array_element_flattening: ArrayElementFlattening

Whether an array’s element is flattened before the delimiter question. See ArrayElementFlattening.

§enumerator_value: EnumeratorValue

Which integer an enumerator serialises as.

§union_framing: MutableUnionFraming

How a @mutable union numbers its branches, and whether its XCDR1 parameter list is terminated.

§short_pid_range: ShortPidRange

Which member ids fit a PL_CDR1 short parameter header.

§fixed_digits: FixedDigitCount

Whether a fixed<P,S> carries its declared digit count or the value’s.

§default_extensibility: Extensibility

What an aggregate whose source said nothing is taken to be.

§key_holder: KeyHolderExtensibility

Whether a key holder keeps the type’s extensibility.

§key_holder_nesting: KeyHolderNesting

How deep a key holder’s member removal reaches.

§key_holder_order: KeyHolderOrder

In what order a key holder’s members are serialized.

§key_holder_alignment: KeyHolderAlignment

Whether a key holder’s members are aligned.

§defaulted_discriminator_member: DefaultedDiscriminatorMember

What becomes of a union’s member when @try_construct(use_default) defaulted its discriminator.

§element_padding: ElementPadding

Whether the elements of a collection carry alignment padding.

§aggregate_delimiter: AggregateDelimiter

Whether an aggregate’s declared extensibility reaches the wire.

§sequence_element_delimiter: SequenceElementDelimiter

Whether a sequence element of a non-@final type is preceded by its own octet length.

§wstring_code_units: WstringCodeUnits

Which octets stand for a wstring’s characters.

Implementations§

Source§

impl LayoutKey

Source

pub const fn pl_cdr1_framing(&self) -> PlCdr1FramingValues

The PL_CDR1 framing this key’s writer and reader use.

The header form is in the plan, because it changes a member’s extent; these values do not, so they ride on the writer and the reader, and both take them from here.

Source

pub const fn data(encoding: Encoding, endianness: Endianness) -> Self

A data plan in the given encoding and byte order, in the default dialect.

The dialect is Dialect::Specification, so every wire question the implementations answer differently is answered the way XTypes 1.3 answers it. LayoutKey::with_dialect selects another; each with_* method below overrides one setting of whichever dialect is in force, and overrides it whether or not a dialect was named.

The variant is named rather than taken from Dialect::default because this is a const fn and Default::default is not one. zerodds_ast_layout::key::the_default_dialect_is_one_fact holds the three spellings — #[default], Dialect::is_default and this call — to one value, so a change to one of them that misses the others fails rather than diverging quietly.

Source

pub const fn in_dialect( dialect: Dialect, encoding: Encoding, endianness: Endianness, purpose: Purpose, ) -> Self

Every policy of one dialect, for one encoding, byte order and purpose.

The encoding is an argument because one setting depends on it: RTI counts a wstring’s length differently under the two versions.

Source

pub const fn with_dialect(self, dialect: Dialect) -> Self

The same plan with every setting taken from another dialect.

This resets every one of them: it is a preset and not a patch, so applying it after a with_* call discards that call. The command-line probes apply the dialect first for that reason.

Source

pub const fn with_length_codes(self, policy: LengthCodePolicy) -> Self

The same plan with a different length-code policy.

Source

pub const fn with_collection_delimiters( self, policy: CollectionDelimiterPolicy, ) -> Self

The same plan with a different collection-delimiter policy.

Source

pub const fn with_element_padding(self, padding: ElementPadding) -> Self

The same plan with the elements of a collection packed against one another or aligned as §7.4.1 says.

Source

pub const fn with_aggregate_delimiter( self, delimiter: AggregateDelimiter, ) -> Self

The same plan with an aggregate’s declared extensibility reaching the wire or not.

Source

pub const fn with_sequence_element_delimiter( self, delimiter: SequenceElementDelimiter, ) -> Self

The same plan with a per-element octet length in front of a sequence element, or without one.

Source

pub const fn with_wstring_code_units(self, units: WstringCodeUnits) -> Self

The same plan with a wstring’s characters in UTF-16 code units or in UTF-8 octets.

Source

pub const fn with_wstring_length(self, policy: WstringLengthPolicy) -> Self

The same plan with a different wstring length policy.

Source

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

The same plan framing a scalar wchar another way.

Source

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

The same plan at a different scalar wchar width.

Source

pub const fn with_map_delimiter(self, policy: MapDelimiter) -> Self

The same plan asking a different half of a map whether the map is delimited.

Source

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

The same plan ordering a wstring’s code units another way.

Source

pub const fn wstring_order_conflicts(self) -> bool

Whether two settings of this plan both decide the byte order of a wstring’s code units.

Always false now, and kept as a signature rather than deleted. It answered the pair (WstringLengthPolicy::UnswappedUnits, non-Stream), which existed only because a byte order was living in the length enumeration under a length’s name. Judgement 2 of docs/wire-axes-followup.md moved it to WstringUnitOrder::HostUnswapped, and one axis cannot conflict with itself: the four orders are four points of one setting and any of them can be combined with any cell of C1 × C2 × C3.

The method stays because a caller refusing an impossible pair is cheap and a caller that stops refusing a possible one is not. If a second setting ever claims the same byte order, this is where it is caught.

Source

pub const fn with_pl_cdr1_headers(self, policy: PlCdr1HeaderPolicy) -> Self

The same plan with a different PL_CDR1 header policy.

Source

pub fn for_sample( self, ast: &Ast, root: Id<TypeNode>, ) -> Result<Self, LayoutError>

The plan for a sample of root: a PL_CDR1 header policy that is decided per sample becomes PlCdr1HeaderPolicy::ExtendedForConstructed when the sample’s type can exceed the short form’s length and PlCdr1HeaderPolicy::ShortRoundedLength when it cannot. Any other key is returned as it is.

A writer and a reader of a whole sample call this once, with the sample’s type, and frame every type nested in it with the key it returns: RTI decides the form for the sample, and a nested type that is small on its own is framed by its sample’s choice.

§Errors

crate::plan::LayoutError when the sample’s type cannot be sized: an unresolved reference, an unevaluable bound, a nesting past the planner’s bound.

Source

pub const fn with_pl_cdr1_reading(self, reading: PlCdr1Reading) -> Self

The same plan with a reader that takes another framing’s PL_CDR1 streams, or does not.

Source

pub const fn with_pid_flags(self, policy: PidFlagPolicy) -> Self

The same plan putting different flags on a parameter id.

Source

pub const fn with_must_understand(self, policy: MustUnderstandPolicy) -> Self

The same plan writing or omitting a member’s must-understand flag.

Source

pub const fn with_enum_holder(self, policy: EnumHolderWidth) -> Self

The same plan giving an enumeration a holder of another width.

Source

pub const fn with_union_label(self, policy: UnionLabelMatch) -> Self

The same plan matching a negative case label another way.

Source

pub const fn with_array_element_flattening( self, policy: ArrayElementFlattening, ) -> Self

The same key with another array-element flattening.

Source

pub const fn with_map_entries(self, policy: MapEntryOrder) -> Self

The same plan ordering a map’s entries another way.

Source

pub const fn with_enumerator_value(self, policy: EnumeratorValue) -> Self

The same plan with a different enumerator-value policy.

Source

pub const fn with_union_framing(self, policy: MutableUnionFraming) -> Self

The same plan with a different @mutable union framing.

Source

pub const fn with_short_pid_range(self, policy: ShortPidRange) -> Self

The same plan with a different short-PID range.

Source

pub const fn with_fixed_digits(self, policy: FixedDigitCount) -> Self

The same plan counting a fixed’s digits another way.

Source

pub const fn with_key_holder(self, policy: KeyHolderExtensibility) -> Self

The same plan with a different key-holder rule.

Source

pub const fn with_key_holder_nesting(self, policy: KeyHolderNesting) -> Self

The same plan with a different key-holder nesting rule.

Source

pub const fn with_key_holder_order(self, policy: KeyHolderOrder) -> Self

The same plan ordering a key holder’s members differently.

Source

pub const fn with_key_holder_alignment(self, policy: KeyHolderAlignment) -> Self

The same plan aligning a key holder’s members differently.

Source

pub const fn with_defaulted_discriminator_member( self, policy: DefaultedDiscriminatorMember, ) -> Self

The same plan giving a union’s member another answer when @try_construct(use_default) defaulted its discriminator.

Source

pub const fn with_default_extensibility( self, extensibility: Extensibility, ) -> Self

The same plan reading an unannotated aggregate as something else.

XTypes 1.3 §7.3.1.2.1.8 sanctions the knob outright:

In the event that the representation of a given type does not indicate the type’s extensibility kind, the type shall be considered appendable. Implementations may provide a mechanism to override this default behavior; for example, IDL compilers may provide configuration options to allow users to specify whether types of unspecified extensibility are to be considered final, appendable, or mutable.

Source

pub const fn key(encoding: Encoding) -> Self

The key-holder plan, which is always big-endian. DDSI-RTPS 2.5 §9.6.3.8.

In Dialect::Specification, the default, for the reason Self::data is: the dialect reaches the holder — whether an unannotated keyed aggregate carries a DHEADER depends on what unannotated means — and crate::keyhash::key_holder_plan_with is the way to plan a holder under some other dialect.

Source

pub const fn member_pid_carries_must_understand(self) -> bool

Whether a member’s own parameter id carries its must-understand bit — the M in a short PID’s 16-bit flags and FLAG_2 in PID_EXTENDED’s eMemberHeader (§7.4.1.2.3).

Two policies cross here. MustUnderstandPolicy::writes_flag says whether the member’s declaration reaches any flag at all. PidFlagPolicy::ImplExtensionOnMembers — OpenDDS — sets FLAG_IMPL_EXTENSION | FLAG_MUST_UNDERSTAND on every 16-bit member id as fixed framing, and writes nothing declaration-dependent anywhere in a PID: measured 2026-08-24 on identifier-keyword-member-ids under XCDR1, where the @key member’s eMemberHeader is 0x0FEDF2A2 — the bare hash, no FLAG_2 — while the same member’s XCDR2 EMHEADER carries M_FLAG (which is what put DeclaredAndKey in the OpenDDS dialect). §7.4.1.2.3 as written wants the bit in the eMemberHeader, so the specification dialect keeps it.

Source

pub const fn offset_key(self) -> OffsetKey

The part of the key that actually affects offsets.

Two keys sharing this share their offset computation, which is what lets one cache entry serve both byte orders.

Endianness is not in it: byte order changes the bytes, not where they sit.

Everything else is. CollectionDelimiterPolicy was left out until this cache served an RTI-dialect plan, with no delimiter, to a Cyclone-dialect request that needed one: two keys that differ in a four-byte header do not share an offset computation. WstringLengthPolicy was left out for the reason that a wstring plans as Extent::Unbounded under every variant, which is true and was not the whole question: the policy also fixes the width of a scalar wchar, and a four-byte one aligns to four and moves every member behind it. WcharFraming is in for the second half of the same reason — GIOP 1.2’s wchar is one octet longer than its code unit and aligns to one, so a plan built for it puts every following member somewhere a fixed-width plan does not.

WstringUnitOrder is not in it, and that is a claim rather than an omission: a wstring plans as Extent::Unbounded under all three orders, and the byte-order mark makes it two octets longer without making it any less unbounded. Nothing an order changes reaches an offset.

EnumHolderWidth is in it, and it is the plainest case of all: an @bit_bound(8) enumeration is one octet under one value and four under the other, so it changes the type’s own extent, its alignment and the offset of every member behind it. A cache that left it out would hand a one-octet plan to a caller that asked for the four-octet holder.

UnionLabelMatch is not in it, and that is a claim rather than an omission. A union’s extent is the discriminator plus the widest branch under both values: with no default: the suppressed match writes less than the extent, which the extent already bounds, and with one it writes the default branch, which the extent already covers. Nothing it changes reaches an offset — crates/wire-probe/tests/union_label_match.rs::the_extent_is_the_same_under_both_values is that claim as a test rather than as this sentence.

MapEntryOrder is not in it, and that is a claim rather than an omission for the plainest reason of the three: a permutation of a map’s entries writes the same entries, so the count, the byte extent and every offset behind it are the same under both values. crates/wire-probe/tests/map_entry_order.rs::the_extent_is_the_same_under_both_values is that claim as a test.

FixedDigitCount is in it, and it is the second plainest case after EnumHolderWidth: a fixed<9,3> is five octets under one value and as many as the value needs under the other, so the type stops being fixed-size and every member behind it moves. A cache that left it out would hand a five-octet plan to a caller that asked for the value’s digits.

EnumeratorValue is not in it, and it is the sharpest contrast with EnumHolderWidth beside it: the two axes reach the same construct and only one of them reaches an offset. The holder’s width is a length; which integer goes into it is a value, and @value(200) and the ordinal 2 occupy the same holder. crates/wire-probe/tests/enumerator_value.rs::the_extent_is_the_same_under_both_values is that claim as a test.

Trait Implementations§

Source§

impl Clone for LayoutKey

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 Copy for LayoutKey

Source§

impl Debug for LayoutKey

Source§

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

Formats the value using the given formatter. Read more
Source§

impl Eq for LayoutKey

Source§

impl Hash for LayoutKey

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl Ord for LayoutKey

Source§

fn cmp(&self, other: &Self) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 (const: unstable) · Source§

fn max(self, other: Self) -> Self
where Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 (const: unstable) · Source§

fn min(self, other: Self) -> Self
where Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 (const: unstable) · Source§

fn clamp(self, min: Self, max: Self) -> Self
where Self: Sized,

Restrict a value to a certain interval. Read more
Source§

fn clamp_to<R>(self, range: R) -> Self
where Self: Sized, R: ClampBounds<Self>,

🔬This is a nightly-only experimental API. (clamp_to)
Restrict a value to a certain range. Read more
Source§

impl PartialEq for LayoutKey

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl PartialOrd for LayoutKey

Source§

fn partial_cmp(&self, other: &Self) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 (const: unstable) · Source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 (const: unstable) · Source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the <= operator. Read more
1.0.0 (const: unstable) · Source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 (const: unstable) · Source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by the >= operator. Read more
Source§

impl StructuralPartialEq for LayoutKey

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.