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;