zerodds_routing_service/lib.rs
1// SPDX-License-Identifier: Apache-2.0
2// Copyright 2026 ZeroDDS Contributors
3
4//! # ZeroDDS routing service
5//!
6//! A standalone DDS routing service: it forwards samples between DDS domains,
7//! topics, QoS profiles and partitions **within** the DDS bus — the in-DDS
8//! routing counterpart to the protocol bridges (which cross protocol
9//! boundaries). It is the RTI-Routing-Service equivalent for ZeroDDS.
10//!
11//! Safety classification: **COMFORT**. Part of [**ZeroDDS**](../../README.md).
12//!
13//! ## What it does
14//!
15//! A [`config::Route`] couples an input [`config::Endpoint`] (a reader on a
16//! domain/topic) to an output endpoint (a writer on a — possibly different —
17//! domain/topic), with:
18//!
19//! * **Topic renaming** — input topic `A` → output topic `B`.
20//! * **Domain bridging** — read on domain 0, write on domain 1, in one process.
21//! * **QoS mapping** — per-endpoint reliability / durability / ownership /
22//! partition / data-representation.
23//! * **Type-agnostic byte forwarding** — the CDR body is forwarded verbatim
24//! (representation-faithful: XCDR1/XCDR2 encapsulation preserved); no type
25//! recompilation, cross-vendor.
26//! * **Keyed-instance lifecycle propagation** — dispose / unregister events are
27//! forwarded for keyed topics.
28//! * **Loop guard** — on any domain that is both an input and an output
29//! domain, the router's input participant and output participant are made
30//! mutually invisible (`ignore_participant`), so no router output is ever
31//! re-ingested by a router input on the same domain — preventing
32//! router-internal loops (bidirectional bridges, multi-route cycles) while
33//! application writers stay visible.
34//! * **Content filtering** (v3) — a DDS SQL filter (`temp > 50 AND zone = 'A'`)
35//! evaluated per sample against the decoded body.
36//! * **Field transformation** (v3) — rename / constant-set / drop members,
37//! mapping an input shape to an output shape.
38//!
39//! ## Surfaces
40//!
41//! * Library — [`Router::start`] / [`Router::start_with_types`].
42//! * Config — JSON ([`config::RouterConfig::from_json`]) or XML
43//! ([`config::RouterConfig::from_xml`], native + RTI subset).
44//! * Daemon — the `zerodds-router` binary.
45//! * Metrics — per-route counters in the `zerodds-monitor` registry (rendered
46//! by the existing Prometheus exporter).
47//!
48//! ## Limitations
49//!
50//! * **`preserve_source_timestamp`** is parsed but rejected at route build: the
51//! runtime user byte-path does not surface a sample's source timestamp, so
52//! the router cannot reproduce it. Wiring `source_timestamp` through
53//! `UserSample` + a timestamped write is the prerequisite follow-up.
54//! * **Filter / transform** operate on flat `@final` / `@appendable` structs of
55//! scalar and string members (the common routing case), decoded
56//! little-endian. Nested structs, sequences, unions and `@mutable` member
57//! headers are a documented extension; byte pass-through routing has no such
58//! restriction.
59//! * **Loop guard** covers router-*internal* loops (within one process). Loops
60//! spanning two separate `zerodds-router` processes need a discovery
61//! discriminator (a router tag in `user_data`), which the DCPS builtin
62//! publication reader does not currently surface — a documented follow-up.
63
64#![forbid(unsafe_code)]
65
66pub mod config;
67pub mod engine;
68pub mod error;
69pub mod forwarding;
70pub mod metrics;
71pub mod transform;
72mod xml;
73
74pub use config::{
75 ContentFilter, Durability, Endpoint, Ownership, QosSpec, RenameRule, Route, RouterConfig,
76 SetConstRule, Transform,
77};
78pub use engine::Router;
79pub use error::{Result, RoutingError};
80pub use metrics::{RouteMetrics, RouteMetricsSnapshot};
81pub use transform::{Member, ScalarKind, TypeRegistry, TypeShape};