communication_layer_pub_sub/lib.rs
1#![warn(missing_docs)]
2#![cfg_attr(docsrs, feature(doc_auto_cfg))]
3
4//! Abstraction of various publisher/subscriber communication backends.
5//!
6//! Provides a [`CommunicationLayer`] trait as an abstraction for different publisher/subscriber
7//! systems. The following set of backends are currently supported:
8//!
9//! - **[Zenoh](https://zenoh.io/):** The zenoh project implements a distributed
10//! publisher/subscriber system with automated routing. To use zenoh, use the
11//! [`ZenohCommunicationLayer`][zenoh::ZenohCommunicationLayer] struct.
12
13use std::borrow::Cow;
14
15#[cfg(feature = "zenoh")]
16pub mod zenoh;
17
18type BoxError = Box<dyn std::error::Error + Send + Sync + 'static>;
19
20/// Abstraction trait for different publisher/subscriber implementations.
21pub trait CommunicationLayer: Send + Sync {
22 /// Creates a publisher for the given topic.
23 fn publisher(&mut self, topic: &str) -> Result<Box<dyn Publisher>, BoxError>;
24
25 /// Subscribe to the given topic.
26 fn subscribe(&mut self, topic: &str) -> Result<Box<dyn Subscriber>, BoxError>;
27}
28
29/// Allows publishing messages to subscribers.
30///
31/// The messages is published to the topic that was used to create the publisher
32/// (see [`CommunicationLayer::publisher`]).
33pub trait Publisher: Send + Sync {
34 /// Prepare memory for publishing a message with the given length.
35 ///
36 /// This function makes it possible to construct messages without
37 /// any additional copying. The returned [`Sample`] is initialized
38 /// with zeros.
39 fn prepare(&self, len: usize) -> Result<Box<dyn PublishSample + '_>, BoxError>;
40
41 /// Clone this publisher, returning the clone as a
42 /// [trait object](https://doc.rust-lang.org/book/ch17-02-trait-objects.html).
43 fn dyn_clone(&self) -> Box<dyn Publisher>;
44
45 /// Publishes the gives message to subscribers.
46 ///
47 /// Depending on the backend, this method might need to copy the data, which can
48 /// decrease performance. To avoid this, the [`prepare`](Publisher::prepare) function
49 /// can be used to construct the message in-place.
50 fn publish(&self, data: &[u8]) -> Result<(), BoxError> {
51 let mut sample = self.prepare(data.len())?;
52 sample.as_mut_slice().copy_from_slice(data);
53 sample.publish()?;
54 Ok(())
55 }
56}
57
58/// A prepared message constructed by [`Publisher::prepare`].
59pub trait PublishSample<'a>: Send + Sync {
60 /// Gets a reference to the prepared message.
61 ///
62 /// Makes it possible to construct the message in-place.
63 fn as_mut_slice(&mut self) -> &mut [u8];
64
65 /// Publish this sample to subscribers.
66 ///
67 /// The sample is published to the topic that was used to create the corresponding publisher
68 /// (see [`CommunicationLayer::publisher`]).
69 fn publish(self: Box<Self>) -> Result<(), BoxError>;
70}
71
72/// Allows receiving messages published on a topic.
73pub trait Subscriber: Send + Sync {
74 /// Receives the next message.
75 ///
76 /// Blocks until the next message is available.
77 ///
78 /// Depending on the chosen communication backend, some messages might be dropped if
79 /// the publisher is faster than the subscriber.
80 fn recv(&mut self) -> Result<Option<Box<dyn ReceivedSample>>, BoxError>;
81}
82
83/// A message received from the communication layer.
84pub trait ReceivedSample: Send + Sync {
85 /// Access the message's data.
86 fn get(&self) -> Cow<[u8]>;
87}