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