wamp_core/messages/
subscribe.rs1use super::{MessageDirection, WampMessage};
2use crate::{messages::helpers, roles::Roles};
3use serde::{de::Visitor, Deserialize, Serialize};
4use serde_json::Value;
5use std::marker::PhantomData;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct Subscribe {
65 pub request_id: u64,
66 pub options: Value,
67 pub topic: String,
68}
69
70#[macro_export]
71macro_rules! subscribe {
93 ($topic:expr) => {
94 subscribe! {$topic, serde_json::json!({})}
95 };
96 ($topic:expr, $options:expr) => {
97 Subscribe {
98 topic: $topic.to_string(),
99 options: $options,
100 request_id: $crate::factories::increment(),
101 }
102 };
103}
104
105impl WampMessage for Subscribe {
106 const ID: u64 = 32;
107
108 fn direction(role: Roles) -> &'static MessageDirection {
109 match role {
110 Roles::Callee => &MessageDirection {
111 receives: &false,
112 sends: &false,
113 },
114 Roles::Caller => &MessageDirection {
115 receives: &false,
116 sends: &false,
117 },
118 Roles::Publisher => &MessageDirection {
119 receives: &false,
120 sends: &false,
121 },
122 Roles::Subscriber => &MessageDirection {
123 receives: &false,
124 sends: &true,
125 },
126 Roles::Dealer => &MessageDirection {
127 receives: &false,
128 sends: &false,
129 },
130 Roles::Broker => &MessageDirection {
131 receives: &true,
132 sends: &false,
133 },
134 }
135 }
136}
137
138impl Serialize for Subscribe {
139 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
140 where
141 S: serde::Serializer,
142 {
143 (Self::ID, &self.request_id, &self.options, &self.topic).serialize(serializer)
144 }
145}
146
147impl<'de> Deserialize<'de> for Subscribe {
148 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
149 where
150 D: serde::Deserializer<'de>,
151 {
152 struct SubscribeVisitor(
153 PhantomData<u64>,
154 PhantomData<u64>,
155 PhantomData<Value>,
156 PhantomData<String>,
157 );
158
159 impl<'vi> Visitor<'vi> for SubscribeVisitor {
160 type Value = Subscribe;
161
162 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
163 formatter.write_str("A sequence of Subscribe components.")
164 }
165
166 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
167 where
168 A: serde::de::SeqAccess<'vi>,
169 {
170 let message_id: u64 = helpers::deser_seq_element(
171 &mut seq,
172 "Message id must be present and type u64.",
173 )?;
174 helpers::validate_id::<Subscribe, A, _>(&message_id, "Subscribe")?;
175 let request_id: u64 = helpers::deser_seq_element(
176 &mut seq,
177 "Request ID must be present and type u64",
178 )?;
179 let options: Value = helpers::deser_seq_element(
180 &mut seq,
181 "options must be present and object like",
182 )?;
183 helpers::deser_value_is_object::<A, _>(&options, "options must be object like.")?;
184 let topic: String = helpers::deser_seq_element(
185 &mut seq,
186 "topic URI must be present and type String",
187 )?;
188 helpers::deser_value_is_object::<A, _>(&options, "options must be object like.")?;
189 Ok(Subscribe {
190 request_id,
191 options,
192 topic,
193 })
194 }
195 }
196
197 deserializer.deserialize_struct(
198 "Subscribe",
199 &["request_id", "options", "topic"],
200 SubscribeVisitor(PhantomData, PhantomData, PhantomData, PhantomData),
201 )
202 }
203}
204
205#[cfg(test)]
206mod tests {
207 use serde_json::{from_str, json, to_string};
208
209 use super::Subscribe;
210
211 #[test]
212 fn subscribe_test() {
213 let d1 = r#"[32,713845233,{},"com.myapp.mytopic1"]"#;
214 let r1 = Subscribe {
215 request_id: 713845233,
216 options: json!({}),
217 topic: "com.myapp.mytopic1".to_string(),
218 };
219 assert_eq!(d1, to_string(&r1).unwrap());
220 assert_eq!(r1, from_str::<Subscribe>(d1).unwrap())
221 }
222}