DDS DCPS 1.4 — Spec Coverage

Spec: OMG DDS 1.4 — formal/2015-04-10 (180 pages) →

Context: DCPS is spread across two crates:

Live: Entity trait + listener stack (6 listeners + listener_dispatch), WaitSet+GuardCondition+StatusCondition, all 13 status records, register/unregister/dispose lifecycle, BuiltinSubscriber + 4 builtin- topic readers, CoherentScope (begin/end_coherent_changes), WLP for LIVELINESS, InstanceHandle, SampleInfo. 22 QoS policies defined, a subset wired live.


§1 Scope / Purpose

1.1.1 DDS API + communication semantics for DCPS

Spec: §1.1, p. 1 — “The DDS spec defines an API + communication semantics for DCPS.”

Repo: crates/dcps/src/lib.rs with the full §2.2.2 entity API (DomainParticipant, Publisher, Subscriber, Topic, DataWriter, DataReader, WaitSet, Conditions). Communication semantics over the RTPS transport (crates/rtps/, crates/discovery/).

Tests: workspace-wide (the §2.2.2.x section items demonstrate all sub-requirements individually).

Status: done — all sub-sections §2.2.2-§2.2.6 are marked done; see the per-item evidence further below.

1.1.2 Pre-allocate resources (no dynamic alloc)

Spec: §1.1, p. 1 — “Pre-allocate Resources.”

Repo: crates/dcps/src/runtime.rs::RuntimeConfig with caps for sample pools, reader/writer capacity. DoS caps in crates/rtps/src/parameter_list.rs::MAX_PARAMETERS and crates/dcps/src/condition.rs::MAX_WAITSET_CONDITIONS.

Tests: RuntimeConfig tests + DoS-cap tests in the respective modules.

Status: done — all critical hot paths have static caps; heap allocations remain on-startup or per-event instead of per-sample.

1.1.3 Avoid unbounded resources

Spec: §1.1 — “Avoid unbounded resources.”

Repo: RESOURCE_LIMITS QoS in crates/qos/src/policies/resource_limits.rs plus DoS caps in ParameterList, WaitSet, the type resolver (crates/types/src/resolve.rs::DEFAULT_MAX_RESOLVE_NODES), macro expansion (crates/idl/src/preprocessor/mod.rs::MAX_MACRO_EXPANSION_DEPTH).

Tests: per-cap negative tests per cap site (see the respective crate-specific test modules).

Status: done

1.1.4 Minimize copies

Spec: §1.1 — “Minimize copies.”

Repo: crates/cdr/src/buffer.rs::BufferReader with borrow decode (zero-copy byte slices); crates/dcps/src/dds_type.rs::RawBytes for the unmarshalled inbox; crates/cdr/src/struct_enc.rs::MutableMember with body: &[u8].

Tests: zero-copy paths implicit via roundtrip tests; explicit in cdr borrow tests.

Status: done

1.1.5 Typed interfaces

Spec: §1.1 — “Typed Interfaces.”

Repo: crates/dcps/src/dds_type.rs::DdsType trait, generic over Topic/Writer/Reader.

Tests: type-generic tests.

Status: done

1.1.6 QoS-driven behavior

Spec: §1.1 — “QoS-driven Behavior.”

Repo: crates/qos/src/policies/ with all 22 spec policies: durability, durability_service, presentation, deadline, latency_budget, ownership, ownership_strength, liveliness, time_based_filter, partition, reliability, transport_priority, lifespan, destination_order, history, resource_limits, entity_factory, writer_data_lifecycle, reader_data_lifecycle, user_data, topic_data, group_data. Compatibility check via crates/qos/src/compatibility.rs.

Tests: an own test module per QoS policy (see §2.2.3.x items further below); cross-QoS compatibility tests in compatibility.rs.

Status: done — all 22 policies are available in the wire format and code; engine-side wiring see §2.2.3.x per policy. K3a-F all 10 Iron-Rule open trackers converted to live implementations (T1 contains_entity recursive, T2 GROUP- coherent snapshot_generation, T3 RESOURCE_LIMITS write block, T4 EXCLUSIVE strength selection + GUID tiebreaker, T5 TIME_BASED_FILTER reader drop, T6 READER_DATA_LIFECYCLE autopurge timer, T7 QueryCondition SQL per-sample eval, T8 MultiTopic hash join, T9 liveliness-driven OWNERSHIP failover, T10 TRANSIENT/PERSISTENT durability service).

1.1.7 Pub/sub separation (separate include)

Spec: §1.1 — “Pub/Sub separation.”

Repo: crates/dcps/src/{publisher,subscriber}.rs.

Tests: crate-layout tests.

Status: done

1.2 Wire interop is NOT in scope of DCPS (see DDSI-RTPS)

Spec: §1.2 — “Wire interop is separate, in DDSI-RTPS.”

Repo: — see ddsi-rtps-2.5.md.

Tests:

Status: n/a (informative) — the section only declares the scope separation between the DCPS spec and the DDSI-RTPS spec; no normative requirement on the DCPS implementation.


§2.1 Summary

2.1.1 The DDS spec consists of PIM (UML) + IDL PSM

Spec: §2.1, p. 3 — “PIM + IDL PSM.”

Repo:

Tests:

Status: n/a (informative) — describes the structure of the spec itself (the OMG PIM+PSM convention), not a requirement to implement.

2.1.2 DCPS layer for typed pub/sub data

Spec: §2.1, p. 3.

Repo: crates/dcps/src/lib.rs.

Tests: crate-wide.

Status: done

2.1.3 DLRL layer

Spec: §2.1, p. 3 — optional Data-Local-Reconstruction Layer with an object cache + identity tracking + relationship resolver (1:1/1:N/N:M) over DCPS.

