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