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}