wamp_core/messages/unsubscribe.rs
1use super::{helpers, MessageDirection, WampMessage};
2use crate::roles::Roles;
3use serde::de::{SeqAccess, Visitor};
4use serde::{Deserialize, Deserializer, Serialize};
5use std::fmt::Formatter;
6use std::marker::PhantomData;
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9/// # Unsubscribe - [wamp-proto](https://wamp-proto.org/wamp_latest_ietf.html#name-unsubscribe-2)
10/// Represents an Unsubscribe message in the WAMP protocol.
11/// ## Examples
12/// ```
13/// use wamp_core::messages::Unsubscribe;
14/// use wamp_core::unsubscribe;
15/// use serde_json::json;
16///
17/// # let mut unsubscribe_message2 = unsubscribe!(2);
18///
19/// let unsubscribe_message = Unsubscribe {
20/// request_id: 1,
21/// subscription: 2
22/// };
23///
24/// # assert_eq!(unsubscribe_message, unsubscribe_message2);
25/// ```
26///
27///
28/// ### Serializer
29/// Implements serde Serialize trait for Unsubscribe
30/// ```
31/// use wamp_core::messages::Unsubscribe;
32/// use serde_json::{json, to_string};
33///
34/// // Create an unsubscribe message
35/// let unsubscribe = Unsubscribe {
36/// request_id: 1,
37/// subscription: 2
38/// };
39///
40/// // Establish raw json data string
41/// let data = r#"[34,1,2]"#;
42///
43/// // Here we convert it from an `Unsubscribe` frame, to a string representation.
44/// let unsubscribe = to_string(&unsubscribe).unwrap();
45///
46/// // Confirm that our unsubscribe frame strings are equal to each other
47/// assert_eq!(unsubscribe, data);
48/// ```
49/// ### Deserializer
50/// Implements serde Deserialize trait for Unsubscribe
51/// ```
52/// use wamp_core::messages::Unsubscribe;
53/// use serde_json::from_str;
54///
55/// // Here is our raw json data string
56/// let data = r#"[34,1,2]"#;
57///
58/// // Here we convert it to an `Unsubscribe` frame
59/// let unsubscribe = from_str::<Unsubscribe>(data).unwrap();
60///
61/// // Confirm that our request_id and subscription deserialized
62/// assert_eq!(unsubscribe.request_id, 1);
63/// assert_eq!(unsubscribe.subscription, 2);
64/// ```
65pub struct Unsubscribe {
66 pub request_id: u64,
67 pub subscription: u64,
68}
69
70#[macro_export]
71/// # unsubscribe Macro - [wamp-proto](https://wamp-proto.org/wamp_latest_ietf.html#name-unsubscribe-2)
72/// Macro that allows for creating auto incrementing Unsubscribe wamp message.
73/// ## Examples
74/// ```
75/// use wamp_core::messages::{self, Unsubscribe};
76/// use wamp_core::unsubscribe;
77/// use serde_json::json;
78///
79/// let mut unsubscribe_message = unsubscribe!(2);
80/// let unsubscribe_message2 = unsubscribe!(3);
81///
82/// assert_ne!(unsubscribe_message, unsubscribe_message2);
83///
84/// // These macro invocations are the same as the following:
85/// let unsubscribe_message3 = Unsubscribe {
86/// request_id: 1,
87/// subscription: 2
88/// };
89///
90/// assert_eq!(unsubscribe_message, unsubscribe_message3);
91/// assert_ne!(unsubscribe_message2, unsubscribe_message3);
92/// ```
93macro_rules! unsubscribe {
94 ($subscription:expr) => {
95 Unsubscribe {
96 request_id: $crate::factories::increment(),
97 subscription: $subscription,
98 }
99 };
100}
101
102impl WampMessage for Unsubscribe {
103 const ID: u64 = 34;
104
105 fn direction(role: Roles) -> &'static MessageDirection {
106 match role {
107 Roles::Callee => &MessageDirection {
108 receives: &false,
109 sends: &false,
110 },
111 Roles::Caller => &MessageDirection {
112 receives: &false,
113 sends: &false,
114 },
115 Roles::Publisher => &MessageDirection {
116 receives: &false,
117 sends: &false,
118 },
119 Roles::Subscriber => &MessageDirection {
120 receives: &false,
121 sends: &true,
122 },
123 Roles::Dealer => &MessageDirection {
124 receives: &false,
125 sends: &false,
126 },
127 Roles::Broker => &MessageDirection {
128 receives: &true,
129 sends: &false,
130 },
131 }
132 }
133}
134
135impl Serialize for Unsubscribe {
136 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
137 where
138 S: serde::Serializer,
139 {
140 (Self::ID, &self.request_id, &self.subscription).serialize(serializer)
141 }
142}
143
144impl<'de> Deserialize<'de> for Unsubscribe {
145 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
146 where
147 D: Deserializer<'de>,
148 {
149 struct UnsubscribeVisitor(PhantomData<u64>, PhantomData<u64>, PhantomData<u64>);
150
151 impl<'vi> Visitor<'vi> for UnsubscribeVisitor {
152 type Value = Unsubscribe;
153 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
154 formatter.write_str("A sequence of Unsubscribe components.")
155 }
156
157 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
158 where
159 A: SeqAccess<'vi>,
160 {
161 let message_id: u64 = helpers::deser_seq_element(
162 &mut seq,
163 "Message ID must be present and type u8.",
164 )?;
165 helpers::validate_id::<Unsubscribe, A, _>(&message_id, "Unsubscribe")?;
166 let request_id: u64 = helpers::deser_seq_element(
167 &mut seq,
168 "request_id must be present and type u64.",
169 )?;
170 let subscription: u64 = helpers::deser_seq_element(
171 &mut seq,
172 "subscription must be present and object like.",
173 )?;
174 Ok(Unsubscribe {
175 request_id,
176 subscription,
177 })
178 }
179 }
180
181 deserializer.deserialize_struct(
182 "Unsubscribe",
183 &["request_id", "subscription"],
184 UnsubscribeVisitor(PhantomData, PhantomData, PhantomData),
185 )
186 }
187}
188
189#[cfg(test)]
190mod tests {
191 use serde_json::{from_str, to_string};
192
193 use super::Unsubscribe;
194
195 #[test]
196 fn test() {
197 let d1 = r#"[34,85346237,5512315355]"#;
198 let p1 = Unsubscribe {
199 request_id: 85346237,
200 subscription: 5512315355,
201 };
202 assert_eq!(d1, to_string(&p1).unwrap());
203 assert_eq!(from_str::<Unsubscribe>(d1).unwrap(), p1);
204 }
205}