cyclonedds_rs/
dds_topic.rs1use crate::{dds_listener::DdsListener, dds_participant::DdsParticipant, dds_qos::DdsQos, Entity};
18
19use std::convert::From;
20use std::ffi::CString;
21use std::marker::PhantomData;
22
23use crate::serdes::{SerType, TopicType};
24pub use cyclonedds_sys::{ddsi_sertype, DDSError, DdsEntity};
25
26pub struct TopicBuilder<T: TopicType> {
27    maybe_qos: Option<DdsQos>,
28    maybe_listener: Option<DdsListener>,
29    topic_name: String,
30    phantom: PhantomData<T>,
31}
32
33impl<T> TopicBuilder<T>
34where
35    T: TopicType,
36{
37    pub fn new() -> Self {
38        Self {
39            maybe_qos: None,
40            maybe_listener: None,
41            topic_name: T::topic_name(None),
42            phantom: PhantomData,
43        }
44    }
45
46    pub fn with_name(mut self, name: String) -> Self {
47        self.topic_name = name;
48        self
49    }
50
51    pub fn with_name_prefix(mut self, mut prefix_name: String) -> Self {
52        prefix_name.push_str(self.topic_name.as_str());
53        self.topic_name = prefix_name;
54        self
55    }
56
57    pub fn with_qos(mut self, qos: DdsQos) -> Self {
58        self.maybe_qos = Some(qos);
59        self
60    }
61
62    pub fn with_listener(mut self, listener: DdsListener) -> Self {
63        self.maybe_listener = Some(listener);
64        self
65    }
66
67    pub fn create(self, participant: &DdsParticipant) -> Result<DdsTopic<T>, DDSError> {
68        DdsTopic::<T>::create(
69            participant,
70            self.topic_name.as_str(),
71            self.maybe_qos,
72            self.maybe_listener,
73        )
74    }
75}
76
77pub struct DdsTopic<T: Sized + TopicType>(DdsEntity, PhantomData<T>, Option<DdsListener>);
78
79impl<T> DdsTopic<T>
80where
81    T: std::marker::Sized + TopicType,
82{
83    pub fn create(
84        participant: &DdsParticipant,
85        name: &str,
86        maybe_qos: Option<DdsQos>,
87        maybe_listener: Option<DdsListener>,
88    ) -> Result<Self, DDSError> {
89        let t = SerType::<T>::new();
90        let mut t = SerType::into_sertype(t);
91        let tt = &mut t as *mut *mut ddsi_sertype;
92
93        unsafe {
94            let strname = CString::new(name).expect("CString::new failed");
95            let topic = cyclonedds_sys::dds_create_topic_sertype(
96                participant.entity().entity(),
97                strname.as_ptr(),
98                tt,
99                maybe_qos.map_or(std::ptr::null(), |q| q.into()),
100                maybe_listener
101                    .as_ref()
102                    .map_or(std::ptr::null(), |l| l.into()),
103                std::ptr::null_mut(),
104            );
105
106            if topic >= 0 {
107                Ok(DdsTopic(DdsEntity::new(topic), PhantomData, maybe_listener))
108            } else {
109                Err(DDSError::from(topic))
110            }
111        }
112    }
113}
114
115impl<T> Entity for DdsTopic<T>
116where
117    T: std::marker::Sized + TopicType,
118{
119    fn entity(&self) -> &DdsEntity {
120        &self.0
121    }
122}
123
124impl<T> Clone for DdsTopic<T>
125where
126    T: std::marker::Sized + TopicType,
127{
128    fn clone(&self) -> Self {
129        Self(self.0.clone(), PhantomData, self.2.clone())
130    }
131}
132
133#[cfg(test)]
134mod test {
135    use super::*;
136    use crate::SampleBuffer;
137    use crate::{DdsPublisher, DdsWriter};
138    use cdds_derive::Topic;
139    use serde_derive::{Deserialize, Serialize};
140    use std::sync::Arc;
141    #[test]
142    fn test_topic_creation() {
143        #[derive(Default, Deserialize, Serialize, Topic)]
144        struct MyTopic {
145            #[topic_key]
146            a: u32,
147            b: u32,
148            c: String,
149            d: u32,
150        }
151
152        assert_eq!(
153            MyTopic::topic_name(None),
154            String::from("/dds_topic/test/test_topic_creation/MyTopic")
155        );
156        assert_eq!(
157            MyTopic::topic_name(Some("prefix")),
158            String::from("prefix/dds_topic/test/test_topic_creation/MyTopic")
159        );
160
161        let participant = DdsParticipant::create(None, None, None).unwrap();
162        let topic = MyTopic::create_topic(&participant, None, None, None).unwrap();
163        let publisher =
164            DdsPublisher::create(&participant, None, None).expect("Unable to create publisher");
165        let mut writer = DdsWriter::create(&publisher, topic, None, None).unwrap();
166
167        let data = Arc::new(MyTopic {
170            a: 1,
171            b: 32,
172            c: "my_data_sample".to_owned(),
173            d: 546,
174        });
175
176        writer.write(data).unwrap();
177    }
178}