wamp_core/messages/
register.rs

1use std::marker::PhantomData;
2
3use serde::{de::Visitor, Deserialize, Serialize};
4use serde_json::Value;
5
6use crate::{messages::helpers, roles::Roles};
7
8use super::{MessageDirection, WampMessage};
9
10#[derive(Debug, Clone, PartialEq, Eq)]
11/// # Register - [wamp-proto](https://wamp-proto.org/wamp_latest_ietf.html#name-register-2)
12/// Represents an Register frame in the WAMP protocol.
13/// ## Examples
14/// ```
15/// use wamp_core::messages::Register;
16/// use wamp_core::register;
17/// use serde_json::json;
18///
19/// # let mut registerd1 = register!("procedure");
20///
21/// let registerd = Register {
22///     request_id: 1,
23///     procedure: "procedure".to_string(),
24///     options: json!({})
25/// };
26/// # registerd1.options = json!({});
27/// # assert_eq!(registerd, registerd1);
28/// ```
29/// ### Serializer
30/// Implements serde Serialize trait for Register
31/// ```
32/// use wamp_core::messages::Register;
33/// use serde_json::{json, to_string};
34/// use wamp_core::register;
35///
36/// let data = r#"[64,1,{},"com.myapp.myprocedure1"]"#;
37///
38/// let register1 = register!("com.myapp.myprocedure1");
39///
40/// let register = Register {
41///     request_id: 1,
42///     procedure: "com.myapp.myprocedure1".to_string(),
43///     options: json!({})
44/// };
45///
46/// let data2 = to_string(&register1).unwrap();
47/// let data3 = to_string(&register).unwrap();
48///
49/// assert_eq!(data, data2);
50/// assert_eq!(data2, data3);
51/// ```
52/// ### Deserializer
53/// Implements serde Deserialize trait for register
54/// ```
55/// use wamp_core::messages::Register;
56/// use serde_json::from_str;
57/// use wamp_core::register;
58///
59/// let data = r#"[64,1,{},"com.myapp.myprocedure1"]"#;
60///
61/// let register = from_str::<Register>(data).unwrap();
62///
63/// let register2 = register!("com.myapp.myprocedure1");
64///
65/// assert_eq!(register, register2);
66/// ```
67pub struct Register {
68    pub request_id: u64,
69    pub options: Value,
70    pub procedure: String,
71}
72
73#[macro_export]
74/// # register Macro - [wamp-proto](https://wamp-proto.org/wamp_latest_ietf.html#name-register-2)
75/// Macro that allows for default implementations of Register with empty or custom options and auto incremented request id.
76/// ## Examples
77/// ```
78/// use wamp_core::messages::{self, Register};
79/// use wamp_core::register;
80/// use serde_json::json;
81///
82/// let procedure = "procedure";
83///
84/// // Construct with default empty options object
85/// let register = register!(procedure);
86///
87/// let register2 = Register {
88///     request_id: 1,
89///     options: json!({}),
90///     procedure: procedure.to_string()
91/// };
92///
93/// assert_eq!(register, register2);
94/// ```
95macro_rules! register {
96    ($procedure:expr) => {
97        register! {$procedure, serde_json::json!({})}
98    };
99    ($procedure:expr, $options:expr) => {
100        Register {
101            procedure: $procedure.to_string(),
102            options: $options,
103            request_id: $crate::factories::increment(),
104        }
105    };
106}
107
108impl WampMessage for Register {
109    const ID: u64 = 64;
110
111    fn direction(role: Roles) -> &'static MessageDirection {
112        match role {
113            Roles::Callee => &MessageDirection {
114                receives: &false,
115                sends: &true,
116            },
117            Roles::Caller => &MessageDirection {
118                receives: &false,
119                sends: &false,
120            },
121            Roles::Publisher => &MessageDirection {
122                receives: &false,
123                sends: &false,
124            },
125            Roles::Subscriber => &MessageDirection {
126                receives: &false,
127                sends: &false,
128            },
129            Roles::Dealer => &MessageDirection {
130                receives: &true,
131                sends: &false,
132            },
133            Roles::Broker => &MessageDirection {
134                receives: &false,
135                sends: &false,
136            },
137        }
138    }
139}
140
141impl Serialize for Register {
142    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
143    where
144        S: serde::Serializer,
145    {
146        (Self::ID, &self.request_id, &self.options, &self.procedure).serialize(serializer)
147    }
148}
149
150impl<'de> Deserialize<'de> for Register {
151    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
152    where
153        D: serde::Deserializer<'de>,
154    {
155        struct RegisterVisitor(
156            PhantomData<u64>,
157            PhantomData<u64>,
158            PhantomData<Value>,
159            PhantomData<String>,
160        );
161
162        impl<'vi> Visitor<'vi> for RegisterVisitor {
163            type Value = Register;
164
165            fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
166                formatter.write_str("A sequence of Register components.")
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 u64.",
176                )?;
177                helpers::validate_id::<Register, A, _>(&message_id, "Register")?;
178                let request_id: u64 = helpers::deser_seq_element(
179                    &mut seq,
180                    "Request ID must be present and type u64",
181                )?;
182                let options: Value = helpers::deser_seq_element(
183                    &mut seq,
184                    "options must be present and object like",
185                )?;
186                helpers::deser_value_is_object::<A, _>(&options, "options must be object like.")?;
187                let procedure: String = helpers::deser_seq_element(
188                    &mut seq,
189                    "procedure URI must be present and type String",
190                )?;
191                helpers::deser_value_is_object::<A, _>(&options, "options must be object like.")?;
192                Ok(Register {
193                    request_id,
194                    options,
195                    procedure,
196                })
197            }
198        }
199
200        deserializer.deserialize_struct(
201            "Register",
202            &["request_id", "options", "procedure"],
203            RegisterVisitor(PhantomData, PhantomData, PhantomData, PhantomData),
204        )
205    }
206}