Skip to main content

cyclonedds/
lib.rs

1//! The official Rust binding for
2//! [Cyclone DDS](https://github.com/eclipse-cyclonedds/cyclonedds).
3//!
4//! DDS (Data Distribution Service) is a publish-subscribe middleware standard
5//! for real-time, data-centric communication. It is used in a variety of
6//! mission critical applications in domains such as aerospace, defense,
7//! autonomous systems (e.g. vehicles, robotics), industrial control, smart
8//! energy grids, transportation, simulation, and medical devices.
9//!
10//! [`Participants`](Participant) within a specific [`Domain`] discover each
11//! other automatically via the DDSI/RTPS discovery protocol. Once two endpoints
12//! sharing the same topic name, type information, and compatible
13//! [`Quality of Service`][QoS] (`QoS`) discover each other, the middleware
14//! establishes a connection between them.
15//!
16//! [`Publishers`](Publisher) and [`Subscribers`](Subscriber) allow you to group
17//! [`Writers`](Writer) and [`Readers`](Reader) respectively to allow you to set
18//! their collective behavior. These [`Writers`](Writer) and [`Readers`](Reader)
19//! exchange typed samples via [`Topics`](Topic).
20//!
21//! ```text
22//!                             DOMAIN
23//!                                │
24//!             ┌──────────────────┴──────────────────┐
25//!             │                                     │
26//!        PARTICIPANT                           PARTICIPANT
27//!             │      T ≡ struct Position {x, y}     │
28//!        ┌────┴────┐                           ┌────┴────┐
29//!        │         │                           │         │
30//!   PUBLISHER   TOPIC<T> ═══════════════════ TOPIC<T>  SUBSCRIBER
31//!        │         ║                           ║         │
32//!        │     "Position"                 "Position"     │
33//!        │         ║                           ║         │
34//!     WRITER<T> ═══╝                           ╚═══ READER<T>
35//!          ╰───────── matched via Topic<T> ─────────╯
36//!          Node 01                               Node 02
37//!         ─────────                             ─────────
38//! ```
39//!
40//! Data delivery characteristics, such as how samples are buffered,
41//! retransmitted, and received, are controlled via [`Quality of Service`][QoS],
42//! a collection of
43//! [`QoS policies`](qos::policy) that configure characteristics such as:
44//!
45//! - [`durability`](qos::policy::Durability) (whether late-joining readers receive historical
46//!   samples)
47//!
48//! - [`reliability`](qos::policy::Reliability) (best-effort vs reliable delivery)
49//!
50//! - [`history depth`](qos::policy::History) (the number of samples to store in history)
51//!
52//! - [`deadline`](qos::policy::Deadline) (whether a signal should be generated when a sample is not
53//!   received within a specified period)
54//!
55//! Policies are set independently on the writer and reader side, and
56//! compatibility is checked at discovery time. A writer's offered [`QoS`] must
57//! be compatible with a reader's requested [`QoS`] for the two endpoints to
58//! match.
59//!
60//! There are a variety of other elements to the DDS API such as:
61//!
62//! [`WaitSets`](WaitSet): to allow you to block until a particular status
63//! occurs on a DDS entity. [`Listeners`](Listener): to notify applications of a
64//! change in the status of a particular entity.
65//! [`GuardConditions`](GuardCondition), `StatusConditions`,
66//! [`ReadConditions`](ReadCondition), and [`QueryConditions`](QueryCondition):
67//! Mechanisms to trigger the condition associated with a waitset.
68//!
69//! See the [DDS Specification](https://www.omg.org/spec/DDS/1.4/About-DDS/) and the
70//! [OMG DDS Wiki](https://www.omgwiki.org/ddsf/doku.php?id=ddsf:public:guidebook:01_front:4_toc)
71//! for these other elements and see the rest of the Rust Documentation for what
72//! is supported by this API.
73//!
74//!
75//! # Getting started
76//!
77//! Every DDS application begins with a [`Domain`] and a [`Participant`]:
78//!
79//! ```
80//! use cyclonedds::{Domain, Participant};
81//!
82//! let domain = Domain::default();
83//! let participant = Participant::new(&domain)?;
84//! # Ok::<_, cyclonedds::Error>(())
85//! ```
86//!
87//! Types that can be used as a topic payload must implement the [`Topicable`]
88//! trait, either manually or via the
89//! [`Topicable`](cyclonedds_macros::Topicable) derive macro. Once you have a
90//! topic, create a [`Writer`] or [`Reader`] directly via `new` or through their
91//! builders to set [`QoS`] or to associate specific publishers or subscribers.
92//! You can then create samples and write them via the writer and read those
93//! samples back via the reader.
94//!
95//! ```
96//! # use cyclonedds::{Domain, Participant};
97//! # let domain = Domain::default();
98//! # let participant = Participant::new(&domain)?;
99//! # #[derive(
100//! #     cyclonedds::Topicable, serde::Serialize, serde::Deserialize, Clone, Debug, Default,
101//! # )]
102//! # struct MyData {
103//! #     x: i32,
104//! # }
105//! use cyclonedds::{QoS, Reader, Subscriber, Topic, Writer, qos};
106//!
107//! let topic = Topic::<MyData>::new(&participant, "MyTopic")?;
108//!
109//! let qos = QoS::new()
110//!     .with_reliability(qos::policy::Reliability::BestEffort)
111//!     .with_history(qos::policy::History::KeepLast { depth: 10 });
112//!
113//! let subscriber = Subscriber::builder(&participant).with_qos(&qos).build()?;
114//!
115//! let writer = Writer::builder(&topic).with_qos(&qos).build()?;
116//! let reader = Reader::builder(&topic)
117//!     .with_qos(&qos)
118//!     .with_subscriber(&subscriber)
119//!     .build()?;
120//!
121//! for x in 0..10 {
122//!     let sample = MyData { x };
123//!     writer.write(&sample)?;
124//! }
125//! # assert_eq!(10, reader.read()?.len());
126//!
127//! // Does not remove the samples from the history,
128//! // and does not update metadata.
129//! for sample in reader.peek()? {
130//!     // process sample
131//! }
132//!
133//! // Does not remove the samples from the history,
134//! // but does update metadata.
135//! for sample in reader.read()? {
136//!     // process sample
137//! }
138//!
139//! // Removes the samples from the history,
140//! // and updates metadata.
141//! for sample in reader.take()? {
142//!     // process sample
143//! }
144//!
145//! # assert_eq!(0, reader.read()?.len());
146//! # Ok::<_, cyclonedds::Error>(())
147//! ```
148//!
149//! For further reading, see the [Cyclone DDS
150//! documentation](https://cyclonedds.io), the [OMG DDS
151//! specification](https://www.omg.org/spec/DDS/), and the
152//! [`examples`](https://github.com/eclipse-cyclonedds/cyclonedds-rust/tree/master/cyclonedds/examples).
153
154// NOTE: this is specified here rather than in the common lints within the workspace `Cargo.toml`
155// because excluding it for the examples and integration tests is problematic.
156#![deny(unused_crate_dependencies)]
157// NOTE: active lint levels are defined in the workspace `Cargo.toml`. J
158// These `allow`s for the test exist for lints that significantly reduce test readability or
159// ergonomics.
160#![cfg_attr(
161    test,
162    allow(
163        clippy::cast_sign_loss,
164        clippy::cognitive_complexity,
165        clippy::indexing_slicing,
166        clippy::too_many_lines,
167        clippy::undocumented_unsafe_blocks,
168    )
169)]
170
171pub mod cdr_bounds;
172mod domain;
173mod duration;
174pub mod entity;
175mod error;
176mod guard_condition;
177pub mod listener;
178mod participant;
179mod publisher;
180pub mod qos;
181mod query_condition;
182mod read_condition;
183mod reader;
184pub mod sample;
185pub mod state;
186pub mod status;
187mod subscriber;
188mod time;
189mod topic;
190mod topicable;
191mod waitset;
192mod writer;
193
194pub use cyclonedds_macros::Topicable;
195pub use domain::Domain;
196pub use duration::Duration;
197pub use error::{Error, Result};
198pub use guard_condition::GuardCondition;
199pub use listener::{
200    Listener, PublisherListener, ReaderListener, SubscriberListener, TopicListener, WriterListener,
201};
202pub use participant::Participant;
203pub use publisher::Publisher;
204pub use qos::QoS;
205pub use query_condition::QueryCondition;
206pub use read_condition::ReadCondition;
207pub use reader::Reader;
208pub use state::State;
209pub use status::bitflags::Status;
210pub use subscriber::Subscriber;
211pub use time::Time;
212pub use topic::Topic;
213pub use topicable::{Key, Topicable};
214pub use waitset::WaitSet;
215pub use writer::Writer;
216
217pub mod builder {
218    //! Builder types for constructing DDS entities with custom `QoS` and
219    //! listeners.
220    //!
221    //! Each builder is also accessible via the `builder` associated function on
222    //! its corresponding entity type.
223    pub use crate::participant::ParticipantBuilder;
224    pub use crate::publisher::PublisherBuilder;
225    pub use crate::reader::ReaderBuilder;
226    pub use crate::subscriber::SubscriberBuilder;
227    pub use crate::topic::TopicBuilder;
228    pub use crate::writer::WriterBuilder;
229}
230
231#[cfg(feature = "internal")]
232pub mod internal;
233#[cfg(not(feature = "internal"))]
234mod internal;
235
236#[cfg(test)]
237mod tests;