zerodds-xml-compose 1.0.0-rc.7

DDS-XML type definitions into the ZeroDDS common AST — the XML counterpart of zerodds-idl-compose.
Documentation

zerodds-xml-compose

DDS-XML type definitions into the ZeroDDS common AST — the XML counterpart of zerodds-idl-compose.

One call takes a DDS-XML document and produces the same zerodds_ast::Ast that the IDL front end produces from an .idl file, so everything downstream of the model — zerodds_types::from_ast, the layout planner, zerodds-wire-codec, every code generator — is unchanged and does not know which language the declaration was written in.

let composed = zerodds_xml_compose::compose("types/xml/primitives.xml")?;
assert!(!composed.failed());

Why not zerodds-xml

zerodds-xml reads DDS-XML already and stops one layer short: it builds a descriptive TypeLibrary and bridges that to a MinimalTypeObject. That layer is a published API with its own users, and it drops what a model needs — a member carries no tryConstruct, no hashid and no external, a struct carries no autoid, an enum carries neither extensibility nor defaultLiteral, a union carries no extensibility, and its primitive table has no int8 or uint8. Widening those structs would change signatures every current caller compiles against.

This crate therefore takes the position against zerodds-xml that zerodds-idl-compose takes against zerodds-idl-parse: it reuses the front end's well-formedness layer — parse_xml_tree and its element tree, with the DDS-XML 1.0 §7.1 depth cap, element budget and namespace handling — and lowers that tree into the model itself.

What it carries

<module>, <struct> (with extensibility, baseType, autoid), <union> (with <discriminator> and <case>/<caseDiscriminator>, including default and enumerator-name labels), <enum> (with bitBound, extensibility, defaultLiteral), <bitmask> (both the <flag value=…> and <bit_value position=…> spellings), <typedef>, <forward_dcl>; every XTypes and IDL primitive spelling; bounded and unbounded strings and wstrings; sequences, maps and multi-dimensional arrays; <const> (at the top, in a module and in a structure) and <const_exp> for bounds, array dimensions and enumerator values; <include>; <bitset>; <verbatim>; <annotation> and <annotate>; and the member attributes key, optional, external, mustUnderstand, id, hashid and tryConstruct.

Member ids are assigned by DDS-XTypes 1.3 §7.3.1.2.1.1 with zerodds_idl_lower::hashed_member_id, so a type declared once in .idl and once in .xml reaches the same TypeIdentifier by construction. tests/idl_parity.rs asserts exactly that, pair by pair.

What it refuses

  • <discriminator key="true"> — the model has no slot for it and UnionDiscriminatorFlag has no bit for it, so accepting it would give a keyed and an unkeyed union the same TypeIdentifier. The IDL front end refuses the same construct for the same reason.
  • <annotation baseType="…"> — the model's annotation declaration has no base.
  • A built-in annotation written as <annotate> (key, optional, …); this representation writes those as attributes (§7.3.2.5).
  • An <include> of a file that is not an XML document, and one that cannot be read.
  • Every element it does not know, in a diagnostic naming it.

Bounds

-1 is unbounded. A bound of 0 is refused (IDL takes a positive integer); ComposeOptions::zero_bound_is_unbounded reads it as unbounded, which is how the OMG dds-xtypes suite writes it.

Spec sources

  • OMG DDS-XML 1.0 (formal/18-10-01) §7.1, §7.3.3.
  • OMG DDS-XTypes 1.3 Annex A (XML Type Representation), §7.3.1.2.1.
  • OMG IDL 4.2 §7.4 where the two representations share a rule.