wamp_core/messages/
interrupt.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/// # Interrupt - [wamp-proto](https://wamp-proto.org/wamp_latest_ietf.html#name-interrupt)
12/// Represents an interrupt message in the WAMP protocol.
13/// ## Examples
14/// ```
15/// use wamp_core::messages::Interrupt;
16/// use wamp_core::interrupt;
17/// use serde_json::json;
18/// # let mut interrupt_message2 = interrupt!(1);
19///
20/// let interrupt_message = Interrupt {
21///     request_id: 1,
22///     options: json!({})
23/// };
24///
25/// # assert_eq!(interrupt_message, interrupt_message2);
26/// ```
27/// ### Deserializer
28/// Implements serde Deserialize trait for interrupt
29/// ```
30/// use wamp_core::messages::Interrupt;
31/// use serde_json::from_str;
32///
33/// // Here is our raw json data string
34/// let data = r#"[69,1,{}]"#;
35///
36/// // Here we convert it to an `interrupt` frame
37/// let interrupt = from_str::<Interrupt>(data).unwrap();
38///
39/// // Confirm that our request_id and options deserialized
40/// assert_eq!(interrupt.request_id, 1);
41/// assert_eq!(interrupt.options, serde_json::json!({}));
42/// ```
43/// ### Serializer
44/// Implements serde Serialize trait for interrupt
45/// ```
46/// use wamp_core::messages::Interrupt;
47/// use serde_json::{json, to_string};
48///
49/// // Create an interrupt message
50/// let interrupt = Interrupt {
51///     request_id: 1,
52///     options: json!({ "key": "value" })
53/// };
54///
55/// // Establish raw json data string
56/// let data = r#"[69,1,{"key":"value"}]"#;
57///
58/// // Here we convert it from an `interrupt` frame, to a string representation.
59/// let interrupt = to_string(&interrupt).unwrap();
60///
61/// // Confirm that our interrupt frame strings are equal to each other
62/// assert_eq!(interrupt, data);
63/// ```
64pub struct Interrupt {
65    pub request_id: u64,
66    pub options: Value,
67}
68
69#[macro_export]
70/// # Interrupt Macro - [wamp-proto](https://wamp-proto.org/wamp_latest_ietf.html#name-interrupt)
71/// Macro that allows for default empty implementation of options object on Cabcel.
72/// ## Examples
73/// ```
74/// use wamp_core::messages::{self, Interrupt};
75/// use wamp_core::interrupt;
76/// use serde_json::json;
77///
78/// // Construct with default empty options object
79/// let request_id = 1;
80/// let mut interrupt_message = interrupt!(request_id);
81/// assert_eq!(interrupt_message.options, json!({}));
82///
83/// // Construct with custom options
84/// let interrupt_message2 = interrupt!(1, json!({
85///     "key": "value"
86/// }));
87///
88/// assert_ne!(interrupt_message, interrupt_message2);
89/// interrupt_message.options = json!({ "key": "value" });
90/// assert_eq!(interrupt_message, interrupt_message2);
91///
92/// // These macro invocations are the same as the following:
93/// let interrupt_message3 = Interrupt {
94///     request_id: 1,
95///     options: json!({
96///         "key": "value"
97///     })
98/// };
99///
100/// assert_eq!(interrupt_message, interrupt_message3);
101/// assert_eq!(interrupt_message2, interrupt_message3);
102/// ```
103macro_rules! interrupt {
104    ($request_id:expr) => {
105        interrupt! {$request_id, serde_json::json!({})}
106    };
107    ($request_id:expr, $options:expr) => {
108        Interrupt {
109            request_id: $request_id,
110            options: $options,
111        }
112    };
113}
114
115impl WampMessage for Interrupt {
116    const ID: u64 = 69;
117
118    fn direction(role: Roles) -> &'static MessageDirection {
119        match role {
120            Roles::Callee => &MessageDirection {
121                receives: &true,
122                sends: &false,
123            },
124            Roles::Caller => &MessageDirection {
125                receives: &false,
126                sends: &false,
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 Interrupt {
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 Interrupt {
160    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
161    where
162        D: serde::Deserializer<'de>,
163    {
164        struct InterruptVisitor(PhantomData<u8>, PhantomData<String>, PhantomData<Value>);
165
166        impl<'vi> Visitor<'vi> for InterruptVisitor {
167            type Value = Interrupt;
168
169            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
170                formatter.write_str("WAMP Interrupt 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::<Interrupt, A, _>(&message_id, "Interrupt")?;
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(Interrupt {
186                    request_id,
187                    options,
188                })
189            }
190        }
191
192        deserializer.deserialize_struct(
193            "Interrupt",
194            &["request_id", "options"],
195            InterruptVisitor(PhantomData, PhantomData, PhantomData),
196        )
197    }
198}
199/*
200#[cfg(test)]
201mod tests {
202    use serde_json::{to_string, from_str};
203
204    //use crate::messages::interrupt::Interrupt;
205
206
207    #[test]
208    fn test() {
209        let d1 = r#"[69,3,{}]"#;
210        let g1 = Interrupt {
211            options: serde_json::json!({}),
212            request_id: 3
213        };
214        let d2 = to_string(&g1).unwrap();
215        assert_eq!(d1, d2);
216        let g2: Interrupt = from_str(d1).unwrap();
217        assert_eq!(g1, g2);
218    }
219}
220*/