wamp_core/messages/
mod.rs

1pub mod abort;
2pub mod authenticate;
3pub mod call;
4pub mod cancel;
5pub mod challenge;
6pub mod error;
7pub mod event;
8pub mod goodbye;
9pub mod hello;
10pub mod interrupt;
11pub mod invocation;
12pub mod publish;
13pub mod published;
14pub mod register;
15pub mod registered;
16pub mod result;
17pub mod subscribe;
18pub mod subscribed;
19pub mod unregister;
20pub mod unregistered;
21pub mod unsubscribe;
22pub mod unsubscribed;
23pub mod welcome;
24pub mod r#yield;
25
26pub use abort::Abort;
27pub use authenticate::Authenticate;
28pub use call::Call;
29pub use cancel::Cancel;
30pub use challenge::Challenge;
31pub use error::{WampError, WampErrorEvent};
32pub use event::Event;
33pub use goodbye::Goodbye;
34pub use hello::Hello;
35pub use interrupt::Interrupt;
36pub use invocation::Invocation;
37pub use publish::Publish;
38pub use published::Published;
39pub use r#yield::Yield;
40pub use register::Register;
41pub use registered::Registered;
42pub use result::WampResult;
43pub use subscribe::Subscribe;
44pub use subscribed::Subscribed;
45use tungstenite::Message;
46pub use unregister::Unregister;
47pub use unregistered::Unregistered;
48pub use unsubscribe::Unsubscribe;
49pub use unsubscribed::Unsubscribed;
50pub use welcome::Welcome;
51
52use serde::{de, Deserialize, Deserializer};
53use serde_json::{from_str, from_value, json, Value};
54
55use crate::roles::Roles;
56
57/// # Message parsing helpers
58///
59/// These helpers are internal methods for parsing different aspects of each message.
60/// This is very unorganized and could use some clarity.
61///
62/// The plan for current future releases is to make a macro that automatically
63/// creates wamp message parsers, there are two main reasons for this.
64///
65/// > 1. Macros will allow for a "consistent" state of messages that does not change per instance.
66/// >
67/// > 2. Macros will allow for easy creation of WAMP "Extension" messages.
68///
69/// With that said, these helpers, while clear in definition, can be moved into the rest of the "macro"
70/// code when the time comes, as that will be the primary implentation of the macro, is to create
71/// the Serializer and Deserializer (as well as implement a couple other helper traits for the library)
72///
73/// There is a good change that at the point I am talking about, this will become its own proc macro crate.
74pub(crate) mod helpers {
75
76    use serde::{
77        de::{self, SeqAccess},
78        ser::Error,
79        Deserialize, Serializer,
80    };
81    use serde_json::Value;
82    use std::fmt::Display;
83
84    use super::WampMessage;
85
86    pub(crate) fn deser_seq_element<
87        'de,
88        T: PartialEq + Deserialize<'de>,
89        E: Display,
90        A: SeqAccess<'de>,
91    >(
92        seq: &mut A,
93        error: E,
94    ) -> Result<T, <A as SeqAccess<'de>>::Error> {
95        let element: Option<T> = seq.next_element()?;
96        if element != None {
97            Ok(element.unwrap())
98        } else {
99            Err(serde::de::Error::custom(error))
100        }
101    }
102
103    pub(crate) fn deser_args_kwargs_element<'de, E: Display, A: SeqAccess<'de>>(
104        seq: &mut A,
105        error: E,
106    ) -> Result<Value, <A as SeqAccess<'de>>::Error> {
107        let element: Option<Value> = seq.next_element()?;
108        if let Some(element) = element {
109            if element.is_object() || element.is_array() {
110                Ok(element)
111            } else {
112                Err(serde::de::Error::custom(error))
113            }
114        } else {
115            Ok(Value::Null)
116        }
117    }
118
119    pub(crate) fn validate_id<'de, M: WampMessage, A: SeqAccess<'de>, E: Display>(
120        id: &u64,
121        name: E,
122    ) -> Result<(), A::Error> {
123        if &M::ID == id {
124            Ok(())
125        } else {
126            Err(de::Error::custom(format!(
127                "{name} has invalid ID {id}. The ID for {name} must be {}",
128                M::ID
129            )))
130        }
131    }
132
133    pub(crate) fn deser_value_is_object<'de, A: SeqAccess<'de>, E: Display>(
134        v: &Value,
135        e: E,
136    ) -> Result<(), A::Error> {
137        if v.is_object() {
138            Ok(())
139        } else {
140            Err(de::Error::custom(e))
141        }
142    }
143
144    pub(crate) fn ser_value_is_object<S: Serializer, T: Display>(
145        v: &Value,
146        e: T,
147    ) -> Result<&Value, S::Error> {
148        if v.is_object() {
149            Ok(v)
150        } else {
151            Err(S::Error::custom(e))
152        }
153    }
154
155    pub(crate) fn ser_value_is_args<S: Serializer, T: Display>(
156        v: &Value,
157        e: T,
158    ) -> Result<&Value, S::Error> {
159        if v.is_array() || v.is_null() {
160            Ok(v)
161        } else {
162            Err(S::Error::custom(e))
163        }
164    }
165
166    pub(crate) fn ser_value_is_kwargs<S: Serializer, T: Display>(
167        v: &Value,
168        e: T,
169    ) -> Result<&Value, S::Error> {
170        if v.is_object() || v.is_null() {
171            Ok(v)
172        } else {
173            Err(S::Error::custom(e))
174        }
175    }
176}
177
178#[derive(Debug, PartialEq, PartialOrd)]
179/// # Message Direction
180/// Indicates the Message Direction for a specified Role.
181///
182/// Receives means that the specified Role is allowed to receive the message.
183/// Sends means that the specified Role allowed to send the message.
184pub struct MessageDirection {
185    pub receives: &'static bool,
186    pub sends: &'static bool,
187}
188
189pub trait WampMessage {
190    const ID: u64;
191
192    /// # Direction method
193    /// Indicates the Message Direction for a specified Role.
194    ///
195    /// Receives means that the specified Role is allowed to receive the message.
196    /// Sends means that the specified Role allowed to send the message.
197    fn direction(role: Roles) -> &'static MessageDirection;
198}
199
200#[derive(Debug, Clone, PartialEq, Eq)]
201/// # Messages Enum
202/// This represents each of the messages described in the WAMP protocol.
203///
204/// This includes its own deserializer (you should serialize using the inner struct always).
205///
206/// It also implements `From<*n> for Messages` where n = each WAMP message.
207/// # Examples
208/// ```
209/// use wamp_core::messages::{Call, Messages};
210/// use wamp_core::call;
211/// use serde_json::{Value, json, from_str};
212///
213/// let message = Messages::from(call!("topic"));
214///
215/// // Which is the same as this:
216/// let mut message2 = Messages::Call(Call {
217///     request_id: 1,
218///     options: json!({}),
219///     procedure: "topic".to_string(),
220///     args: Value::Null,
221///     kwargs: Value::Null
222/// });
223/// assert_eq!(message, message2);
224///
225/// // Lets make a raw string to pass to the deserializer (this is a Call message)
226/// let data = r#"[48,1,{},"topic"]"#;
227///
228/// // Deserialize the raw string
229/// let message3 = from_str::<Messages>(data).unwrap();
230///
231/// assert_eq!(message2, message3);
232/// ```
233pub enum Messages {
234    Abort(Abort),
235    Authenticate(Authenticate),
236    Call(Call),
237    Cancel(Cancel),
238    Challenge(Challenge),
239    Error(WampError),
240    Event(Event),
241    Goodbye(Goodbye),
242    Hello(Hello),
243    Interrupt(Interrupt),
244    Invocation(Invocation),
245    Publish(Publish),
246    Published(Published),
247    Register(Register),
248    Registered(Registered),
249    Result(WampResult),
250    Subscribe(Subscribe),
251    Subscribed(Subscribed),
252    Unregister(Unregister),
253    Unregistered(Unregistered),
254    Unsubscribe(Unsubscribe),
255    Unsubscribed(Unsubscribed),
256    Welcome(Welcome),
257    Yield(Yield),
258    Extension(Vec<Value>),
259}
260
261impl Messages {
262    /// # Get Message ID
263    ///
264    /// Get the message ID of a WAMP message. This uses the static u64 for any known WAMP messages.
265    ///
266    /// For Extension messages, it attempts to get the ID and returns None otherwise.
267    ///
268    /// ## Examples
269    /// ```
270    /// use wamp_core::call;
271    /// use wamp_core::messages::Messages;
272    ///
273    /// let message = Messages::from(call!("topic"));
274    ///
275    /// let message_id = message.id();
276    ///
277    /// assert_eq!(message_id, Some(48));
278    /// ```
279    pub fn id(&self) -> Option<u64> {
280        match self {
281            Messages::Authenticate(_) => Some(Authenticate::ID),
282            Messages::Abort(_) => Some(Abort::ID),
283            Messages::Call(_) => Some(Call::ID),
284            Messages::Cancel(_) => Some(Cancel::ID),
285            Messages::Challenge(_) => Some(Authenticate::ID),
286            Messages::Error(_) => Some(WampError::ID),
287            Messages::Event(_) => Some(Event::ID),
288            Messages::Goodbye(_) => Some(Goodbye::ID),
289            Messages::Hello(_) => Some(Hello::ID),
290            Messages::Interrupt(_) => Some(Interrupt::ID),
291            Messages::Invocation(_) => Some(Invocation::ID),
292            Messages::Publish(_) => Some(Publish::ID),
293            Messages::Published(_) => Some(Published::ID),
294            Messages::Register(_) => Some(Register::ID),
295            Messages::Registered(_) => Some(Registered::ID),
296            Messages::Result(_) => Some(WampResult::ID),
297            Messages::Subscribe(_) => Some(Subscribe::ID),
298            Messages::Subscribed(_) => Some(Subscribed::ID),
299            Messages::Unregister(_) => Some(Unregister::ID),
300            Messages::Unregistered(_) => Some(Unregistered::ID),
301            Messages::Unsubscribe(_) => Some(Unsubscribe::ID),
302            Messages::Unsubscribed(_) => Some(Unsubscribed::ID),
303            Messages::Welcome(_) => Some(Welcome::ID),
304            Messages::Yield(_) => Some(Yield::ID),
305            Messages::Extension(values) => {
306                if let Some(value) = values.first() {
307                    value.as_u64()
308                } else {
309                    None
310                }
311            }
312        }
313    }
314}
315
316macro_rules! try_from_messages {
317    ($i: ident) => {
318        impl From<$i> for Messages {
319            fn from(v: $i) -> Messages {
320                Messages::$i(v)
321            }
322        }
323
324        impl From<Messages> for $i {
325            fn from(v: Messages) -> $i {
326                v.into()
327            }
328        }
329    };
330}
331
332try_from_messages!(Abort);
333try_from_messages!(Authenticate);
334try_from_messages!(Call);
335try_from_messages!(Cancel);
336try_from_messages!(Challenge);
337
338// Created manually because the enum member name is not the same as struct name.
339impl From<WampError> for Messages {
340    fn from(v: WampError) -> Self {
341        Messages::Error(v)
342    }
343}
344
345impl TryFrom<Messages> for WampError {
346    type Error = crate::error::Error;
347    fn try_from(v: Messages) -> Result<WampError, Self::Error> {
348        if let Messages::Error(v) = v {
349            Ok(v)
350        } else {
351            Err(crate::error::Error::InvalidMessageEnumMember)
352        }
353    }
354}
355
356impl TryFrom<tungstenite::Message> for Messages {
357    type Error = crate::error::Error;
358
359    fn try_from(value: Message) -> Result<Self, crate::error::Error> {
360        Ok(from_str(value.to_text()?)?)
361    }
362}
363
364impl From<WampResult> for Messages {
365    fn from(v: WampResult) -> Self {
366        Messages::Result(v)
367    }
368}
369
370impl TryFrom<Messages> for WampResult {
371    type Error = crate::error::Error;
372    fn try_from(v: Messages) -> Result<WampResult, Self::Error> {
373        if let Messages::Result(v) = v {
374            Ok(v)
375        } else {
376            Err(crate::error::Error::InvalidMessageEnumMember)
377        }
378    }
379}
380
381try_from_messages!(Event);
382try_from_messages!(Goodbye);
383try_from_messages!(Hello);
384try_from_messages!(Interrupt);
385try_from_messages!(Invocation);
386try_from_messages!(Publish);
387try_from_messages!(Published);
388try_from_messages!(Register);
389try_from_messages!(Registered);
390try_from_messages!(Subscribe);
391try_from_messages!(Subscribed);
392try_from_messages!(Unregister);
393try_from_messages!(Unregistered);
394try_from_messages!(Unsubscribe);
395try_from_messages!(Unsubscribed);
396try_from_messages!(Welcome);
397try_from_messages!(Yield);
398
399impl<'de> Deserialize<'de> for Messages {
400    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
401    where
402        D: serde::Deserializer<'de>,
403    {
404        let wamp_components: Vec<Value> = Deserialize::deserialize(deserializer)?;
405        let wamp_message_id = match wamp_components.first() {
406            Some(v) => match v.as_u64() {
407                Some(v) => Ok(v),
408                None => Err(de::Error::custom("")),
409            },
410            None => Err(de::Error::custom("value")),
411        }?;
412
413        fn helper<'d, T, D>(wamp_components: Vec<Value>) -> Result<T, D::Error>
414        where
415            T: for<'de> Deserialize<'de>,
416            D: Deserializer<'d>,
417        {
418            let value: T = from_value(json!(wamp_components)).map_err(de::Error::custom)?;
419            Ok(value)
420        }
421
422        match wamp_message_id {
423            Abort::ID => Ok(Self::Abort(helper::<Abort, D>(wamp_components)?)),
424            Authenticate::ID => Ok(Self::Authenticate(helper::<Authenticate, D>(
425                wamp_components,
426            )?)),
427            Call::ID => Ok(Self::Call(helper::<Call, D>(wamp_components)?)),
428            Cancel::ID => Ok(Self::Cancel(helper::<Cancel, D>(wamp_components)?)),
429            Challenge::ID => Ok(Self::Challenge(helper::<Challenge, D>(wamp_components)?)),
430            WampError::ID => Ok(Self::Error(helper::<WampError, D>(wamp_components)?)),
431            Event::ID => Ok(Self::Event(helper::<Event, D>(wamp_components)?)),
432            Goodbye::ID => Ok(Self::Goodbye(helper::<Goodbye, D>(wamp_components)?)),
433            Hello::ID => Ok(Self::Hello(helper::<Hello, D>(wamp_components)?)),
434            Interrupt::ID => Ok(Self::Interrupt(helper::<Interrupt, D>(wamp_components)?)),
435            Invocation::ID => Ok(Self::Invocation(helper::<Invocation, D>(wamp_components)?)),
436            Publish::ID => Ok(Self::Publish(helper::<Publish, D>(wamp_components)?)),
437            Published::ID => Ok(Self::Published(helper::<Published, D>(wamp_components)?)),
438            Register::ID => Ok(Self::Register(helper::<Register, D>(wamp_components)?)),
439            Registered::ID => Ok(Self::Registered(helper::<Registered, D>(wamp_components)?)),
440            WampResult::ID => Ok(Self::Result(helper::<WampResult, D>(wamp_components)?)),
441            Subscribe::ID => Ok(Self::Subscribe(helper::<Subscribe, D>(wamp_components)?)),
442            Subscribed::ID => Ok(Self::Subscribed(helper::<Subscribed, D>(wamp_components)?)),
443            Unregister::ID => Ok(Self::Unregister(helper::<Unregister, D>(wamp_components)?)),
444            Unregistered::ID => Ok(Self::Unregistered(helper::<Unregistered, D>(
445                wamp_components,
446            )?)),
447            Unsubscribe::ID => Ok(Self::Unsubscribe(helper::<Unsubscribe, D>(
448                wamp_components,
449            )?)),
450            Unsubscribed::ID => Ok(Self::Unsubscribed(helper::<Unsubscribed, D>(
451                wamp_components,
452            )?)),
453            Welcome::ID => Ok(Self::Welcome(helper::<Welcome, D>(wamp_components)?)),
454            Yield::ID => Ok(Self::Yield(helper::<Yield, D>(wamp_components)?)),
455            _ => Ok(Self::Extension(wamp_components)),
456        }
457    }
458}