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