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}