1use super::{helpers, MessageDirection, WampMessage};
2use crate::roles::Roles;
3use serde::de::{SeqAccess, Visitor};
4use serde::{Deserialize, Deserializer, Serialize};
5use serde_json::{json, Value};
6use std::fmt::Formatter;
7use std::marker::PhantomData;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct Invocation {
69 pub request_id: u64,
70 pub registration: u64,
71 pub details: Value,
72 pub args: Value,
73 pub kwargs: Value,
74}
75
76#[macro_export]
77macro_rules! invocation {
120 ($registration:expr) => {
121 invocation!{$registration, serde_json::json!({}), serde_json::Value::Null, serde_json::Value::Null}
122 };
123
124 ($registration:expr, $details:expr) => {
125 invocation!{$registration, $details, serde_json::Value::Null, serde_json::Value::Null}
126 };
127
128 ($registration:expr, args: $args:expr) => {
129 invocation!{$registration, serde_json::json!({}), $args, serde_json::Value::Null}
130 };
131
132 ($registration:expr, kwargs: $kwargs:expr) => {
133 invocation!{$registration, serde_json::json!({}), serde_json::Value::Null, $kwargs}
134 };
135
136 ($registration:expr, args: $args:expr, kwargs: $kwargs:expr) => {
137 invocation!{$registration, serde_json::json!({}), $args, $kwargs}
138 };
139
140 ($registration:expr, $details:expr, args: $args:expr) => {
141 invocation!{$registration, $details, $args, serde_json::Value::Null}
142 };
143
144 ($registration:expr, $details:expr, kwargs: $kwargs:expr) => {
145 invocation!{$registration, $details, serde_json::Value::Null, $kwargs}
146 };
147
148 ($registration:expr, $details:expr, $args:expr, $kwargs:expr) => {{
149 Invocation {
150 request_id: $crate::factories::increment(),
151 details: $details,
152 registration: $registration,
153 args: $args,
154 kwargs: $kwargs
155 }
156 }};
157}
158
159impl WampMessage for Invocation {
160 const ID: u64 = 68;
161
162 fn direction(role: Roles) -> &'static MessageDirection {
163 match role {
164 Roles::Callee => &MessageDirection {
165 receives: &true,
166 sends: &false,
167 },
168 Roles::Caller => &MessageDirection {
169 receives: &false,
170 sends: &false,
171 },
172 Roles::Publisher => &MessageDirection {
173 receives: &false,
174 sends: &false,
175 },
176 Roles::Subscriber => &MessageDirection {
177 receives: &false,
178 sends: &false,
179 },
180 Roles::Dealer => &MessageDirection {
181 receives: &false,
182 sends: &true,
183 },
184 Roles::Broker => &MessageDirection {
185 receives: &false,
186 sends: &false,
187 },
188 }
189 }
190}
191
192impl Serialize for Invocation {
193 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
194 where
195 S: serde::Serializer,
196 {
197 let args =
198 helpers::ser_value_is_args::<S, _>(&self.args, "Args must be Array like or Null.")?;
199 let kwargs = helpers::ser_value_is_kwargs::<S, _>(
200 &self.kwargs,
201 "Kwargs must be Object like or Null.",
202 )?;
203
204 if args.is_null() {
205 if kwargs.is_null() {
206 (
207 Self::ID,
208 &self.request_id,
209 &self.registration,
210 &self.details,
211 )
212 .serialize(serializer)
213 } else {
214 (
215 Self::ID,
216 &self.request_id,
217 &self.registration,
218 &self.details,
219 json!([]),
220 kwargs,
221 )
222 .serialize(serializer)
223 }
224 } else {
225 if kwargs.is_null() {
226 (
227 Self::ID,
228 &self.request_id,
229 &self.registration,
230 &self.details,
231 args,
232 )
233 .serialize(serializer)
234 } else {
235 (
236 Self::ID,
237 &self.request_id,
238 &self.registration,
239 &self.details,
240 args,
241 kwargs,
242 )
243 .serialize(serializer)
244 }
245 }
246 }
247}
248
249impl<'de> Deserialize<'de> for Invocation {
250 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
251 where
252 D: Deserializer<'de>,
253 {
254 struct InvocationVisitor(
255 PhantomData<u8>,
256 PhantomData<u64>,
257 PhantomData<u64>,
258 PhantomData<Value>,
259 PhantomData<Value>,
260 PhantomData<Value>,
261 );
262
263 impl<'vi> Visitor<'vi> for InvocationVisitor {
264 type Value = Invocation;
265 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
266 formatter.write_str("A sequence of Invocation components.")
267 }
268
269 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
270 where
271 A: SeqAccess<'vi>,
272 {
273 let message_id: u64 = helpers::deser_seq_element(
274 &mut seq,
275 "Message ID must be present and type u8.",
276 )?;
277 helpers::validate_id::<Invocation, A, _>(&message_id, "Invocation")?;
278 let request_id: u64 = helpers::deser_seq_element(
279 &mut seq,
280 "request_id must be present and type u64.",
281 )?;
282 let registration: u64 = helpers::deser_seq_element(
283 &mut seq,
284 "registration must be present and object like.",
285 )?;
286 let details: Value = helpers::deser_seq_element(
287 &mut seq,
288 "Details must be present and object like.",
289 )?;
290 helpers::deser_value_is_object::<A, _>(&details, "Details must be object like.")?;
291 let args: Value = helpers::deser_args_kwargs_element(
292 &mut seq,
293 "Args must be array like or null.",
294 )?;
295 let kwargs: Value = helpers::deser_args_kwargs_element(
296 &mut seq,
297 "Kwargs must be object like or null.",
298 )?;
299 Ok(Invocation {
300 request_id,
301 registration,
302 details,
303 args,
304 kwargs,
305 })
306 }
307 }
308
309 deserializer.deserialize_struct(
310 "Invocation",
311 &["request_id", "registration", "details", "args", "kwargs"],
312 InvocationVisitor(
313 PhantomData,
314 PhantomData,
315 PhantomData,
316 PhantomData,
317 PhantomData,
318 PhantomData,
319 ),
320 )
321 }
322}
323
324#[cfg(test)]
325mod tests {
326 use serde_json::{from_str, to_string};
327
328 use super::Invocation;
329
330 #[test]
331 fn test() {
332 let d = r#"[68,6131533,9823529,{},["johnny"],{"firstname":"John","surname":"Doe"}]"#;
333 let mut ed = Invocation {
334 request_id: 6131533,
335 registration: 9823529,
336 details: serde_json::json!({}),
337 args: serde_json::Value::Null,
338 kwargs: serde_json::json!({"firstname":"John","surname":"Doe"}),
339 };
340 let ed2: Invocation = from_str(d).unwrap();
341 assert_ne!(ed, ed2);
342 ed.args = serde_json::json!(["johnny"]);
343 assert_eq!(ed, ed2);
344 let d2 = to_string(&ed).unwrap();
345 assert_eq!(d, d2);
346 }
347}