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}