Repo: crates/dlrl/ (1668 SLOC + 48 inline tests) + crates/dlrl-codegen/ (PSM codegen for C++/C#/Java/TS).

Tests: cross-ref dlrl-1.2 (own spec-coverage file for DDS 1.2 §8 + Annex B; no longer part of the spec in DDS 1.4).

Status: done — DLRL is implemented as a standalone stack; formal spec coverage in dlrl-1.2 (20 done / 0 partial / 0 open).


§2.2.1.1 ReturnCode_t (Page 5, Tab. RC)

2.2.1.1.1 RC OK -> Result::Ok

Spec: §2.2.1.1 Tab.RC — “OK: Successful return.”

Repo: crates/dcps/src/error.rs::Result::Ok.

Tests: crate-wide.

Status: done

2.2.1.1.2 RC ERROR -> DdsError::Other

Spec: “ERROR: Generic, unspecified error.”

Repo: crates/dcps/src/error.rs::DdsError::Other { reason } + as_return_code() maps to return_code::ERROR = 1. WireError/TransportError also map to RC ERROR (spec-conformant: all three are unspecified implementation errors).

Tests: crates/dcps/src/error.rs::tests: rc_error_maps_for_wire_and_transport_and_other, rc_constants_have_spec_values.

Status: done

2.2.1.1.3 RC BAD_PARAMETER -> DdsError::BadParameter

Spec: “BAD_PARAMETER: Illegal parameter value.”

Repo: crates/dcps/src/error.rs::DdsError::BadParameter { what } + as_return_code() maps to return_code::BAD_PARAMETER = 3.

Tests: crates/dcps/src/error.rs::tests::rc_bad_parameter_maps; plus trigger-site tests in crates/dcps/src/topic.rs (e.g. an empty topic name → BadParameter).

Status: done

2.2.1.1.4 RC UNSUPPORTED -> DdsError::Unsupported

Spec: “UNSUPPORTED: Unsupported operation.”

Repo: crates/dcps/src/error.rs::DdsError::Unsupported { feature } + as_return_code() maps to return_code::UNSUPPORTED = 2.

Tests: crates/dcps/src/error.rs::tests::rc_unsupported_maps.

Status: done

2.2.1.1.5 RC ALREADY_DELETED

Spec: “ALREADY_DELETED: already deleted.”

Repo: crates/dcps/src/entity.rs::EntityState.deleted: AtomicBool + mark_deleted() (idempotent) + check_not_deleted() -> Result<()> guard helper delivers DdsError::AlreadyDeleted on subsequent ops. as_return_code() maps to return_code::ALREADY_DELETED = 9.

Tests: crates/dcps/src/entity.rs::tests: check_not_deleted_passes_for_fresh_entity, check_not_deleted_returns_already_deleted_after_mark, mark_deleted_is_idempotent; plus the mapping crates/dcps/src/error.rs::tests::rc_already_deleted_maps.

Status: done

2.2.1.1.6 RC OUT_OF_RESOURCES -> DdsError::OutOfResources

Spec: “OUT_OF_RESOURCES.”

Repo: crates/dcps/src/error.rs::DdsError::OutOfResources { what } + as_return_code() maps to return_code::OUT_OF_RESOURCES = 5; RESOURCE_LIMITS-QoS wiring in crates/qos/src/policies/resource_limits.rs.

Tests: crates/dcps/src/error.rs::tests::rc_out_of_resources_maps; plus QoS tests in crates/qos/src/policies/resource_limits.rs::tests.

Status: done

2.2.1.1.7 RC NOT_ENABLED

Spec: “NOT_ENABLED: Operation invoked on disabled Entity.”

Repo: crates/dcps/src/error.rs::DdsError::NotEnabled + as_return_code() maps to return_code::NOT_ENABLED = 6. crates/dcps/src/entity.rs::EntityState::check_enabled() -> Result<()> guard helper for public ops.

Tests: crates/dcps/src/entity.rs::tests: check_enabled_returns_not_enabled_for_disabled_entity, check_enabled_passes_after_enable, check_enabled_passes_for_factory_entity, plus existing enable_is_idempotent_and_reports_first_transition; plus the mapping crates/dcps/src/error.rs::tests::rc_not_enabled_maps.

Status: done

2.2.1.1.8 RC IMMUTABLE_POLICY

Spec: “IMMUTABLE_POLICY: Modify immutable QosPolicy.”

Repo: crates/dcps/src/error.rs::DdsError::ImmutablePolicy { policy } + as_return_code() maps to return_code::IMMUTABLE_POLICY = 7. crates/dcps/src/entity.rs::immutable_if_enabled helper site. The immutability matrix is tracked per QoS item in §2.2.3.x.

Tests: crates/dcps/src/error.rs::tests::rc_immutable_policy_maps; plus crates/dcps/src/entity.rs::tests::immutable_if_enabled_returns_correct_error.

Status: done

2.2.1.1.9 RC INCONSISTENT_POLICY

Spec: “INCONSISTENT_POLICY: inconsistent set.”

Repo: crates/dcps/src/error.rs::DdsError::InconsistentPolicy { what } + as_return_code() maps to return_code::INCONSISTENT_POLICY = 8. QoS consistency check in crates/qos/src/compatibility.rs.

Tests: crates/dcps/src/error.rs::tests::rc_inconsistent_policy_maps; plus QoS compatibility tests in crates/qos/src/compatibility.rs::tests.

Status: done

2.2.1.1.10 RC PRECONDITION_NOT_MET

Spec: “PRECONDITION_NOT_MET.”

Repo: crates/dcps/src/error.rs::DdsError::PreconditionNotMet { reason } + as_return_code() maps to return_code::PRECONDITION_NOT_MET = 4.

Tests: crates/dcps/src/error.rs::tests::rc_precondition_not_met_maps.

Status: done

2.2.1.1.11 RC TIMEOUT

Spec: “TIMEOUT.”

Repo: error.rs::DdsError::Timeout.

Tests: timeout tests in publisher.rs.

Status: done

2.2.1.1.12 RC ILLEGAL_OPERATION

Spec: “ILLEGAL_OPERATION.”

Repo: crates/dcps/src/error.rs::DdsError::IllegalOperation { what } + as_return_code() maps to return_code::ILLEGAL_OPERATION = 12.

Tests: crates/dcps/src/error.rs::tests::rc_illegal_operation_maps.

Status: done

2.2.1.1.13 RC NO_DATA

Spec: “NO_DATA.”

Repo: crates/dcps/src/error.rs::DdsError::NoData + as_return_code() maps to return_code::NO_DATA = 11. In practice read/take return an empty Vec<Sample> instead of an explicit error — that is spec-conformant (§2.2.2.5.3.6 allows both variants); the explicit error is available for C/C++/Java bridges.

Tests: crates/dcps/src/error.rs::tests::rc_no_data_maps.

Status: done


§2.2.1.2 Conceptual Outline

2.2.1.2.1 Publisher/DataWriter send-side, Subscriber/DataReader receive-side

Spec: §2.2.1.2, p. 5-6.

Repo: crates/dcps/src/{publisher,subscriber}.rs.

Tests: crate-wide.

Status: done

2.2.1.2.2 Topic connects publication and subscription via name+type

Spec: §2.2.1.2 — “Topic name+type.”

Repo: crates/dcps/src/topic.rs::Topic<T>.

Tests: topic tests.

Status: done

2.2.1.2.3 Coherent set via Publisher (begin/end_coherent_changes)

Spec: §2.2.1.2.

Repo: crates/dcps/src/coherent_set.rs::CoherentScope::begin/end.

Tests: begin_coherent_changes_* tests.

Status: done


§2.2.2.1 Infrastructure Module

2.2.2.1.1 Entity class — abstract base + QoS + listener + StatusCondition

Spec: §2.2.2.1.1, p. 11-13 — operations: set_qos / get_qos / set_listener / get_listener / get_statuscondition / get_status_changes / enable / get_instance_handle.

Repo: crates/dcps/src/entity.rs::Entity trait + EntityState.

Tests: enable_is_idempotent_and_reports_first_transition, get_status_condition_returns_pristine_when_no_changes.

Status: done — Entity trait + default impls + EntityState; IMMUTABLE-QoS enforcement via immutable_if_enabled / DdsError::ImmutablePolicy (§2.2.2.1.2 set_qos).

2.2.2.1.2 DomainEntity class

Spec: §2.2.2.1.2, p. 14 — “Specialization of Entity to be a contained-element of a DomainParticipant.”

Repo: the Entity trait suffices; no separate DomainEntity trait.

Tests: indirect.

Status: done

2.2.2.1.3 QosPolicy class

Spec: §2.2.2.1.3, p. 15.

Repo: crates/qos/src/policies/.

Tests: policies tests.

Status: done

2.2.2.1.4 Listener interface (abstract root)

Spec: §2.2.2.1.4, p. 15 — “Abstract root for all listener types.”

Repo: crates/dcps/src/listener.rs with 6 listener traits (Topic/DataWriter/Publisher/DataReader/Subscriber/DomainParticipant).

Tests: listener_dispatch_* tests.

Status: done

2.2.2.1.5 Status class

Spec: §2.2.2.1.5, p. 16.

Repo: crates/dcps/src/status.rs with all 13 status records.

Tests: status_records_default tests.

Status: done

2.2.2.1.6 WaitSet class (attach/detach/wait/get_conditions/notify)

Spec: §2.2.2.1.6, p. 16-17.

Repo: crates/dcps/src/condition.rs::WaitSet with attach_condition (idempotent + DoS cap MAX_WAITSET_CONDITIONS = 1024 delivers OutOfResources); detach_condition; get_conditions; wait with single-thread-wait enforcement via WaitSetInner.waiting: AtomicBool + an RAII guard (PreconditionNotMet on a concurrent second call); notify cvar wakeup; multi-WaitSet via Clone (shared Inner via Arc).

Tests: crates/dcps/src/condition.rs::tests: waitset_attach_detach_idempotent, waitset_wait_returns_immediately_if_already_triggered, waitset_wait_timeout_returns_err, waitset_wakes_when_guard_triggers, waitset_with_multiple_conditions_returns_all_triggered, waitset_clone_shares_state, waitset_default_is_empty, waitset_concurrent_wait_returns_precondition_not_met (single- thread-enforce negative), waitset_sequential_waits_after_first_returns_succeed, waitset_attach_above_max_returns_out_of_resources (OOR negative), waitset_attach_idempotent_does_not_count_against_cap, waitset_panic_in_wait_releases_waiting_flag.

Status: done

2.2.2.1.7 Condition class (trait root + get_trigger_value)

Spec: §2.2.2.1.7, p. 17.

Repo: condition.rs::Condition trait.

Tests: condition_trait_* tests.

Status: done

2.2.2.1.8 GuardCondition class (set_trigger_value)

Spec: §2.2.2.1.8, p. 18.

Repo: condition.rs::GuardCondition.

Tests: GuardCondition tests.

Status: done

2.2.2.1.9 StatusCondition class (set/get_enabled_statuses, get_entity)

Spec: §2.2.2.1.9, p. 18-19.

Repo: crates/dcps/src/entity.rs::StatusCondition with set_enabled_statuses / enabled_statuses / trigger_value / get_entity_handle() -> InstanceHandle (spec §2.2.2.1.9 get_entity equivalent for the Rust API; the handle is the only stable identity across all wrapper granularities) / entity_state() -> &Arc<EntityState> for direct state access.

Tests: crates/dcps/src/entity.rs::tests: status_condition_get_entity_handle_matches_owner_state, status_condition_get_entity_handle_unique_per_entity, status_condition_entity_state_returns_same_arc, status_condition_entity_state_reflects_lifecycle_changes, plus existing status_condition_trigger_value, status_condition_implements_condition_trait.

Status: done


§2.2.2.2 Domain Module

2.2.2.2.1 DomainParticipant class

Spec: §2.2.2.2.1, p. 21-30 — container for Pub/Sub/Topic/MultiTopic; factory methods; admin ops (ignore_); get_discovered_; etc.

Repo: crates/dcps/src/participant.rs::DomainParticipant with: - create_publisher / create_subscriber / create_topic (factory methods, each operation tracks the InstanceHandle of the created entity in inner.publishers / inner.subscribers / inner.topics for contains_entity and delete_contained_entities). - lookup_topicdescription(name) -> Option<TopicDescriptionHandle> (spec §2.2.2.2.1.12) — immediate local lookup without a discovery wait. - find_topic(name, timeout) -> Result<TopicDescriptionHandle> (spec §2.2.2.2.1.11) — local + SEDP cache poll until timeout. - instance_handle() (spec §2.2.2.1.1) — InstanceHandle of the participant. - contains_entity(handle) -> bool (spec §2.2.2.2.1.10) — checks self, all topics, all pub/sub children. - ignore_* / get_discovered_* / delete_contained_entities already wired in WP 2.7.

Tests: crates/dcps/src/participant.rs::tests: lookup_topicdescription_returns_local_topics, lookup_topicdescription_none_for_unknown, find_topic_returns_immediately_for_local, contains_entity_returns_true_for_self_handle, contains_entity_returns_true_for_local_topic, contains_entity_returns_true_for_local_publisher, contains_entity_returns_true_for_local_subscriber, contains_entity_returns_false_for_unknown_handle, contains_entity_returns_false_for_topic_after_delete.

Recursive path: contains_entity additionally recognizes DataWriter/DataReader handles via pub/sub children. PublisherInner + SubscriberInner track DW/DR handles (datawriters / datareaders mutex); via a weak backref they also propagate into ParticipantInner.datawriters / datareaders for fast top-down lookup. Per pub/sub there is also contains_writer / contains_reader as a targeted sub-lookup.

Tests (in addition to the 6 above): contains_entity_recursive_finds_local_datawriter, contains_entity_recursive_finds_local_datareader, contains_entity_recursive_does_not_find_foreign_datawriter.

Status: done

2.2.2.2.2 DomainParticipantFactory class (singleton)

Spec: §2.2.2.2.2, p. 31-33.

Repo: crates/dcps/src/factory.rs::DomainParticipantFactory with: - instance() -> &'static Self (spec §2.2.2.2.2.1 get_instance, singleton via OnceLock). - create_participant / create_participant_with_config / create_participant_offline (spec §2.2.2.2.2.2; all variants track the participant in the internal registry). - lookup_participant(domain_id) -> Option<DomainParticipant> (spec §2.2.2.2.2.4). - delete_participant(&p) -> Result<()> (spec §2.2.2.2.2.3 — removes from the registry + calls delete_contained_entities; delivers PreconditionNotMet if not registered). - set_default_participant_qos / get_default_participant_qos (spec §2.2.2.2.2.5). - set_qos / get_qos with a DomainParticipantFactoryQos struct (spec §2.2.2.2.2.6, default autoenable_created_entities = true).

Tests: crates/dcps/src/factory.rs::tests: factory_is_singleton, factory_creates_participant_with_correct_domain_id, lookup_participant_finds_registered_offline_participant, lookup_participant_returns_none_for_unknown_domain, delete_participant_removes_from_registry, delete_participant_unknown_returns_precondition_not_met, default_participant_qos_roundtrips, factory_qos_default_is_autoenable_true, factory_set_get_qos_roundtrip.

Status: done

2.2.2.2.3 DomainParticipantListener interface

Spec: §2.2.2.2.3, p. 33-34.

Repo: listener.rs::DomainParticipantListener trait + 14-method default.

Tests: listener_* tests.

Status: done


§2.2.2.3 Topic-Definition Module

2.2.2.3.1 TopicDescription class (abstract base)

Spec: §2.2.2.3.1, p. 35 — abstract base for Topic, ContentFilteredTopic, MultiTopic. API: get_type_name, get_name, get_participant.

Repo: crates/dcps/src/topic.rs::TopicDescription trait (object-safe, &dyn TopicDescription is the consumed type); implemented by Topic<T>, TopicDescriptionHandle, ContentFilteredTopic<T>.

Tests: crates/dcps/src/topic.rs::tests: topic_implements_topic_description, topic_description_handle_is_cloneable, topic_description_trait_is_object_safe, topic_description_create_topic_rejects_empty_name (BadParameter negative), topic_description_get_participant_returns_owning_participant.

Status: done

2.2.2.3.2 Topic class

Spec: §2.2.2.3.2, p. 36-37.

Repo: topic.rs::Topic<T>.

Tests: topic tests.

Status: done

2.2.2.3.3 ContentFilteredTopic class

Spec: §2.2.2.3.3, p. 37-38 — filter expression + filter parameters + get_related_topic. TopicDescription implementation with the type name from the related topic.

Repo: crates/dcps/src/topic.rs::ContentFilteredTopic<T> with new (constructor with expression parsing + parameter-index validation), get_filter_expression, get_filter_parameters, set_filter_parameters (with BadParameter validation), get_related_topic, evaluate(row) over the zerodds_sql_filter engine, plus a TopicDescription trait impl. DomainParticipant create_contentfilteredtopic factory.

Tests: crates/dcps/src/topic.rs::tests: cft_compiles_and_evaluates_filter, cft_with_params_can_be_updated, cft_get_related_topic, cft_invalid_expression_rejected (BadParameter negative), cft_param_index_out_of_range_rejected (BadParameter negative), cft_set_filter_parameters_validates_count, cft_filter_with_string_param, cft_filter_with_or_and_combination, cft_unknown_field_returns_bad_parameter (BadParameter negative), cft_clone_shares_params.

Status: done

2.2.2.3.4 MultiTopic class [optional, spec §2.2.2.3.4]

Spec: §2.2.2.3.4, p. 38-39 — combines multiple topics via an SQL subscription expression. Spec-explicit optional.

Repo: crates/dcps/src/topic.rs::MultiTopic<T> with subscription_expression (read-only), expression_parameters (get/set per RwLock), related_topic_names: Vec<String>, get_related_topic_names. TopicDescription trait impl with a user-defined type_name. DomainParticipant factory: create_multitopic (spec §2.2.2.2.1.15) + delete_multitopic (spec §2.2.2.2.1.16) with participant-match validation and a full BadParameter negative path.

Tests: crates/dcps/src/topic.rs::tests: multitopic_compiles_and_implements_topic_description, multitopic_set_expression_parameters_roundtrip, multitopic_rejects_empty_name (negative), multitopic_rejects_empty_type_name (negative), multitopic_rejects_empty_related_topics (negative), multitopic_rejects_invalid_expression (negative), multitopic_rejects_param_index_out_of_range (negative), multitopic_set_params_validates_index_range (negative), multitopic_clone_shares_params, delete_multitopic_rejects_foreign_participant (negative).

Cross-topic sample routing: hash-join operator crates/dcps/src/topic.rs::hash_join_two with an O(n+m) build/probe phase + Cartesian match for duplicate keys. JoinedRow<'a> dispatches dotted paths <topic>.<field> to the right topic source. MultiTopic::evaluate_joined(row) evaluates the subscription_expression against the combined rows. Tests: joined_row_dispatches_dotted_paths_by_topic_prefix, joined_row_undotted_falls_back_to_first_match, multitopic_evaluate_joined_uses_dotted_paths, hash_join_two_combines_matching_rows, hash_join_two_returns_empty_when_no_keys_match (negative), hash_join_two_emits_cartesian_for_duplicate_keys, hash_join_two_predicate_can_filter_pairs.

Status: done

2.2.2.3.5 TopicListener interface (on_inconsistent_topic)

Spec: §2.2.2.3.5, p. 40.

Repo: listener.rs::TopicListener trait.

Tests:

Status: done

2.2.2.3.6 TypeSupport interface

Spec: §2.2.2.3.6, p. 40-41.

Repo: dds_type.rs::DdsType trait.

Tests:

Status: done

2.2.2.3.7 Derived classes per application class (FooDataReader/Writer/TypeSupport)

Spec: §2.2.2.3.7, p. 41.

Repo: generic DataReader<T>/DataWriter<T> (Rust-idiomatically no Foo* classes).

Tests: generic tests.

Status: done


§2.2.2.4 Publication Module

2.2.2.4.1 Publisher class

Spec: §2.2.2.4.1, p. 43-46 — operations: create_datawriter, delete_datawriter, set/get_default_datawriter_qos, copy_from_topic_qos, suspend/resume_publications, begin/end_coherent_changes, wait_for_acknowledgments, get_participant.

Repo: crates/dcps/src/publisher.rs::Publisher with: - create_datawriter / set_listener / assert_liveliness / wait_for_acknowledgments (existing). - suspend_publications / resume_publications / is_suspended via PublisherInner.suspended: AtomicBool (spec §2.2.2.4.1.10/11). - copy_from_topic_qos(&mut DataWriterQos, &TopicQos) static helper (spec §2.2.2.4.1.13) — copies the shared policies visible in the current TopicQos struct (durability, reliability). - coherent changes via crates/dcps/src/coherent_set.rs::CoherentScope.

Tests: crates/dcps/src/publisher.rs::tests: publisher_creates_datawriter_for_matching_type, suspend_publications_sets_flag, resume_publications_clears_flag, suspend_publications_is_idempotent, resume_without_suspend_is_noop, copy_from_topic_qos_copies_durability_and_reliability, copy_from_topic_qos_does_not_touch_writer_only_policies, plus coherent-set tests in coherent_set.rs::tests.

Status: done

2.2.2.4.2 DataWriter class

Spec: §2.2.2.4.2, p. 47-55 — write/dispose/register/lookup/ assert_liveliness/get_*-status/get_matched_subscriptions.

Repo: publisher.rs::DataWriter<T> + instance_tracker.rs + wlp.rs.

Tests: datawriter_* tests.

Status: done — register_instance/unregister/dispose/write/ write_w_timestamp/lookup_instance/get_key_value/assert_liveliness live; get_*_status polling API partial.

2.2.2.4.3 PublisherListener interface

Spec: §2.2.2.4.3, p. 56.

Repo: listener.rs::PublisherListener.

Tests:

Status: done

2.2.2.4.4 DataWriterListener interface (4 callbacks)

Spec: §2.2.2.4.4, p. 57.

Repo: listener.rs::DataWriterListener.

Tests:

Status: done

2.2.2.4.5 Concurrency behavior

Spec: §2.2.2.4.5, p. 57.

Repo: Rust-thread-safe via Arc.

Tests:

Status: done


§2.2.2.5 Subscription Module

2.2.2.5.1 SampleInfo state machine (Sample/View/Instance state)

Spec: §2.2.2.5.1.1-9, p. 59-65 — interpretation of the SampleInfo fields; three orthogonal state dimensions with a mask filter.

Repo: crates/dcps/src/sample_info.rs with: - SampleStateKind (READ / NOT_READ) + sample_state_mask::* constants. - ViewStateKind (NEW / NOT_NEW) + view_state_mask::*. - InstanceStateKind (ALIVE / NOT_ALIVE_DISPOSED / NOT_ALIVE_NO_WRITERS) + instance_state_mask::* + is_alive / is_not_alive predicates. - SampleInfo::matches_states(sample_mask, view_mask, instance_mask) for the read_w_condition filter. - SampleInfo::new_alive constructor for the live path.

Tests: crates/dcps/src/sample_info.rs::tests: defaults_are_alive_new_not_read, instance_state_predicates, sample_state_predicate, matches_states_filter, sample_info_three_state_dimensions_independent (positive + negative filter per dimension), sample_info_dispose_marker_has_invalid_data, enum_default_impls.

Status: done

2.2.2.5.2 Subscriber class

Spec: §2.2.2.5.2, p. 65-69 — operations: create_datareader, get_datareaders, notify_datareaders, begin/end_access, etc.

Repo: crates/dcps/src/subscriber.rs::Subscriber with: - create_datareader / set_listener / get_listener (existing). - begin_access (spec §2.2.2.5.2.8, idempotent, nestable) + end_access (spec §2.2.2.5.2.9, delivers PreconditionNotMet on underflow) + is_access_open via SubscriberInner.access_scope: Arc<GroupAccessScope> (counter-based in crates/dcps/src/coherent_set.rs::GroupAccessScope).

Tests: crates/dcps/src/subscriber.rs::tests: subscriber_begin_end_access_roundtrip, subscriber_end_access_without_begin_returns_precondition_not_met, (negative), subscriber_begin_access_is_nestable, subscriber_too_many_ends_after_balanced_returns_error (negative), plus existing subscriber-create_datareader and listener tests.

Status: done

2.2.2.5.3 DataReader class

Spec: §2.2.2.5.3, p. 70-85 — read/take/read_with_info/ read_filtered/read_instance/take_instance/read_next_instance/ take_next_instance/get_*-status/wait_for_historical_data etc.

Repo: subscriber.rs::DataReader<T>.

Tests: datareader_* tests.

Status: done — all read/take variants done; get_*_status polling partial; wait_for_historical_data open.

2.2.2.5.4 DataSample class (Data + SampleInfo)

Spec: §2.2.2.5.4, p. 86.

Repo: subscriber.rs::Sample<T>.

Tests:

Status: done

2.2.2.5.5 SampleInfo class (complete)

Spec: §2.2.2.5.5, p. 86-87 — sample_state/view_state/ instance_state/disposed_generation_count/no_writers_generation_count/ sample_rank/generation_rank/absolute_generation_rank/source_timestamp/ instance_handle/publication_handle/valid_data (12 fields).

Repo: crates/dcps/src/sample_info.rs::SampleInfo with all 12 spec fields and appropriate default values. The reader-side update of the generation counters happens in the DataReader read paths.

Tests: crates/dcps/src/sample_info.rs::tests: sample_info_all_spec_fields_accessible (all 12 fields readable + settable with concrete values), sample_info_dispose_marker_has_invalid_data (negative: a dispose sample has valid_data=false), sample_info_generation_rank_starts_zero, new_alive_constructor_sets_handles_and_timestamp, plus existing defaults_are_alive_new_not_read.

Status: done

2.2.2.5.6 SubscriberListener interface

Spec: §2.2.2.5.6, p. 87.

Repo: listener.rs::SubscriberListener.

Tests:

Status: done

2.2.2.5.7 DataReaderListener interface (7 callbacks)

Spec: §2.2.2.5.7, p. 88.

Repo: listener.rs::DataReaderListener.

Tests:

Status: done

2.2.2.5.8 ReadCondition class

Spec: §2.2.2.5.8, p. 88-89 — Sample/View/InstanceState mask filter; triggers when the reader contains samples with these masks.

Repo: crates/dcps/src/condition.rs::ReadCondition with mask getters (get_sample_state_mask, get_view_state_mask, get_instance_state_mask) + a closure-based trigger (sm, vm, im) -> bool. Condition trait implemented (object-safe).

Tests: crates/dcps/src/condition.rs::tests: read_condition_returns_trigger_from_closure, read_condition_trigger_false_when_closure_says_false (negative), read_condition_implements_condition_trait_object_safe, read_condition_attaches_to_waitset (WaitSet integration).

Status: done

2.2.2.5.9 QueryCondition class

Spec: §2.2.2.5.9, p. 89 — extends ReadCondition with an SQL filter expression + mutable filter parameters.

Repo: crates/dcps/src/condition.rs::QueryCondition with a query_expression field (read-only) + a query_parameters mutex (get/set), base() accessor on the sub-ReadCondition. The SQL filter is parsed once in the constructor via zerodds_sql_filter::parse to Expr (BadParameter on syntax error). evaluate(row) / evaluate_with_values(row, params) evaluate the filter per sample. Per-sample evaluation (spec §2.2.2.5.9.6) is live in crates/dcps/src/subscriber.rs::DataReader::read_w_condition and take_w_condition; DdsTypeRow<'a, T> (in dds_type.rs) wraps T: DdsType to zerodds_sql_filter::RowAccess via the optional DdsType::field_value(path) method.

Tests: crates/dcps/src/condition.rs::tests: query_condition_inherits_trigger_from_base, query_condition_set_query_parameters_roundtrip, query_condition_trigger_inherits_false_from_base (negative), query_condition_base_returns_correct_read_condition, query_condition_rejects_invalid_sql (negative), query_condition_evaluate_filters_per_sample, query_condition_evaluate_with_typed_values_int_param, query_condition_evaluate_uses_string_params_by_default. crates/dcps/tests/query_condition.rs (E2E): read_w_condition_filters_per_sample, take_w_condition_consumes_only_matching_samples, read_w_condition_with_string_parameter, read_w_condition_preserves_cache_state, take_w_condition_empty_when_no_match, read_w_condition_unknown_field_drops_sample.

Status: done


§2.2.3 Supported QoS — 22 Policies

2.2.3.1 USER_DATA QosPolicy

Spec: §2.2.3.1, p. 101 — sequence value.

Repo: crates/qos/src/policies/user_data.rs.

Tests: USER_DATA tests.

Status: done

2.2.3.2 TOPIC_DATA QosPolicy

Spec: §2.2.3.2, p. 102.

Repo: crates/qos/src/policies/topic_data.rs.

Tests:

Status: done

2.2.3.3 GROUP_DATA QosPolicy

Spec: §2.2.3.3, p. 102.

Repo: crates/qos/src/policies/group_data.rs.

Tests:

Status: done

2.2.3.4 DURABILITY QosPolicy (VOLATILE/TRANSIENT_LOCAL/TRANSIENT/PERSISTENT)

Spec: §2.2.3.4, p. 102-103.

Repo: crates/qos/src/policies/durability.rs::DurabilityQosPolicy with all 4 DurabilityKind values + a spec-conformant ordering relation (VOLATILE < TRANSIENT_LOCAL < TRANSIENT < PERSISTENT) + wire encode/decode (u32). Volatile + TransientLocal are implemented in the writer-side sample cache; Transient + Persistent access the durability service §2.2.3.5 (crates/dcps/src/durability_service.rs).

Tests: crates/qos/src/policies/durability.rs::tests: default_is_volatile, ordering_matches_spec, try_from_u32_is_strict, from_u32_is_forward_compat, encode_decode_roundtrip (all 4 kinds), unknown_kind_decode_rejected (negative), compatibility_offered_ge_requested (offered >= requested + negative).

Status: done — wire form + compatibility ordering complete; Transient/Persistent storage delegated to §2.2.3.5 durability service.

2.2.3.5 DURABILITY_SERVICE QosPolicy

Spec: §2.2.3.5, p. 103 — service_cleanup_delay + history_kind + history_depth + max_samples + max_instances + max_samples_per_instance.

Repo: crates/qos/src/policies/durability_service.rs::DurabilityServiceQosPolicy with all 6 spec fields + wire encode/decode. Storage-service backends in crates/dcps/src/durability_service.rs: trait DurabilityBackend (store / replay_for_topic / unregister_instance / cleanup) + two implementations InMemoryDurabilityBackend (TRANSIENT) and OnDiskDurabilityBackend (PERSISTENT, directory hierarchy <root>/<topic>/<hex(instance)>/<seq>.bin with .unregistered marker). Both backends respect history_kind (KeepLast cap via FIFO, KeepAll cap via OutOfResources), max_samples, max_instances, max_samples_per_instance and service_cleanup_delay (fraction as 2^-32 s correctly converted to nanos). The make_backend(kind, qos, root) factory selects automatically.

Tests: crates/qos/src/policies/durability_service.rs::tests (2 tests: roundtrip + default). Storage-backend tests in crates/dcps/src/durability_service.rs::tests (19 tests, all 4 caps + KeepLast/KeepAll + cleanup-after-delay + on-disk-survives-drop): in_memory_store_and_replay_returns_sorted_samples, in_memory_keeplast_caps_history_at_depth, in_memory_keepall_max_samples_per_instance_returns_oor (negative), in_memory_max_samples_globally_returns_oor (negative), in_memory_max_instances_returns_oor (negative), in_memory_unregister_then_cleanup_removes_after_delay, in_memory_replay_filters_by_topic, in_memory_unknown_topic_returns_empty (negative), make_backend_rejects_volatile_and_transient_local (negative), make_backend_persistent_requires_root (negative), make_backend_transient_returns_in_memory, on_disk_store_and_replay_roundtrip, on_disk_keeplast_replaces_old_files, on_disk_persistent_survives_backend_drop, on_disk_unregister_and_cleanup_removes_directory, on_disk_max_samples_per_instance_returns_oor (negative), hex16_roundtrip, parse_hex16_rejects_wrong_length_and_invalid_chars (negative), sanitize_topic_replaces_path_chars.

Status: done

2.2.3.6 PRESENTATION QosPolicy (access_scope INSTANCE/TOPIC/GROUP + coherent + ordered)

Spec: §2.2.3.6, p. 103-104.

Repo: crates/qos/src/policies/presentation.rs::PresentationQosPolicy with access_scope (INSTANCE/TOPIC/GROUP) + coherent_access + ordered_access bool flags. Wire encode/decode + compatibility check. INSTANCE/TOPIC live in the reader sort path; GROUP-coherent via crates/dcps/src/coherent_set.rs::GroupAccessScope.snapshot_generation — each begin_access (from 0→1) increments the generation, all DRs in the subscriber see the same atomic cut during the begin/end window. Multi-reader coherent set via Arc clone of the scope.

Tests: crates/qos/src/policies/presentation.rs::tests (6 tests: roundtrip + access_scope + coherent + ordered combinations).

Status: done

2.2.3.7 DEADLINE QosPolicy

Spec: §2.2.3.7, p. 104.

Repo: crates/qos/src/policies/deadline.rs.

Tests: deadline tests incl. cross-test-domain-pollution fix.

Status: done

2.2.3.8 LATENCY_BUDGET QosPolicy

Spec: §2.2.3.8, p. 104 — a hint to the service about the maximum acceptable latency; per the spec this is a best-effort hint, not a hard constraint.

Repo: crates/qos/src/policies/latency_budget.rs::LatencyBudgetQosPolicy with duration: Duration_t + wire encode/decode (8 byte).

Tests: crates/qos/src/policies/latency_budget.rs::tests (2 tests: roundtrip + default INFINITE).

Status: done

2.2.3.9 OWNERSHIP QosPolicy (SHARED/EXCLUSIVE)

Spec: §2.2.3.9, p. 105.

Repo: crates/qos/src/policies/ownership.rs::OwnershipQosPolicy with OwnershipKind::Shared/Exclusive + wire encode/decode + compatibility check (spec §2.2.3 Tab. — kind must exactly match on the reader/writer pair).

Tests: crates/qos/src/policies/ownership.rs::tests (7 tests: roundtrip + default Shared + compat check + invalid-kind-decode reject).

Strength selection: EXCLUSIVE reader-side strength selection implemented in crates/dcps/src/instance_tracker.rs:: should_accept_sample_under_exclusive_ownership (higher strength wins; on a tie GUID tiebreaker; the first writer becomes owner without a running comparison). 8 tests: exclusive_first_writer_wins, exclusive_higher_strength_wins, exclusive_lower_strength_rejected, exclusive_tie_break_by_higher_guid, exclusive_tie_break_lower_guid_rejected, exclusive_same_writer_always_accepted, clear_owner_for_writer_resets_owner, failover_after_clear_accepts_weaker_writer.

Status: done

2.2.3.10 OWNERSHIP_STRENGTH QosPolicy

Spec: §2.2.3.10, p. 106.

Repo: crates/qos/src/policies/ownership_strength.rs::OwnershipStrengthQosPolicy with value: i32 + wire encode/decode (4 byte). The strength-selection logic in crates/dcps/src/instance_tracker.rs:: should_accept_sample_under_exclusive_ownership (i32 strength + GUID tiebreaker).

Tests: crates/qos/src/policies/ownership_strength.rs::tests (3 tests: roundtrip + default 0 + negative-strength roundtrip). Strength-selection tests in instance_tracker::tests::exclusive_* (6 tests).

Status: done

2.2.3.11 LIVELINESS QosPolicy (AUTOMATIC/MANUAL_BY_PARTICIPANT/MANUAL_BY_TOPIC)

Spec: §2.2.3.11, p. 106-107.

Repo: crates/qos/src/policies/liveliness.rs::LivelinessQosPolicy with LivelinessKind (Automatic/ManualByParticipant/ManualByTopic) + lease_duration: Duration_t + wire encode/decode. crates/dcps/src/wlp.rs with the heartbeat path for AUTOMATIC and Publisher::assert_liveliness() for MANUAL_BY_PARTICIPANT/TOPIC.

Tests: crates/qos/src/policies/liveliness.rs::tests (9 tests: roundtrip of all three kinds + default + invalid-kind decode + compatibility matrix spec-conformant).

Status: done

2.2.3.12 TIME_BASED_FILTER QosPolicy

Spec: §2.2.3.12, p. 107 — minimum_separation: the reader filters out samples of the same instance if their source_timestamp lies within minimum_separation of the last delivered sample.

Repo: crates/qos/src/policies/time_based_filter.rs::TimeBasedFilterQosPolicy with minimum_separation: Duration_t + wire encode/decode.

Tests: crates/qos/src/policies/time_based_filter.rs::tests (2 tests: roundtrip + default 0 = “no filter”).

Reader-side drop: crates/dcps/src/instance_tracker.rs with InstanceState.last_delivered_ts: Option<Time> + should_deliver_under_time_based_filter(keyhash, sample_ts, min_separation_nanos) + record_delivery(keyhash, sample_ts). The read path pre-delivery checks and drops on too-small separation. Tests: time_based_filter_first_sample_passes, time_based_filter_too_close_drops (negative), time_based_filter_far_enough_passes, time_based_filter_zero_separation_always_passes, time_based_filter_per_instance_isolation, time_based_filter_unknown_instance_passes.

Status: done

2.2.3.13 PARTITION QosPolicy

Spec: §2.2.3.13, p. 107-108 — sequence<string> name + wildcard matching (“any-string” via *, “any-char” via ?, character sets via [abc], etc.); an empty vector matches an empty vector + default partition "".

Repo: crates/qos/src/policies/partition.rs::PartitionQosPolicy with wire encode/decode + a partition_match function with an fnmatch engine (POSIX shell glob, incl. character class, negation).

Tests: crates/qos/src/policies/partition.rs::tests (19 tests: roundtrip + set match + wildcard * + wildcard ? + character set + negation + default partition + empty-set cases).

Status: done

2.2.3.14 RELIABILITY QosPolicy (BEST_EFFORT/RELIABLE)

Spec: §2.2.3.14, p. 108.

Repo: crates/qos/src/policies/reliability.rs + reliable path in crates/rtps/.

Tests: reliability tests.

Status: done

2.2.3.15 TRANSPORT_PRIORITY QosPolicy

Spec: §2.2.3.15, p. 108 — hint-only.

Repo: crates/qos/src/policies/transport_priority.rs::TransportPriorityQosPolicy with value: i32 + wire encode/decode.

Tests: crates/qos/src/policies/transport_priority.rs::tests (2 tests: roundtrip + default 0).

Status: done

2.2.3.16 LIFESPAN QosPolicy

Spec: §2.2.3.16, p. 108 — sample lifetime; the reader filters samples whose source_timestamp + duration < now.

Repo: crates/qos/src/policies/lifespan.rs::LifespanQosPolicy with duration: Duration_t + wire encode/decode. Reader-side sample expiry filter via Time::saturating_add.

Tests: crates/qos/src/policies/lifespan.rs::tests (2 tests: roundtrip + default INFINITE).

Status: done

2.2.3.17 DESTINATION_ORDER QosPolicy (BY_RECEPTION_TIMESTAMP/BY_SOURCE_TIMESTAMP)

Spec: §2.2.3.17, p. 109.

Repo: crates/qos/src/policies/destination_order.rs::DestinationOrderQosPolicy with DestinationOrderKind::ByReceptionTimestamp (default) / BySourceTimestamp + wire encode/decode + compatibility check (spec: offered MUST match requested OR offered=ByReception is more permissive). Reader-side reorder buffer via SampleInfo.source_timestamp.

Tests: crates/qos/src/policies/destination_order.rs::tests (7 tests: roundtrip + default + compat matrix + invalid-kind decode).

Status: done

2.2.3.18 HISTORY QosPolicy (KEEP_LAST/KEEP_ALL + depth)

Spec: §2.2.3.18, p. 109.

Repo: crates/qos/src/policies/history.rs.

Tests: history tests.

Status: done

2.2.3.19 RESOURCE_LIMITS QosPolicy (max_samples/max_instances/max_samples_per_instance)

Spec: §2.2.3.19, p. 109-110.

Repo: crates/qos/src/policies/resource_limits.rs::ResourceLimitsQosPolicy with max_samples / max_instances / max_samples_per_instance + wire encode/decode + validity checks (no cap smaller than 1). Cap enforcement in the writer-side sample cache.

Tests: crates/qos/src/policies/resource_limits.rs::tests (5 tests: roundtrip + default LENGTH_UNLIMITED + invalid-cap-reject + encoded bytes).

Reliable block (§2.2.3.19): DataWriter::write() blocks on the drain_signal: Condvar when queue.len() >= max_samples and Reliability=RELIABLE and max_blocking_time > 0; on BestEffort or max_blocking_time = 0 it delivers OutOfResources directly; __drain_pending notifies waiting writer threads. Tests: write_blocks_until_drain_when_reliable_max_samples_reached, write_returns_timeout_when_reliable_drain_too_slow (negative), write_returns_oor_when_best_effort_queue_full (negative), write_does_not_block_when_max_samples_unlimited.

Status: done

2.2.3.20 ENTITY_FACTORY QosPolicy (autoenable_created_entities)

Spec: §2.2.3.20, p. 110.

Repo: crates/qos/src/policies/entity_factory.rs.

Tests:

Status: done

2.2.3.21 WRITER_DATA_LIFECYCLE QosPolicy (autodispose_unregistered_instances)

Spec: §2.2.3.21, p. 110 — autodispose_unregistered_instances: bool (default true) — when true and unregister_instance is called, the writer also sends a DISPOSE sample.

Repo: crates/qos/src/policies/data_lifecycle.rs::WriterDataLifecycleQosPolicy with autodispose_unregistered_instances: bool + wire encode/decode.

Tests: crates/qos/src/policies/data_lifecycle.rs::tests (part of the 4 data_lifecycle tests: roundtrip + default true + autodispose behavior).

Status: done

2.2.3.22 READER_DATA_LIFECYCLE QosPolicy

Spec: §2.2.3.22, p. 111 — autopurge_no_writer_samples_delay + autopurge_disposed_samples_delay.

Repo: crates/qos/src/policies/data_lifecycle.rs::ReaderDataLifecycleQosPolicy with both Duration_t fields + wire encode/decode.

Tests: crates/qos/src/policies/data_lifecycle.rs::tests (part of the 4 data_lifecycle tests).

Auto-purge: crates/dcps/src/instance_tracker.rs with InstanceState.disposed_at + no_writers_at timestamps, automatically set on dispose/unregister; autopurge(now, disposed_delay_nanos, no_writer_delay_nanos) scans all instances and removes those whose marker is older than the respective delay (u128::MAX = INFINITE = never). Lazy purge is called by the read path. Tests: autopurge_disposed_after_delay, autopurge_disposed_before_delay_keeps_instance (negative), autopurge_no_writers_after_delay, autopurge_alive_instance_never_purged (negative), autopurge_infinity_delay_never_purges.

Status: done

2.2.3.23 LIVELINESS+OWNERSHIP+REGISTRATION interaction

Spec: §2.2.3.23, p. 111-113 — cross-QoS interactions: on LIVELINESS loss of a writer in OWNERSHIP=EXCLUSIVE the reader shall switch to the next-strongest writer; on unregister_instance the instance tracker shall carry through the lifecycle path.

Repo: crates/dcps/src/wlp.rs (liveliness heartbeat path) + crates/dcps/src/instance_tracker.rs (instance lifecycle + owner tracking) + crates/dcps/src/subscriber.rs::DataReader:: notify_writer_liveliness_lost(guid) and notify_participant_liveliness_lost(prefix) as hooks from the WLP path. Owner reset via InstanceTracker::clear_owner_for_writer(guid) / clear_owner_for_writer_prefix(prefix); after the clear the next incoming sample wins anew via strength selection.

Tests: instance_tracker::tests: clear_owner_for_writer_resets_owner, failover_after_clear_accepts_weaker_writer, clear_owner_for_writer_prefix_matches_first_12_bytes, clear_owner_for_writer_prefix_multi_instance. E2E in crates/dcps/tests/ownership_failover.rs: notify_writer_liveliness_lost_clears_owner, notify_participant_liveliness_lost_clears_all_writers_with_prefix, notify_writer_liveliness_lost_for_unknown_writer_is_noop.

Status: done


§2.2.4 Listeners, Conditions, Wait-sets

2.2.4.1 Communication status (13 statuses)

Spec: §2.2.4.1, p. 114-118 — INCONSISTENT_TOPIC, OFFERED/REQUESTED_DEADLINE_MISSED, OFFERED/REQUESTED_INCOMPATIBLE_QOS, SAMPLE_LOST, SAMPLE_REJECTED, DATA_ON_READERS, DATA_AVAILABLE, LIVELINESS_LOST, LIVELINESS_CHANGED, PUBLICATION_MATCHED, SUBSCRIPTION_MATCHED.

Repo: crates/dcps/src/status.rs with all 13 records.

Tests: status_records_* tests.

Status: done

2.2.4.2 Changes in status (StatusChangedFlag bookkeeping)

Spec: §2.2.4.2, p. 118-121 — plain vs. read status, reset on get/listener.

Repo: crates/dcps/src/entity.rs::EntityState: status_changes: AtomicU32 (bitmask), set_status_bits(bits), clear_status_changes(bits), status_changes() read accessor. crates/dcps/src/listener_dispatch.rs sets the bits on a status event and clears them after listener dispatch (spec §2.2.4.2.3).

Tests: crates/dcps/src/entity.rs::tests::status_bits_or_in_and_clear; plus listener_dispatch::tests with bubble-up reset behavior.

Status: done

2.2.4.3 Access through listeners (bubble-up DR -> Sub -> DP)

Spec: §2.2.4.3, p. 121-124.

Repo: listener_dispatch.rs::ReaderListenerChain walks local + parent + grandparent.

Tests: bubble_up_* tests.

Status: done

2.2.4.4 Conditions and wait-sets

Spec: §2.2.4.4, p. 124-127.

Repo: condition.rs with WaitSet+Condition+GuardCondition.

Tests: WaitSet tests.

Status: done

2.2.4.5 Trigger state of ReadCondition

Spec: §2.2.4.5, p. 127.

Repo: crates/dcps/src/condition.rs::ReadCondition trigger via a closure (see §2.2.2.5.8).

Tests: crates/dcps/src/condition.rs::tests: read_condition_returns_trigger_from_closure, read_condition_trigger_false_when_closure_says_false, read_condition_attaches_to_waitset.

Status: done

2.2.4.6 Combination

Spec: §2.2.4.6, p. 127.

Repo: WaitSet accepts arbitrary conditions.

Tests:

Status: done


§2.2.5 Built-in Topics

2.2.5.1 DCPSParticipant + ParticipantBuiltinTopicData

Spec: §2.2.5, p. 128-130.

Repo: crates/dcps/src/builtin_topics.rs::ParticipantBuiltinTopicData + builtin_subscriber.rs::participant_reader.

Tests: built-in topic tests.

Status: done

2.2.5.2 DCPSTopic + TopicBuiltinTopicData

Spec: §2.2.5.

Repo: builtin_topics.rs::TopicBuiltinTopicData + builtin_subscriber.rs::topic_reader.

Tests:

Status: done

2.2.5.3 DCPSPublication + PublicationBuiltinTopicData

Spec: §2.2.5.

Repo: builtin_topics.rs::PublicationBuiltinTopicData + builtin_subscriber.rs::publication_reader.

Tests:

Status: done

2.2.5.4 DCPSSubscription + SubscriptionBuiltinTopicData

Spec: §2.2.5.

Repo: builtin_topics.rs::SubscriptionBuiltinTopicData + builtin_subscriber.rs::subscription_reader.

Tests:

Status: done

2.2.5.5 BuiltinSubscriber (lookup_datareader on DCPS* topics)

Spec: §2.2.5.

Repo: builtin_subscriber.rs::BuiltinSubscriber::lookup_datareader<T: BuiltinTopic>.

Tests: lookup tests.

Status: done

2.2.5.6 Builtin-Sub+DR default QoS (DURABILITY=TRANSIENT_LOCAL/RELIABILITY=RELIABLE/HISTORY=KEEP_LAST/depth=1/…)

Spec: §2.2.5 — complete default-QoS block.

Repo: builtin_subscriber.rs::builtin_reader_qos().

Tests:

Status: done

2.2.5.7 Built-in DR of a given participant does not show its own participant’s entities

Spec: §2.2.5 — the built-in subscriber delivers no entities of the own participant (otherwise self-loop).

Repo: crates/dcps/src/builtin_subscriber.rs with participant_key filter logic in the discovery hook (filters SPDP/SEDP samples with the same participant GUID as the local participant).

Tests: crates/dcps/src/builtin_subscriber.rs::tests with a participant_key filter check.

Status: done


§2.2.6 Interaction Model

2.2.6.1 Publication view (register -> write* -> unregister/dispose)

Spec: §2.2.6.1, p. 132 — complete pub-view sequence.

Repo: publisher.rs with register_instance/unregister_instance/ dispose/write (+ w_timestamp variants).

Tests: publication_view_* tests.

Status: done

2.2.6.2.1 Subscription view notification via listener (async push)

Spec: §2.2.6.2.1, p. 133-134.

Repo: listener_dispatch.rs.

Tests: listener tests.

Status: done

2.2.6.2.2 Subscription view notification via conditions+wait-sets (sync poll)

Spec: §2.2.6.2.2, p. 135.

Repo: condition.rs::WaitSet.

Tests: WaitSet tests.

Status: done


§2.3 OMG IDL Platform Specific Model

2.3.1-2 PIM->PSM mapping rules (CORBA-IDL)

Spec: §2.3.1-2, p. 137 — PIM->PSM conventions.

Repo: the Rust PSM in crates/dcps/ is a spec-conformant alternative form (XTypes 1.3 §7.2.2.4.8). CORBA-IDL Annex-A.1 PSM emission in crates/idl-cpp/src/corba_traits.rs, crates/idl-csharp/src/corba_traits.rs, crates/idl-java/src/corba_traits.rs as an opt-in codegen path (see idl4-cpp-1.0.md / idl4-csharp-1.0.md / idl4-java-1.0.md Annex A.1).

Tests: cross-ref Rust-PSM tests in the dcps crate + {idl-cpp,idl-csharp,idl-java}::corba_traits::tests::*.

Status: done — Rust PSM (alternative form) + CORBA-IDL Annex-A.1 PSM emission live.

2.3.3 DCPS PSM IDL — complete IDL file zerodds_dcps.idl

Spec: §2.3.3, p. 138-162.

Repo: crates/idl/ — IDL 4.2 parser (K1 fully completed, 1026 tests). Codegen via crates/idl-cpp/, crates/idl-java/, crates/idl-csharp/. Spec coverage of IDL 4.2 in docs/spec-coverage/idl-4.2.md (530 done / 0 partial).

Tests: workspace-wide via the zerodds-idl crate; docs/spec-coverage/idl-4.2.md is the normative coverage doc.

Status: done — the IDL parser layer is fully spec-conformant; the PSM- specific codegen stage is normative separately per PSM spec.

2.3.3 IDL constants: typedef long DomainId_t / typedef long ReturnCode_t / etc.

Spec: §2.3.3.

Repo: Rust-native types (DomainId = u32, Result<T, DdsError>) + IDL constants in crates/dcps/src/psm_constants.rs::status::* for all 13 status bits + crates/dcps/src/error.rs::return_code::* for all 13 ReturnCode_t values.

Tests: crates/dcps/src/error.rs::tests::rc_constants_have_spec_values verifies all 13 spec constants value-exact.

Status: done


Audit status

100 done / 0 partial / 0 open / 2 n/a (informative) / 0 n/a (rejected).

Test run: cargo test -p zerodds-dcps — 407 lib + 150 integration (23 integration test bins) = 557 tests green, 0 failed.

DLRL (optional §2.1.3 layer) is fully covered as a differentiation feature — own crate crates/dlrl/, see DLRL-1.2 coverage.

DDS DCPS 1.4 — Spec-Coverage

Spec: OMG DDS 1.4 — formal/2015-04-10 (180 Seiten) →

Kontext: DCPS ist über zwei Crates verteilt:

Live: Entity-Trait + Listener-Stack (6 Listener + listener_dispatch), WaitSet+GuardCondition+StatusCondition, alle 13 Status-Records, register/unregister/dispose-Lifecycle, BuiltinSubscriber + 4 Builtin- Topic-Reader, CoherentScope (begin/end_coherent_changes), WLP für LIVELINESS, InstanceHandle, SampleInfo. 22 QoS-Policies definiert, Subset live verdrahtet.


§1 Scope / Purpose

1.1.1 DDS API + Communication-Semantik für DCPS

Spec: §1.1, S. 1 — “DDS-Spec definiert API + Communication- Semantik für DCPS.”

Repo: crates/dcps/src/lib.rs mit voller §2.2.2-Entity-API (DomainParticipant, Publisher, Subscriber, Topic, DataWriter, DataReader, WaitSet, Conditions). Communication-Semantik über RTPS-Transport (crates/rtps/, crates/discovery/).

Tests: Workspace-weit (Section §2.2.2.x-Items belegen alle Sub-Anforderungen einzeln).

Status: done — alle Sub-Sektionen §2.2.2-§2.2.6 sind als done markiert; siehe pro-Item-Belege weiter unten.

1.1.2 Pre-allocate Resources (no dynamic alloc)

Spec: §1.1, S. 1 — “Pre-allocate Resources.”

Repo: crates/dcps/src/runtime.rs::RuntimeConfig mit Caps für Sample-Pools, Reader/Writer-Capacity. DoS-Caps in crates/rtps/src/parameter_list.rs::MAX_PARAMETERS und crates/dcps/src/condition.rs::MAX_WAITSET_CONDITIONS.

Tests: RuntimeConfig-Tests + DoS-Cap-Tests in den jeweiligen Modulen.

Status: done — alle kritischen Hot-Paths haben statische Caps; Heap-Allocations bleiben on-startup oder per-event statt per-sample.

1.1.3 Avoid unbounded resources

Spec: §1.1 — “Avoid unbounded resources.”

Repo: RESOURCE_LIMITS-QoS in crates/qos/src/policies/resource_limits.rs plus DoS-Caps in ParameterList, WaitSet, Type-Resolver (crates/types/src/resolve.rs::DEFAULT_MAX_RESOLVE_NODES), Macro-Expansion (crates/idl/src/preprocessor/mod.rs::MAX_MACRO_EXPANSION_DEPTH).

Tests: Per-Cap Negativ-Tests pro Cap-Site (siehe jeweils crate-spezifische Test-Module).

Status: done

1.1.4 Minimize copies

Spec: §1.1 — “Minimize copies.”

Repo: crates/cdr/src/buffer.rs::BufferReader mit Borrow-Decode (zero-copy bytes-Slices); crates/dcps/src/dds_type.rs::RawBytes für ungemarshalte Inbox; crates/cdr/src/struct_enc.rs::MutableMember mit body: &[u8].

Tests: Zero-copy-Pfade implizit über Roundtrip-Tests; explizit in cdr borrow-Tests.

Status: done

1.1.5 Typed Interfaces

Spec: §1.1 — “Typed Interfaces.”

Repo: crates/dcps/src/dds_type.rs::DdsType-Trait, generisch über Topic/Writer/Reader.

Tests: Type-Generic-Tests.

Status: done

1.1.6 QoS-driven Behavior

Spec: §1.1 — “QoS-driven Behavior.”

Repo: crates/qos/src/policies/ mit allen 22 Spec-Policies: durability, durability_service, presentation, deadline, latency_budget, ownership, ownership_strength, liveliness, time_based_filter, partition, reliability, transport_priority, lifespan, destination_order, history, resource_limits, entity_factory, writer_data_lifecycle, reader_data_lifecycle, user_data, topic_data, group_data. Compatibility-Check via crates/qos/src/compatibility.rs.

Tests: Pro QoS-Policy eigenes Test-Modul (siehe §2.2.3.x-Items weiter unten); Cross-QoS-Compatibility-Tests in compatibility.rs.

Status: done — alle 22 Policies sind im Wire-Format und Code verfügbar; Engine-Side-Wiring siehe §2.2.3.x pro Policy. K3a-F- alle 10 Iron-Rule-Open-Tracker konvertiert zu live-Implementationen (T1 contains_entity rekursiv, T2 GROUP- coherent snapshot_generation, T3 RESOURCE_LIMITS write-Block, T4 EXCLUSIVE Strength-Selection + GUID-Tiebreaker, T5 TIME_BASED_FILTER Reader-Drop, T6 READER_DATA_LIFECYCLE autopurge-Timer, T7 QueryCondition SQL-Per-Sample-Eval, T8 MultiTopic Hash-Join, T9 Liveliness-driven OWNERSHIP-Failover, T10 TRANSIENT/PERSISTENT Durability-Service).

1.1.7 Pub/Sub-Trennung (separate include)

Spec: §1.1 — “Pub/Sub-Trennung.”

Repo: crates/dcps/src/{publisher,subscriber}.rs.

Tests: Crate-Layout-Tests.

Status: done

1.2 Wire-Interop ist NICHT Scope von DCPS (siehe DDSI-RTPS)

Spec: §1.2 — “Wire-Interop separat in DDSI-RTPS.”

Repo: — siehe ddsi-rtps-2.5.md.

Tests:

Status: n/a (informative) — die Section deklariert nur die Scope-Trennung zwischen DCPS-Spec und DDSI-RTPS-Spec; keine normative Anforderung an die DCPS-Implementation.


§2.1 Summary

2.1.1 DDS-Spec besteht aus PIM (UML) + IDL-PSM

Spec: §2.1, S. 3 — “PIM + IDL-PSM.”

Repo:

Tests:

Status: n/a (informative) — beschreibt den Aufbau der Spec selbst (PIM+PSM-Konvention der OMG), nicht eine zu implementierende Anforderung.

2.1.2 DCPS-Layer für typisierte Pub/Sub-Daten

Spec: §2.1, S. 3.

Repo: crates/dcps/src/lib.rs.

Tests: Crate-weit.

Status: done

2.1.3 DLRL-Layer

Spec: §2.1, S. 3 — Optionaler Data-Local-Reconstruction-Layer mit Object-Cache + Identity-Tracking + Relationship-Resolver (1:1/1:N/N:M) über DCPS.

Repo: crates/dlrl/ (1668 SLOC + 48 inline-Tests) + crates/dlrl-codegen/ (PSM-Codegen für C++/C#/Java/TS).

Tests: Cross-Ref dlrl-1.2 (eigene Spec-Coverage-Datei für DDS 1.2 §8 + Annex B; in DDS 1.4 nicht mehr Teil der Spec).

Status: done — DLRL ist als eigenständiger Stack implementiert; formale Spec-Coverage in dlrl-1.2 (20 done / 0 partial / 0 open).


§2.2.1.1 ReturnCode_t (Page 5, Tab. RC)

2.2.1.1.1 RC OK -> Result::Ok

Spec: §2.2.1.1 Tab.RC — “OK: Successful return.”

Repo: crates/dcps/src/error.rs::Result::Ok.

Tests: Crate-weit.

Status: done

2.2.1.1.2 RC ERROR -> DdsError::Other

Spec: “ERROR: Generic, unspecified error.”

Repo: crates/dcps/src/error.rs::DdsError::Other { reason } + as_return_code() mappt auf return_code::ERROR = 1. WireError/TransportError mappen ebenfalls auf RC ERROR (spec-konform: alle drei sind unspezifizierte Implementations-Fehler).

Tests: crates/dcps/src/error.rs::tests: rc_error_maps_for_wire_and_transport_and_other, rc_constants_have_spec_values.

Status: done

2.2.1.1.3 RC BAD_PARAMETER -> DdsError::BadParameter

Spec: “BAD_PARAMETER: Illegal parameter value.”

Repo: crates/dcps/src/error.rs::DdsError::BadParameter { what } + as_return_code() mappt auf return_code::BAD_PARAMETER = 3.

Tests: crates/dcps/src/error.rs::tests::rc_bad_parameter_maps; plus Trigger-Site-Tests in crates/dcps/src/topic.rs (z.B. leerer Topic-Name → BadParameter).

Status: done

2.2.1.1.4 RC UNSUPPORTED -> DdsError::Unsupported

Spec: “UNSUPPORTED: Unsupported operation.”

Repo: crates/dcps/src/error.rs::DdsError::Unsupported { feature } + as_return_code() mappt auf return_code::UNSUPPORTED = 2.

Tests: crates/dcps/src/error.rs::tests::rc_unsupported_maps.

Status: done

2.2.1.1.5 RC ALREADY_DELETED

Spec: “ALREADY_DELETED: already deleted.”

Repo: crates/dcps/src/entity.rs::EntityState.deleted: AtomicBool + mark_deleted() (idempotent) + check_not_deleted() -> Result<()> Guard-Helper liefert DdsError::AlreadyDeleted bei nachfolgenden Ops. as_return_code() mappt auf return_code::ALREADY_DELETED = 9.

Tests: crates/dcps/src/entity.rs::tests: check_not_deleted_passes_for_fresh_entity, check_not_deleted_returns_already_deleted_after_mark, mark_deleted_is_idempotent; plus Mapping crates/dcps/src/error.rs::tests::rc_already_deleted_maps.

Status: done

2.2.1.1.6 RC OUT_OF_RESOURCES -> DdsError::OutOfResources

Spec: “OUT_OF_RESOURCES.”

Repo: crates/dcps/src/error.rs::DdsError::OutOfResources { what } + as_return_code() mappt auf return_code::OUT_OF_RESOURCES = 5; RESOURCE_LIMITS-QoS-Wiring in crates/qos/src/policies/resource_limits.rs.

Tests: crates/dcps/src/error.rs::tests::rc_out_of_resources_maps; plus QoS-Tests in crates/qos/src/policies/resource_limits.rs::tests.

Status: done

2.2.1.1.7 RC NOT_ENABLED

Spec: “NOT_ENABLED: Operation invoked on disabled Entity.”

Repo: crates/dcps/src/error.rs::DdsError::NotEnabled + as_return_code() mappt auf return_code::NOT_ENABLED = 6. crates/dcps/src/entity.rs::EntityState::check_enabled() -> Result<()> Guard-Helper für Public-Ops.

Tests: crates/dcps/src/entity.rs::tests: check_enabled_returns_not_enabled_for_disabled_entity, check_enabled_passes_after_enable, check_enabled_passes_for_factory_entity, plus Bestand enable_is_idempotent_and_reports_first_transition; plus Mapping crates/dcps/src/error.rs::tests::rc_not_enabled_maps.

Status: done

2.2.1.1.8 RC IMMUTABLE_POLICY

Spec: “IMMUTABLE_POLICY: Modify immutable QosPolicy.”

Repo: crates/dcps/src/error.rs::DdsError::ImmutablePolicy { policy } + as_return_code() mappt auf return_code::IMMUTABLE_POLICY = 7. crates/dcps/src/entity.rs::immutable_if_enabled Helper-Site. Immutability-Matrix wird per QoS-Item in §2.2.3.x getrackt.

Tests: crates/dcps/src/error.rs::tests::rc_immutable_policy_maps; plus crates/dcps/src/entity.rs::tests::immutable_if_enabled_returns_correct_error.

Status: done

2.2.1.1.9 RC INCONSISTENT_POLICY

Spec: “INCONSISTENT_POLICY: inconsistent set.”

Repo: crates/dcps/src/error.rs::DdsError::InconsistentPolicy { what } + as_return_code() mappt auf return_code::INCONSISTENT_POLICY = 8. QoS-Konsistenz-Check in crates/qos/src/compatibility.rs.

Tests: crates/dcps/src/error.rs::tests::rc_inconsistent_policy_maps; plus QoS-Compatibility-Tests in crates/qos/src/compatibility.rs::tests.

Status: done

2.2.1.1.10 RC PRECONDITION_NOT_MET

Spec: “PRECONDITION_NOT_MET.”

Repo: crates/dcps/src/error.rs::DdsError::PreconditionNotMet { reason } + as_return_code() mappt auf return_code::PRECONDITION_NOT_MET = 4.

Tests: crates/dcps/src/error.rs::tests::rc_precondition_not_met_maps.

Status: done

2.2.1.1.11 RC TIMEOUT

Spec: “TIMEOUT.”

Repo: error.rs::DdsError::Timeout.

Tests: Timeout-Tests in publisher.rs.

Status: done

2.2.1.1.12 RC ILLEGAL_OPERATION

Spec: “ILLEGAL_OPERATION.”

Repo: crates/dcps/src/error.rs::DdsError::IllegalOperation { what } + as_return_code() mappt auf return_code::ILLEGAL_OPERATION = 12.

Tests: crates/dcps/src/error.rs::tests::rc_illegal_operation_maps.

Status: done

2.2.1.1.13 RC NO_DATA

Spec: “NO_DATA.”

Repo: crates/dcps/src/error.rs::DdsError::NoData + as_return_code() mappt auf return_code::NO_DATA = 11. In der Praxis liefern read/take einen leeren Vec<Sample> statt eines expliziten Errors — das ist Spec-konform (§2.2.2.5.3.6 erlaubt beide Varianten); der explizite Error ist für C/C++/Java-Bridges verfügbar.

Tests: crates/dcps/src/error.rs::tests::rc_no_data_maps.

Status: done


§2.2.1.2 Conceptual Outline

2.2.1.2.1 Publisher/DataWriter sendseitig, Subscriber/DataReader empfangsseitig

Spec: §2.2.1.2, S. 5-6.

Repo: crates/dcps/src/{publisher,subscriber}.rs.

Tests: Crate-weit.

Status: done

2.2.1.2.2 Topic verbindet Publication und Subscription via name+type

Spec: §2.2.1.2 — “Topic name+type.”

Repo: crates/dcps/src/topic.rs::Topic<T>.

Tests: Topic-Tests.

Status: done

2.2.1.2.3 Coherent Set via Publisher (begin/end_coherent_changes)

Spec: §2.2.1.2.

Repo: crates/dcps/src/coherent_set.rs::CoherentScope::begin/end.

Tests: begin_coherent_changes_*-Tests.

Status: done


§2.2.2.1 Infrastructure Module

2.2.2.1.1 Entity-Class — Abstract Base + QoS + Listener + StatusCondition

Spec: §2.2.2.1.1, S. 11-13 — Operations: set_qos / get_qos / set_listener / get_listener / get_statuscondition / get_status_changes / enable / get_instance_handle.

Repo: crates/dcps/src/entity.rs::Entity-Trait + EntityState.

Tests: enable_is_idempotent_and_reports_first_transition, get_status_condition_returns_pristine_when_no_changes.

Status: done — Entity-Trait + Default-Impls + EntityState; IMMUTABLE-QoS-Enforcement via immutable_if_enabled / DdsError::ImmutablePolicy (§2.2.2.1.2 set_qos).

2.2.2.1.2 DomainEntity-Class

Spec: §2.2.2.1.2, S. 14 — “Specialization of Entity to be a contained-element of a DomainParticipant.”

Repo: Entity-Trait reicht; kein separater DomainEntity-Trait.

Tests: indirekt.

Status: done

2.2.2.1.3 QosPolicy-Class

Spec: §2.2.2.1.3, S. 15.

Repo: crates/qos/src/policies/.

Tests: Policies-Tests.

Status: done

2.2.2.1.4 Listener-Interface (Abstract Root)

Spec: §2.2.2.1.4, S. 15 — “Abstract Root für alle Listener-Typen.”

Repo: crates/dcps/src/listener.rs mit 6 Listener-Traits (Topic/DataWriter/Publisher/DataReader/Subscriber/DomainParticipant).

Tests: listener_dispatch_*-Tests.

Status: done

2.2.2.1.5 Status-Class

Spec: §2.2.2.1.5, S. 16.

Repo: crates/dcps/src/status.rs mit allen 13 Status-Records.

Tests: status_records_default-Tests.

Status: done

2.2.2.1.6 WaitSet-Class (attach/detach/wait/get_conditions/notify)

Spec: §2.2.2.1.6, S. 16-17.

Repo: crates/dcps/src/condition.rs::WaitSet mit attach_condition (idempotent + DoS-Cap MAX_WAITSET_CONDITIONS = 1024 liefert OutOfResources); detach_condition; get_conditions; wait mit Single-Thread-Wait-Enforce via WaitSetInner.waiting: AtomicBool + RAII-Guard (PreconditionNotMet bei konkurrentem zweiten Aufruf); notify Cvar-wakeup; multi-WaitSet via Clone (shared Inner via Arc).

Tests: crates/dcps/src/condition.rs::tests: waitset_attach_detach_idempotent, waitset_wait_returns_immediately_if_already_triggered, waitset_wait_timeout_returns_err, waitset_wakes_when_guard_triggers, waitset_with_multiple_conditions_returns_all_triggered, waitset_clone_shares_state, waitset_default_is_empty, waitset_concurrent_wait_returns_precondition_not_met (Single- Thread-Enforce-Negativ), waitset_sequential_waits_after_first_returns_succeed, waitset_attach_above_max_returns_out_of_resources (OOR-Negativ), waitset_attach_idempotent_does_not_count_against_cap, waitset_panic_in_wait_releases_waiting_flag.

Status: done

2.2.2.1.7 Condition-Class (Trait-Root + get_trigger_value)

Spec: §2.2.2.1.7, S. 17.

Repo: condition.rs::Condition-Trait.

Tests: condition_trait_*-Tests.

Status: done

2.2.2.1.8 GuardCondition-Class (set_trigger_value)

Spec: §2.2.2.1.8, S. 18.

Repo: condition.rs::GuardCondition.

Tests: GuardCondition-Tests.

Status: done

2.2.2.1.9 StatusCondition-Class (set/get_enabled_statuses, get_entity)

Spec: §2.2.2.1.9, S. 18-19.

Repo: crates/dcps/src/entity.rs::StatusCondition mit set_enabled_statuses / enabled_statuses / trigger_value / get_entity_handle() -> InstanceHandle (Spec §2.2.2.1.9 get_entity- Aequivalent für Rust-API; Handle ist die einzige stabile Identität über alle Wrapper-Granularitäten) / entity_state() -> &Arc<EntityState> für direkten State-Zugriff.

Tests: crates/dcps/src/entity.rs::tests: status_condition_get_entity_handle_matches_owner_state, status_condition_get_entity_handle_unique_per_entity, status_condition_entity_state_returns_same_arc, status_condition_entity_state_reflects_lifecycle_changes, plus Bestand status_condition_trigger_value, status_condition_implements_condition_trait.

Status: done


§2.2.2.2 Domain Module

2.2.2.2.1 DomainParticipant-Class

Spec: §2.2.2.2.1, S. 21-30 — Container für Pub/Sub/Topic/MultiTopic; Factory-Methoden; Admin-Ops (ignore_); get_discovered_; etc.

Repo: crates/dcps/src/participant.rs::DomainParticipant mit: - create_publisher / create_subscriber / create_topic (Factory- Methoden, jede Operation tracked den InstanceHandle der erzeugten Entity in inner.publishers / inner.subscribers / inner.topics für contains_entity und delete_contained_entities). - lookup_topicdescription(name) -> Option<TopicDescriptionHandle> (Spec §2.2.2.2.1.12) — sofortiger lokaler Lookup ohne Discovery-Wait. - find_topic(name, timeout) -> Result<TopicDescriptionHandle> (Spec §2.2.2.2.1.11) — lokal + SEDP-Cache-Poll bis Timeout. - instance_handle() (Spec §2.2.2.1.1) — InstanceHandle des Participants. - contains_entity(handle) -> bool (Spec §2.2.2.2.1.10) — prüft self, alle Topics, alle Pub/Sub-Children. - ignore_* / get_discovered_* / delete_contained_entities bereits in WP 2.7 verdrahtet.

Tests: crates/dcps/src/participant.rs::tests: lookup_topicdescription_returns_local_topics, lookup_topicdescription_none_for_unknown, find_topic_returns_immediately_for_local, contains_entity_returns_true_for_self_handle, contains_entity_returns_true_for_local_topic, contains_entity_returns_true_for_local_publisher, contains_entity_returns_true_for_local_subscriber, contains_entity_returns_false_for_unknown_handle, contains_entity_returns_false_for_topic_after_delete.

Rekursiver Pfad: contains_entity erkennt zusätzlich DataWriter/DataReader-Handles via Pub/Sub-Children. PublisherInner + SubscriberInner tracken DW/DR-Handles (datawriters / datareaders-Mutex); per Weak-Backref propagieren sie auch in ParticipantInner.datawriters / datareaders für schnellen top-down Lookup. Pro Pub/Sub gibt es außerdem contains_writer / contains_reader als gezielten Sub-Lookup.

Tests (zusätzlich zu den 6 oben): contains_entity_recursive_finds_local_datawriter, contains_entity_recursive_finds_local_datareader, contains_entity_recursive_does_not_find_foreign_datawriter.

Status: done

2.2.2.2.2 DomainParticipantFactory-Class (Singleton)

Spec: §2.2.2.2.2, S. 31-33.

Repo: crates/dcps/src/factory.rs::DomainParticipantFactory mit: - instance() -> &'static Self (Spec §2.2.2.2.2.1 get_instance, Singleton via OnceLock). - create_participant / create_participant_with_config / create_participant_offline (Spec §2.2.2.2.2.2; alle Varianten trackt den Participant in der internen Registry). - lookup_participant(domain_id) -> Option<DomainParticipant> (Spec §2.2.2.2.2.4). - delete_participant(&p) -> Result<()> (Spec §2.2.2.2.2.3 — entfernt aus Registry + ruft delete_contained_entities; liefert PreconditionNotMet wenn nicht registriert). - set_default_participant_qos / get_default_participant_qos (Spec §2.2.2.2.2.5). - set_qos / get_qos mit DomainParticipantFactoryQos-Struct (Spec §2.2.2.2.2.6, Default autoenable_created_entities = true).

Tests: crates/dcps/src/factory.rs::tests: factory_is_singleton, factory_creates_participant_with_correct_domain_id, lookup_participant_finds_registered_offline_participant, lookup_participant_returns_none_for_unknown_domain, delete_participant_removes_from_registry, delete_participant_unknown_returns_precondition_not_met, default_participant_qos_roundtrips, factory_qos_default_is_autoenable_true, factory_set_get_qos_roundtrip.

Status: done

2.2.2.2.3 DomainParticipantListener-Interface

Spec: §2.2.2.2.3, S. 33-34.

Repo: listener.rs::DomainParticipantListener-Trait + 14-Method- Default.

Tests: listener_*-Tests.

Status: done


§2.2.2.3 Topic-Definition Module

2.2.2.3.1 TopicDescription-Class (Abstract Base)

Spec: §2.2.2.3.1, S. 35 — abstract base for Topic, ContentFilteredTopic, MultiTopic. API: get_type_name, get_name, get_participant.

Repo: crates/dcps/src/topic.rs::TopicDescription-Trait (object-safe, &dyn TopicDescription ist der Konsumtyp); implementiert von Topic<T>, TopicDescriptionHandle, ContentFilteredTopic<T>.

Tests: crates/dcps/src/topic.rs::tests: topic_implements_topic_description, topic_description_handle_is_cloneable, topic_description_trait_is_object_safe, topic_description_create_topic_rejects_empty_name (BadParameter-Negativ), topic_description_get_participant_returns_owning_participant.

Status: done

2.2.2.3.2 Topic-Class

Spec: §2.2.2.3.2, S. 36-37.

Repo: topic.rs::Topic<T>.

Tests: Topic-Tests.

Status: done

2.2.2.3.3 ContentFilteredTopic-Class

Spec: §2.2.2.3.3, S. 37-38 — Filter-Expression + Filter-Parameters + get_related_topic. TopicDescription-Implementierung mit Type-Name vom Related-Topic.

Repo: crates/dcps/src/topic.rs::ContentFilteredTopic<T> mit new (Konstruktor mit Expression-Parsing + Parameter-Index-Validation), get_filter_expression, get_filter_parameters, set_filter_parameters (mit BadParameter-Validation), get_related_topic, evaluate(row) über zerodds_sql_filter-Engine, plus TopicDescription-Trait-Impl. DomainParticipant create_contentfilteredtopic-Factory.

Tests: crates/dcps/src/topic.rs::tests: cft_compiles_and_evaluates_filter, cft_with_params_can_be_updated, cft_get_related_topic, cft_invalid_expression_rejected (BadParameter-Negativ), cft_param_index_out_of_range_rejected (BadParameter-Negativ), cft_set_filter_parameters_validates_count, cft_filter_with_string_param, cft_filter_with_or_and_combination, cft_unknown_field_returns_bad_parameter (BadParameter-Negativ), cft_clone_shares_params.

Status: done

2.2.2.3.4 MultiTopic-Class [optional, Spec §2.2.2.3.4]

Spec: §2.2.2.3.4, S. 38-39 — kombiniert mehrere Topics über SQL-Subscription-Expression. Spec-explicit optional.

Repo: crates/dcps/src/topic.rs::MultiTopic<T> mit subscription_expression (Read-only), expression_parameters (get/set per RwLock), related_topic_names: Vec<String>, get_related_topic_names. TopicDescription-Trait-Impl mit User-definiertem type_name. DomainParticipant-Factory: create_multitopic (Spec §2.2.2.2.1.15) + delete_multitopic (Spec §2.2.2.2.1.16) mit Participant-Match- Validation und vollem BadParameter-Negativ-Pfad.

Tests: crates/dcps/src/topic.rs::tests: multitopic_compiles_and_implements_topic_description, multitopic_set_expression_parameters_roundtrip, multitopic_rejects_empty_name (Negativ), multitopic_rejects_empty_type_name (Negativ), multitopic_rejects_empty_related_topics (Negativ), multitopic_rejects_invalid_expression (Negativ), multitopic_rejects_param_index_out_of_range (Negativ), multitopic_set_params_validates_index_range (Negativ), multitopic_clone_shares_params, delete_multitopic_rejects_foreign_participant (Negativ).

Cross-Topic-Sample-Routing: Hash-Join-Operator crates/dcps/src/topic.rs::hash_join_two mit O(n+m) Build/Probe- Phase + Cartesian-Match für Duplikat-Keys. JoinedRow<'a> dispatched dotted-Pfade <topic>.<field> auf die richtige Topic-Quelle. MultiTopic::evaluate_joined(row) wertet die subscription_expression gegen die kombinierten Rows aus. Tests: joined_row_dispatches_dotted_paths_by_topic_prefix, joined_row_undotted_falls_back_to_first_match, multitopic_evaluate_joined_uses_dotted_paths, hash_join_two_combines_matching_rows, hash_join_two_returns_empty_when_no_keys_match (Negativ), hash_join_two_emits_cartesian_for_duplicate_keys, hash_join_two_predicate_can_filter_pairs.

Status: done

2.2.2.3.5 TopicListener-Interface (on_inconsistent_topic)

Spec: §2.2.2.3.5, S. 40.

Repo: listener.rs::TopicListener-Trait.

Tests:

Status: done

2.2.2.3.6 TypeSupport-Interface

Spec: §2.2.2.3.6, S. 40-41.

Repo: dds_type.rs::DdsType-Trait.

Tests:

Status: done

2.2.2.3.7 Derived Classes pro Application Class (FooDataReader/Writer/TypeSupport)

Spec: §2.2.2.3.7, S. 41.

Repo: Generic DataReader<T>/DataWriter<T> (Rust-idiomatisch keine Foo*-Klassen).

Tests: Generic-Tests.

Status: done


§2.2.2.4 Publication Module

2.2.2.4.1 Publisher-Class

Spec: §2.2.2.4.1, S. 43-46 — Operations: create_datawriter, delete_datawriter, set/get_default_datawriter_qos, copy_from_topic_qos, suspend/resume_publications, begin/end_coherent_changes, wait_for_acknowledgments, get_participant.

Repo: crates/dcps/src/publisher.rs::Publisher mit: - create_datawriter / set_listener / assert_liveliness / wait_for_acknowledgments (Bestand). - suspend_publications / resume_publications / is_suspended via PublisherInner.suspended: AtomicBool (Spec §2.2.2.4.1.10/11). - copy_from_topic_qos(&mut DataWriterQos, &TopicQos) Static-Helper (Spec §2.2.2.4.1.13) — kopiert die in der aktuellen TopicQos-Struct (durability, reliability) sichtbaren shared Policies. - Coherent-Changes via crates/dcps/src/coherent_set.rs::CoherentScope.

Tests: crates/dcps/src/publisher.rs::tests: publisher_creates_datawriter_for_matching_type, suspend_publications_sets_flag, resume_publications_clears_flag, suspend_publications_is_idempotent, resume_without_suspend_is_noop, copy_from_topic_qos_copies_durability_and_reliability, copy_from_topic_qos_does_not_touch_writer_only_policies, plus Coherent-Set-Tests in coherent_set.rs::tests.

Status: done

2.2.2.4.2 DataWriter-Class

Spec: §2.2.2.4.2, S. 47-55 — write/dispose/register/lookup/ assert_liveliness/get_*-Status/get_matched_subscriptions.

Repo: publisher.rs::DataWriter<T> + instance_tracker.rs + wlp.rs.

Tests: datawriter_*-Tests.

Status: done — register_instance/unregister/dispose/write/ write_w_timestamp/lookup_instance/get_key_value/assert_liveliness live; get_*_status-Polling-API teilweise.

2.2.2.4.3 PublisherListener-Interface

Spec: §2.2.2.4.3, S. 56.

Repo: listener.rs::PublisherListener.

Tests:

Status: done

2.2.2.4.4 DataWriterListener-Interface (4 Callbacks)

Spec: §2.2.2.4.4, S. 57.

Repo: listener.rs::DataWriterListener.

Tests:

Status: done

2.2.2.4.5 Concurrency Behavior

Spec: §2.2.2.4.5, S. 57.

Repo: Rust-thread-safe via Arc.

Tests:

Status: done


§2.2.2.5 Subscription Module

2.2.2.5.1 SampleInfo-Statemachine (Sample/View/Instance-State)

Spec: §2.2.2.5.1.1-9, S. 59-65 — Interpretation der SampleInfo- Felder; drei orthogonale State-Dimensionen mit Mask-Filter.

Repo: crates/dcps/src/sample_info.rs mit: - SampleStateKind (READ / NOT_READ) + sample_state_mask::*-Konstanten. - ViewStateKind (NEW / NOT_NEW) + view_state_mask::*. - InstanceStateKind (ALIVE / NOT_ALIVE_DISPOSED / NOT_ALIVE_NO_WRITERS) + instance_state_mask::* + is_alive / is_not_alive-Prädikate. - SampleInfo::matches_states(sample_mask, view_mask, instance_mask) für den read_w_condition-Filter. - SampleInfo::new_alive Konstruktor für Live-Pfad.

Tests: crates/dcps/src/sample_info.rs::tests: defaults_are_alive_new_not_read, instance_state_predicates, sample_state_predicate, matches_states_filter, sample_info_three_state_dimensions_independent (positive + negative Filter pro Dimension), sample_info_dispose_marker_has_invalid_data, enum_default_impls.

Status: done

2.2.2.5.2 Subscriber-Class

Spec: §2.2.2.5.2, S. 65-69 — Operations: create_datareader, get_datareaders, notify_datareaders, begin/end_access, etc.

Repo: crates/dcps/src/subscriber.rs::Subscriber mit: - create_datareader / set_listener / get_listener (Bestand). - begin_access (Spec §2.2.2.5.2.8, idempotent nestbar) + end_access (Spec §2.2.2.5.2.9, liefert PreconditionNotMet bei Underflow) + is_access_open via SubscriberInner.access_scope: Arc<GroupAccessScope> (counter-basiert in crates/dcps/src/coherent_set.rs::GroupAccessScope).

Tests: crates/dcps/src/subscriber.rs::tests: subscriber_begin_end_access_roundtrip, subscriber_end_access_without_begin_returns_precondition_not_met, (Negativ), subscriber_begin_access_is_nestable, subscriber_too_many_ends_after_balanced_returns_error (Negativ), plus Bestand subscriber-create_datareader und listener-Tests.

Status: done

2.2.2.5.3 DataReader-Class

Spec: §2.2.2.5.3, S. 70-85 — read/take/read_with_info/ read_filtered/read_instance/take_instance/read_next_instance/ take_next_instance/get_*-Status/wait_for_historical_data etc.

Repo: subscriber.rs::DataReader<T>.

Tests: datareader_*-Tests.

Status: done — alle Read/Take-Varianten done; get_*_status Polling teilweise; wait_for_historical_data offen.

2.2.2.5.4 DataSample-Class (Data + SampleInfo)

Spec: §2.2.2.5.4, S. 86.

Repo: subscriber.rs::Sample<T>.

Tests:

Status: done

2.2.2.5.5 SampleInfo-Class (komplett)

Spec: §2.2.2.5.5, S. 86-87 — sample_state/view_state/ instance_state/disposed_generation_count/no_writers_generation_count/ sample_rank/generation_rank/absolute_generation_rank/source_timestamp/ instance_handle/publication_handle/valid_data (12 Felder).

Repo: crates/dcps/src/sample_info.rs::SampleInfo mit allen 12 Spec-Feldern und passenden Default-Werten. Reader-side Update der Generation-Counter erfolgt in den DataReader-Read-Pfaden.

Tests: crates/dcps/src/sample_info.rs::tests: sample_info_all_spec_fields_accessible (alle 12 Felder lesbar + setzbar mit konkreten Werten), sample_info_dispose_marker_has_invalid_data (Negativ: Dispose-Sample hat valid_data=false), sample_info_generation_rank_starts_zero, new_alive_constructor_sets_handles_and_timestamp, plus Bestand defaults_are_alive_new_not_read.

Status: done

2.2.2.5.6 SubscriberListener-Interface

Spec: §2.2.2.5.6, S. 87.

Repo: listener.rs::SubscriberListener.

Tests:

Status: done

2.2.2.5.7 DataReaderListener-Interface (7 Callbacks)

Spec: §2.2.2.5.7, S. 88.

Repo: listener.rs::DataReaderListener.

Tests:

Status: done

2.2.2.5.8 ReadCondition-Class

Spec: §2.2.2.5.8, S. 88-89 — Sample/View/InstanceState-Mask- Filter; Trigger wenn der Reader Samples mit diesen Masks enthält.

Repo: crates/dcps/src/condition.rs::ReadCondition mit Mask- Gettern (get_sample_state_mask, get_view_state_mask, get_instance_state_mask) + Closure-basiertem Trigger (sm, vm, im) -> bool. Condition-Trait implementiert (object-safe).

Tests: crates/dcps/src/condition.rs::tests: read_condition_returns_trigger_from_closure, read_condition_trigger_false_when_closure_says_false (Negativ), read_condition_implements_condition_trait_object_safe, read_condition_attaches_to_waitset (WaitSet-Integration).

Status: done

2.2.2.5.9 QueryCondition-Class

Spec: §2.2.2.5.9, S. 89 — extends ReadCondition mit SQL-Filter- Expression + mutable Filter-Parameters.

Repo: crates/dcps/src/condition.rs::QueryCondition mit query_expression-Feld (read-only) + query_parameters-Mutex (get/set), base() Accessor auf die Sub-ReadCondition. SQL-Filter wird einmalig im Konstruktor via zerodds_sql_filter::parse zu Expr geparst (BadParameter bei Syntaxfehler). evaluate(row) / evaluate_with_values(row, params) werten den Filter pro Sample aus. Per-Sample-Evaluation (Spec §2.2.2.5.9.6) ist live in crates/dcps/src/subscriber.rs::DataReader::read_w_condition und take_w_condition; DdsTypeRow<'a, T> (in dds_type.rs) wraps T: DdsType zu zerodds_sql_filter::RowAccess via die optionale DdsType::field_value(path)-Methode.

Tests: crates/dcps/src/condition.rs::tests: query_condition_inherits_trigger_from_base, query_condition_set_query_parameters_roundtrip, query_condition_trigger_inherits_false_from_base (Negativ), query_condition_base_returns_correct_read_condition, query_condition_rejects_invalid_sql (Negativ), query_condition_evaluate_filters_per_sample, query_condition_evaluate_with_typed_values_int_param, query_condition_evaluate_uses_string_params_by_default. crates/dcps/tests/query_condition.rs (E2E): read_w_condition_filters_per_sample, take_w_condition_consumes_only_matching_samples, read_w_condition_with_string_parameter, read_w_condition_preserves_cache_state, take_w_condition_empty_when_no_match, read_w_condition_unknown_field_drops_sample.

Status: done


§2.2.3 Supported QoS — 22 Policies

2.2.3.1 USER_DATA QosPolicy

Spec: §2.2.3.1, S. 101 — sequence value.

Repo: crates/qos/src/policies/user_data.rs.

Tests: USER_DATA-Tests.

Status: done

2.2.3.2 TOPIC_DATA QosPolicy

Spec: §2.2.3.2, S. 102.

Repo: crates/qos/src/policies/topic_data.rs.

Tests:

Status: done

2.2.3.3 GROUP_DATA QosPolicy

Spec: §2.2.3.3, S. 102.

Repo: crates/qos/src/policies/group_data.rs.

Tests:

Status: done

2.2.3.4 DURABILITY QosPolicy (VOLATILE/TRANSIENT_LOCAL/TRANSIENT/PERSISTENT)

Spec: §2.2.3.4, S. 102-103.

Repo: crates/qos/src/policies/durability.rs::DurabilityQosPolicy mit allen 4 DurabilityKind-Werten + Spec-konformer Ordering-Relation (VOLATILE < TRANSIENT_LOCAL < TRANSIENT < PERSISTENT) + Wire-Encode/Decode (u32). Volatile + TransientLocal sind im Writer-side Sample-Cache implementiert; Transient + Persistent greifen auf den Durability-Service §2.2.3.5 zu (crates/dcps/src/durability_service.rs).

Tests: crates/qos/src/policies/durability.rs::tests: default_is_volatile, ordering_matches_spec, try_from_u32_is_strict, from_u32_is_forward_compat, encode_decode_roundtrip (alle 4 Kinds), unknown_kind_decode_rejected (Negativ), compatibility_offered_ge_requested (offered >= requested + Negativ).

Status: done — Wire-Form + Compatibility-Ordering vollständig; Transient/Persistent-Storage delegiert an §2.2.3.5 Durability-Service.

2.2.3.5 DURABILITY_SERVICE QosPolicy

Spec: §2.2.3.5, S. 103 — service_cleanup_delay + history_kind + history_depth + max_samples + max_instances + max_samples_per_instance.

Repo: crates/qos/src/policies/durability_service.rs::DurabilityServiceQosPolicy mit allen 6 Spec-Feldern + Wire-Encode/Decode. Storage-Service-Backends in crates/dcps/src/durability_service.rs: Trait DurabilityBackend (store / replay_for_topic / unregister_instance / cleanup) + zwei Implementationen InMemoryDurabilityBackend (TRANSIENT) und OnDiskDurabilityBackend (PERSISTENT, Verzeichnis-Hierarchie <root>/<topic>/<hex(instance)>/<seq>.bin mit .unregistered-Marker). Beide Backends respektieren history_kind (KeepLast-Cap durch FIFO, KeepAll-Cap durch OutOfResources), max_samples, max_instances, max_samples_per_instance und service_cleanup_delay (fraction als 2^-32 s korrekt nach Nanos konvertiert). make_backend(kind, qos, root)- Factory wählt automatisch.

Tests: crates/qos/src/policies/durability_service.rs::tests (2 Tests: roundtrip + default). Storage-Backend-Tests in crates/dcps/src/durability_service.rs::tests (19 Tests, alle 4 Caps + KeepLast/KeepAll + cleanup-after-delay + on-disk-survives-drop): in_memory_store_and_replay_returns_sorted_samples, in_memory_keeplast_caps_history_at_depth, in_memory_keepall_max_samples_per_instance_returns_oor (Negativ), in_memory_max_samples_globally_returns_oor (Negativ), in_memory_max_instances_returns_oor (Negativ), in_memory_unregister_then_cleanup_removes_after_delay, in_memory_replay_filters_by_topic, in_memory_unknown_topic_returns_empty (Negativ), make_backend_rejects_volatile_and_transient_local (Negativ), make_backend_persistent_requires_root (Negativ), make_backend_transient_returns_in_memory, on_disk_store_and_replay_roundtrip, on_disk_keeplast_replaces_old_files, on_disk_persistent_survives_backend_drop, on_disk_unregister_and_cleanup_removes_directory, on_disk_max_samples_per_instance_returns_oor (Negativ), hex16_roundtrip, parse_hex16_rejects_wrong_length_and_invalid_chars (Negativ), sanitize_topic_replaces_path_chars.

Status: done

2.2.3.6 PRESENTATION QosPolicy (access_scope INSTANCE/TOPIC/GROUP + coherent + ordered)

Spec: §2.2.3.6, S. 103-104.

Repo: crates/qos/src/policies/presentation.rs::PresentationQosPolicy mit access_scope (INSTANCE/TOPIC/GROUP) + coherent_access + ordered_access Bool-Flags. Wire-Encode/Decode + Compatibility-Check. INSTANCE/TOPIC live im Reader-Sort-Pfad; GROUP-coherent via crates/dcps/src/coherent_set.rs::GroupAccessScope.snapshot_generation — jedes begin_access (von 0→1) inkrementiert die Generation, alle DR im Subscriber sehen während des begin/end-Fensters denselben atomic Cut. Multi-Reader-Coherent-Set über Arc-Clone der Scope.

Tests: crates/qos/src/policies/presentation.rs::tests (6 Tests: roundtrip + access_scope + coherent + ordered Kombinationen).

Status: done

2.2.3.7 DEADLINE QosPolicy

Spec: §2.2.3.7, S. 104.

Repo: crates/qos/src/policies/deadline.rs.

Tests: Deadline-Tests inkl. cross-test-domain-pollution-Fix.

Status: done

2.2.3.8 LATENCY_BUDGET QosPolicy

Spec: §2.2.3.8, S. 104 — Hint an die Service über maximal akzeptierbare Latenz; pro Spec ist das eine Best-Effort-Hint, kein hartes Constraint.

Repo: crates/qos/src/policies/latency_budget.rs::LatencyBudgetQosPolicy mit duration: Duration_t + Wire-Encode/Decode (8 byte).

Tests: crates/qos/src/policies/latency_budget.rs::tests (2 Tests: roundtrip + default INFINITE).

Status: done

2.2.3.9 OWNERSHIP QosPolicy (SHARED/EXCLUSIVE)

Spec: §2.2.3.9, S. 105.

Repo: crates/qos/src/policies/ownership.rs::OwnershipQosPolicy mit OwnershipKind::Shared/Exclusive + Wire-Encode/Decode + Compatibility-Check (Spec §2.2.3 Tab. — kind muss exact match auf Reader/Writer-Pair).

Tests: crates/qos/src/policies/ownership.rs::tests (7 Tests: roundtrip + default Shared + Compat-Check + invalid-kind-Decode-Reject).

Strength-Selection: EXCLUSIVE Reader-side Strength-Selection implementiert in crates/dcps/src/instance_tracker.rs:: should_accept_sample_under_exclusive_ownership (Higher-Strength gewinnt; bei Tie GUID-Tiebreaker; First-Writer wird Owner ohne laufenden Vergleich). 8 Tests: exclusive_first_writer_wins, exclusive_higher_strength_wins, exclusive_lower_strength_rejected, exclusive_tie_break_by_higher_guid, exclusive_tie_break_lower_guid_rejected, exclusive_same_writer_always_accepted, clear_owner_for_writer_resets_owner, failover_after_clear_accepts_weaker_writer.

Status: done

2.2.3.10 OWNERSHIP_STRENGTH QosPolicy

Spec: §2.2.3.10, S. 106.

Repo: crates/qos/src/policies/ownership_strength.rs::OwnershipStrengthQosPolicy mit value: i32 + Wire-Encode/Decode (4 byte). Strength-Selection-Logik in crates/dcps/src/instance_tracker.rs:: should_accept_sample_under_exclusive_ownership (i32-Strength + GUID-Tiebreaker).

Tests: crates/qos/src/policies/ownership_strength.rs::tests (3 Tests: roundtrip + default 0 + negative-strength-roundtrip). Strength-Selection-Tests in instance_tracker::tests::exclusive_* (6 Tests).

Status: done

2.2.3.11 LIVELINESS QosPolicy (AUTOMATIC/MANUAL_BY_PARTICIPANT/MANUAL_BY_TOPIC)

Spec: §2.2.3.11, S. 106-107.

Repo: crates/qos/src/policies/liveliness.rs::LivelinessQosPolicy mit LivelinessKind (Automatic/ManualByParticipant/ManualByTopic) + lease_duration: Duration_t + Wire-Encode/Decode. crates/dcps/src/wlp.rs mit Heartbeat-Pfad für AUTOMATIC und Publisher::assert_liveliness() für MANUAL_BY_PARTICIPANT/TOPIC.

Tests: crates/qos/src/policies/liveliness.rs::tests (9 Tests: roundtrip aller drei Kinds + default + invalid-kind-Decode + Compatibility-Matrix Spec-konform).

Status: done

2.2.3.12 TIME_BASED_FILTER QosPolicy

Spec: §2.2.3.12, S. 107 — minimum_separation: Reader filtert Samples derselben Instanz aus, wenn ihr source_timestamp innerhalb von minimum_separation zum letzten gelieferten Sample liegt.

Repo: crates/qos/src/policies/time_based_filter.rs::TimeBasedFilterQosPolicy mit minimum_separation: Duration_t + Wire-Encode/Decode.

Tests: crates/qos/src/policies/time_based_filter.rs::tests (2 Tests: roundtrip + default 0 = “kein Filter”).

Reader-side Drop: crates/dcps/src/instance_tracker.rs mit InstanceState.last_delivered_ts: Option<Time> + should_deliver_under_time_based_filter(keyhash, sample_ts, min_separation_nanos) + record_delivery(keyhash, sample_ts). Read-Pfad pre-Delivery prüft und droppt bei zu geringer Separation. Tests: time_based_filter_first_sample_passes, time_based_filter_too_close_drops (Negativ), time_based_filter_far_enough_passes, time_based_filter_zero_separation_always_passes, time_based_filter_per_instance_isolation, time_based_filter_unknown_instance_passes.

Status: done

2.2.3.13 PARTITION QosPolicy

Spec: §2.2.3.13, S. 107-108 — sequence<string> name + Wildcard-Matching (“any-string” via *, “any-char” via ?, Character-Sets via [abc], etc.); leerer Vector matched leeren Vector + Default-Partition "".

Repo: crates/qos/src/policies/partition.rs::PartitionQosPolicy mit Wire-Encode/Decode + partition_match Funktion mit fnmatch- Engine (POSIX shell-glob, inkl. Character-Class, Negation).

Tests: crates/qos/src/policies/partition.rs::tests (19 Tests: roundtrip + Set-Match + Wildcard * + Wildcard ? + Character-Set + Negation + Default-Partition + Empty-Set Cases).

Status: done

2.2.3.14 RELIABILITY QosPolicy (BEST_EFFORT/RELIABLE)

Spec: §2.2.3.14, S. 108.

Repo: crates/qos/src/policies/reliability.rs + reliable Pfad in crates/rtps/.

Tests: Reliability-Tests.

Status: done

2.2.3.15 TRANSPORT_PRIORITY QosPolicy

Spec: §2.2.3.15, S. 108 — Hint-only.

Repo: crates/qos/src/policies/transport_priority.rs::TransportPriorityQosPolicy mit value: i32 + Wire-Encode/Decode.

Tests: crates/qos/src/policies/transport_priority.rs::tests (2 Tests: roundtrip + default 0).

Status: done

2.2.3.16 LIFESPAN QosPolicy

Spec: §2.2.3.16, S. 108 — Sample-Lifetime; Reader filtert Samples deren source_timestamp + duration < now.

Repo: crates/qos/src/policies/lifespan.rs::LifespanQosPolicy mit duration: Duration_t + Wire-Encode/Decode. Reader-side Sample- Expiry-Filter via Time::saturating_add.

Tests: crates/qos/src/policies/lifespan.rs::tests (2 Tests: roundtrip + default INFINITE).

Status: done

2.2.3.17 DESTINATION_ORDER QosPolicy (BY_RECEPTION_TIMESTAMP/BY_SOURCE_TIMESTAMP)

Spec: §2.2.3.17, S. 109.

Repo: crates/qos/src/policies/destination_order.rs::DestinationOrderQosPolicy mit DestinationOrderKind::ByReceptionTimestamp (Default) / BySourceTimestamp + Wire-Encode/Decode + Compatibility-Check (Spec: offered MUST match requested OR offered=ByReception is more permissive). Reader-side Reorder-Buffer via SampleInfo.source_timestamp.

Tests: crates/qos/src/policies/destination_order.rs::tests (7 Tests: roundtrip + default + Compat-Matrix + invalid-kind-Decode).

Status: done

2.2.3.18 HISTORY QosPolicy (KEEP_LAST/KEEP_ALL + depth)

Spec: §2.2.3.18, S. 109.

Repo: crates/qos/src/policies/history.rs.

Tests: History-Tests.

Status: done

2.2.3.19 RESOURCE_LIMITS QosPolicy (max_samples/max_instances/max_samples_per_instance)

Spec: §2.2.3.19, S. 109-110.

Repo: crates/qos/src/policies/resource_limits.rs::ResourceLimitsQosPolicy mit max_samples / max_instances / max_samples_per_instance + Wire-Encode/Decode + Validity-Checks (kein Cap kleiner als 1). Cap-Enforcement im Writer-Side Sample-Cache.

Tests: crates/qos/src/policies/resource_limits.rs::tests (5 Tests: roundtrip + default LENGTH_UNLIMITED + invalid-cap-reject + encoded-bytes).

Reliable-Block (§2.2.3.19): DataWriter::write() blockt am drain_signal: Condvar wenn queue.len() >= max_samples und Reliability=RELIABLE und max_blocking_time > 0; bei BestEffort oder max_blocking_time = 0 liefert es OutOfResources direkt; __drain_pending notifies wartende Writer-Threads. Tests: write_blocks_until_drain_when_reliable_max_samples_reached, write_returns_timeout_when_reliable_drain_too_slow (Negativ), write_returns_oor_when_best_effort_queue_full (Negativ), write_does_not_block_when_max_samples_unlimited.

Status: done

2.2.3.20 ENTITY_FACTORY QosPolicy (autoenable_created_entities)

Spec: §2.2.3.20, S. 110.

Repo: crates/qos/src/policies/entity_factory.rs.

Tests:

Status: done

2.2.3.21 WRITER_DATA_LIFECYCLE QosPolicy (autodispose_unregistered_instances)

Spec: §2.2.3.21, S. 110 — autodispose_unregistered_instances: bool (Default true) — wenn true und unregister_instance gerufen wird, sendet Writer auch ein DISPOSE-Sample.

Repo: crates/qos/src/policies/data_lifecycle.rs::WriterDataLifecycleQosPolicy mit autodispose_unregistered_instances: bool + Wire-Encode/Decode.

Tests: crates/qos/src/policies/data_lifecycle.rs::tests (Teil der 4 data_lifecycle-Tests: roundtrip + default true + autodispose-Verhalten).

Status: done

2.2.3.22 READER_DATA_LIFECYCLE QosPolicy

Spec: §2.2.3.22, S. 111 — autopurge_no_writer_samples_delay + autopurge_disposed_samples_delay.

Repo: crates/qos/src/policies/data_lifecycle.rs::ReaderDataLifecycleQosPolicy mit beiden Duration_t-Feldern + Wire-Encode/Decode.

Tests: crates/qos/src/policies/data_lifecycle.rs::tests (Teil der 4 data_lifecycle-Tests).

Auto-Purge: crates/dcps/src/instance_tracker.rs mit InstanceState.disposed_at + no_writers_at Timestamps, automatisch gesetzt beim dispose/unregister; autopurge(now, disposed_delay_nanos, no_writer_delay_nanos) durchsucht alle Instances und entfernt die, deren Marker länger als der jeweilige Delay her ist (u128::MAX = INFINITE = nie). Lazy-Purge wird vom Read-Pfad gerufen. Tests: autopurge_disposed_after_delay, autopurge_disposed_before_delay_keeps_instance (Negativ), autopurge_no_writers_after_delay, autopurge_alive_instance_never_purged (Negativ), autopurge_infinity_delay_never_purges.

Status: done

2.2.3.23 LIVELINESS+OWNERSHIP+REGISTRATION-Interaktion

Spec: §2.2.3.23, S. 111-113 — Cross-QoS-Interaktionen: bei LIVELINESS-Verlust eines Writers in OWNERSHIP=EXCLUSIVE soll der Reader auf den nächst-stärksten Writer umschalten; bei unregister_instance soll INSTANCE-Tracker den Lifecycle-Pfad durchziehen.

Repo: crates/dcps/src/wlp.rs (Liveliness-Heartbeat-Pfad) + crates/dcps/src/instance_tracker.rs (Instance-Lifecycle + Owner-Tracking) + crates/dcps/src/subscriber.rs::DataReader:: notify_writer_liveliness_lost(guid) und notify_participant_liveliness_lost(prefix) als Hooks aus dem WLP-Pfad. Owner-Reset via InstanceTracker::clear_owner_for_writer(guid) / clear_owner_for_writer_prefix(prefix); nach dem Clear gewinnt der nächste eintreffende Sample via Strength-Selection neu.

Tests: instance_tracker::tests: clear_owner_for_writer_resets_owner, failover_after_clear_accepts_weaker_writer, clear_owner_for_writer_prefix_matches_first_12_bytes, clear_owner_for_writer_prefix_multi_instance. E2E in crates/dcps/tests/ownership_failover.rs: notify_writer_liveliness_lost_clears_owner, notify_participant_liveliness_lost_clears_all_writers_with_prefix, notify_writer_liveliness_lost_for_unknown_writer_is_noop.

Status: done


§2.2.4 Listeners, Conditions, Wait-sets

2.2.4.1 Communication Status (13 Statuses)

Spec: §2.2.4.1, S. 114-118 — INCONSISTENT_TOPIC, OFFERED/REQUESTED_DEADLINE_MISSED, OFFERED/REQUESTED_INCOMPATIBLE_QOS, SAMPLE_LOST, SAMPLE_REJECTED, DATA_ON_READERS, DATA_AVAILABLE, LIVELINESS_LOST, LIVELINESS_CHANGED, PUBLICATION_MATCHED, SUBSCRIPTION_MATCHED.

Repo: crates/dcps/src/status.rs mit allen 13 Records.

Tests: status_records_*-Tests.

Status: done

2.2.4.2 Changes in Status (StatusChangedFlag-Bookkeeping)

Spec: §2.2.4.2, S. 118-121 — Plain vs. Read Status, Reset auf get/Listener.

Repo: crates/dcps/src/entity.rs::EntityState: status_changes: AtomicU32 (Bitmask), set_status_bits(bits), clear_status_changes(bits), status_changes() Read-Accessor. crates/dcps/src/listener_dispatch.rs setzt Bits beim Status-Event und cleart sie nach Listener-Dispatch (Spec §2.2.4.2.3).

Tests: crates/dcps/src/entity.rs::tests::status_bits_or_in_and_clear; plus listener_dispatch::tests mit Bubble-Up Reset-Verhalten.

Status: done

2.2.4.3 Access through Listeners (Bubble-Up DR -> Sub -> DP)

Spec: §2.2.4.3, S. 121-124.

Repo: listener_dispatch.rs::ReaderListenerChain walken local + parent + grandparent.

Tests: bubble_up_*-Tests.

Status: done

2.2.4.4 Conditions and Wait-Sets

Spec: §2.2.4.4, S. 124-127.

Repo: condition.rs mit WaitSet+Condition+GuardCondition.

Tests: WaitSet-Tests.

Status: done

2.2.4.5 Trigger State of ReadCondition

Spec: §2.2.4.5, S. 127.

Repo: crates/dcps/src/condition.rs::ReadCondition-Trigger via Closure (siehe §2.2.2.5.8).

Tests: crates/dcps/src/condition.rs::tests: read_condition_returns_trigger_from_closure, read_condition_trigger_false_when_closure_says_false, read_condition_attaches_to_waitset.

Status: done

2.2.4.6 Combination

Spec: §2.2.4.6, S. 127.

Repo: WaitSet akzeptiert beliebige Conditions.

Tests:

Status: done


§2.2.5 Built-in Topics

2.2.5.1 DCPSParticipant + ParticipantBuiltinTopicData

Spec: §2.2.5, S. 128-130.

Repo: crates/dcps/src/builtin_topics.rs::ParticipantBuiltinTopicData + builtin_subscriber.rs::participant_reader.

Tests: Builtin-Topic-Tests.

Status: done

2.2.5.2 DCPSTopic + TopicBuiltinTopicData

Spec: §2.2.5.

Repo: builtin_topics.rs::TopicBuiltinTopicData + builtin_subscriber.rs::topic_reader.

Tests:

Status: done

2.2.5.3 DCPSPublication + PublicationBuiltinTopicData

Spec: §2.2.5.

Repo: builtin_topics.rs::PublicationBuiltinTopicData + builtin_subscriber.rs::publication_reader.

Tests:

Status: done

2.2.5.4 DCPSSubscription + SubscriptionBuiltinTopicData

Spec: §2.2.5.

Repo: builtin_topics.rs::SubscriptionBuiltinTopicData + builtin_subscriber.rs::subscription_reader.

Tests:

Status: done

2.2.5.5 BuiltinSubscriber (lookup_datareader auf DCPS*-Topics)

Spec: §2.2.5.

Repo: builtin_subscriber.rs::BuiltinSubscriber::lookup_datareader<T: BuiltinTopic>.

Tests: Lookup-Tests.

Status: done

2.2.5.6 Builtin-Sub+DR Default-QoS (DURABILITY=TRANSIENT_LOCAL/RELIABILITY=RELIABLE/HISTORY=KEEP_LAST/depth=1/…)

Spec: §2.2.5 — vollständiger Default-QoS-Block.

Repo: builtin_subscriber.rs::builtin_reader_qos().

Tests:

Status: done

2.2.5.7 Built-in DR von gegebenem Participant zeigt nicht eigene-Participant-Entities

Spec: §2.2.5 — Built-in Subscriber liefert keine Entities des eigenen Participants (sonst self-loop).

Repo: crates/dcps/src/builtin_subscriber.rs mit participant_key- Filter-Logik im Discovery-Hook (filtert SPDP/SEDP-Samples mit gleicher Participant-Guid wie der lokale Participant).

Tests: crates/dcps/src/builtin_subscriber.rs::tests mit participant_key-Filter-Prüfung.

Status: done


§2.2.6 Interaction Model

2.2.6.1 Publication View (register -> write* -> unregister/dispose)

Spec: §2.2.6.1, S. 132 — komplette Pub-View-Sequenz.

Repo: publisher.rs mit register_instance/unregister_instance/ dispose/write (+ w_timestamp Varianten).

Tests: publication_view_*-Tests.

Status: done

2.2.6.2.1 Subscription View Notification via Listener (async push)

Spec: §2.2.6.2.1, S. 133-134.

Repo: listener_dispatch.rs.

Tests: Listener-Tests.

Status: done

2.2.6.2.2 Subscription View Notification via Conditions+WaitSets (sync poll)

Spec: §2.2.6.2.2, S. 135.

Repo: condition.rs::WaitSet.

Tests: WaitSet-Tests.

Status: done


§2.3 OMG IDL Platform Specific Model

2.3.1-2 PIM->PSM Mapping Rules (CORBA-IDL)

Spec: §2.3.1-2, S. 137 — PIM->PSM-Konventionen.

Repo: Rust-PSM in crates/dcps/ ist Spec-konforme Alternative- Form (XTypes 1.3 §7.2.2.4.8). CORBA-IDL-Annex-A.1-PSM-Emission in crates/idl-cpp/src/corba_traits.rs, crates/idl-csharp/src/corba_traits.rs, crates/idl-java/src/corba_traits.rs als opt-in Codegen-Pfad (siehe idl4-cpp-1.0.md / idl4-csharp-1.0.md / idl4-java-1.0.md Annex A.1).

Tests: Cross-Ref Rust-PSM-Tests im dcps-Crate + {idl-cpp,idl-csharp,idl-java}::corba_traits::tests::*.

Status: done — Rust-PSM (Alternative-Form) + CORBA-IDL-Annex-A.1- PSM-Emission live.

2.3.3 DCPS PSM IDL — komplette IDL-File zerodds_dcps.idl

Spec: §2.3.3, S. 138-162.

Repo: crates/idl/ — IDL-4.2-Parser (K1 voll abgeschlossen, 1026 Tests). Code-Gen über crates/idl-cpp/, crates/idl-java/, crates/idl-csharp/. Spec-Coverage des IDL 4.2 in docs/spec-coverage/idl-4.2.md (530 done / 0 partial).

Tests: Workspace-weit über zerodds-idl-Crate; docs/spec-coverage/idl-4.2.md ist die normative Coverage-Doku.

Status: done — IDL-Parser-Layer vollständig spec-konform; PSM- spezifische Code-Gen-Stage ist je PSM-Spec separat normativ.

2.3.3 IDL-Constants: typedef long DomainId_t / typedef long ReturnCode_t / etc.

Spec: §2.3.3.

Repo: Rust-Native-Typen (DomainId = u32, Result<T, DdsError>) + IDL-Constants in crates/dcps/src/psm_constants.rs::status::* für alle 13 Status-Bits + crates/dcps/src/error.rs::return_code::* für alle 13 ReturnCode_t-Werte.

Tests: crates/dcps/src/error.rs::tests::rc_constants_have_spec_values verifiziert alle 13 Spec-Konstanten Wert-genau.

Status: done


Audit-Status

100 done / 0 partial / 0 open / 2 n/a (informative) / 0 n/a (rejected).

Test-Lauf: cargo test -p zerodds-dcps — 407 lib + 150 integration (23 Integration-Test-Bins) = 557 Tests grün, 0 failed.

DLRL (optionaler §2.1.3-Layer) ist als Differenzierungs-Feature voll abgedeckt — eigener Crate crates/dlrl/, siehe DLRL-1.2-Coverage.