1use super::{helpers, MessageDirection, WampMessage};
2use crate::roles::Roles;
3use serde::de::{SeqAccess, Visitor};
4use serde::{Deserialize, Deserializer, Serialize};
5use serde_json::{json, Value};
6use std::fmt::Formatter;
7use std::marker::PhantomData;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct WampResult {
70 pub request_id: u64,
71 pub details: Value,
72 pub args: Value,
73 pub kwargs: Value,
74}
75
76#[macro_export]
77macro_rules! result {
123 ($request_id:expr) => {
124 result! {$request_id, json!({}), Value::Null, Value::Null}
125 };
126 ($request_id:expr, $details:expr) => {
127 result! {$request_id, $details, Value::Null, Value::Null}
128 };
129 ($request_id:expr, args: $args:expr) => {
130 result! {$request_id, serde_json::json!({}), $args, Value::Null}
131 };
132 ($request_id:expr, kwargs: $kwargs:expr) => {
133 result! {$request_id, serde_json::json!({}), Value::Null, $kwargs}
134 };
135 ($request_id:expr, args: $args:expr, kwargs: $kwargs:expr) => {
136 result! {$request_id, serde_json::json!({}), $args, $kwargs}
137 };
138 ($request_id:expr, $details:expr, args: $args:expr) => {
139 result! {$request_id, $details, $args, Value::Null}
140 };
141 ($request_id:expr, $details:expr, kwargs: $kwargs:expr) => {
142 result! {$request_id, $details, Value::Null, $kwargs}
143 };
144 ($request_id:expr, $details:expr, $args:expr, $kwargs:expr) => {
145 WampResult {
146 args: $args,
147 request_id: $request_id,
148 details: $details,
149 kwargs: $kwargs,
150 }
151 };
152}
153
154impl WampMessage for WampResult {
155 const ID: u64 = 50;
156
157 fn direction(role: Roles) -> &'static MessageDirection {
158 match role {
159 Roles::Callee => &MessageDirection {
160 receives: &false,
161 sends: &false,
162 },
163 Roles::Caller => &MessageDirection {
164 receives: &true,
165 sends: &false,
166 },
167 Roles::Publisher => &MessageDirection {
168 receives: &false,
169 sends: &false,
170 },
171 Roles::Subscriber => &MessageDirection {
172 receives: &false,
173 sends: &false,
174 },
175 Roles::Dealer => &MessageDirection {
176 receives: &false,
177 sends: &false,
178 },
179 Roles::Broker => &MessageDirection {
180 receives: &false,
181 sends: &true,
182 },
183 }
184 }
185}
186
187impl Serialize for WampResult {
188 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
189 where
190 S: serde::Serializer,
191 {
192 let details =
193 helpers::ser_value_is_object::<S, _>(&self.details, "details must be object like.")?;
194 let args =
195 helpers::ser_value_is_args::<S, _>(&self.args, "Args must be Array like or Null.")?;
196 let kwargs = helpers::ser_value_is_kwargs::<S, _>(
197 &self.kwargs,
198 "Kwargs must be Object like or Null.",
199 )?;
200 if args.is_null() {
201 if kwargs.is_null() {
202 (Self::ID, &self.request_id, details).serialize(serializer)
203 } else {
204 (Self::ID, &self.request_id, details, json!([]), kwargs).serialize(serializer)
205 }
206 } else {
207 if kwargs.is_null() {
208 (Self::ID, &self.request_id, details, args).serialize(serializer)
209 } else {
210 (Self::ID, &self.request_id, details, args, kwargs).serialize(serializer)
211 }
212 }
213 }
214}
215
216impl<'de> Deserialize<'de> for WampResult {
217 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
218 where
219 D: Deserializer<'de>,
220 {
221 struct WampResultVisitor(
222 PhantomData<u64>,
223 PhantomData<u64>,
224 PhantomData<Value>,
225 PhantomData<Value>,
226 PhantomData<Value>,
227 );
228
229 impl<'vi> Visitor<'vi> for WampResultVisitor {
230 type Value = WampResult;
231 fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
232 formatter.write_str("A sequence of WampResult components.")
233 }
234
235 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
236 where
237 A: SeqAccess<'vi>,
238 {
239 let message_id: u64 = helpers::deser_seq_element(
240 &mut seq,
241 "Message ID must be present and type u8.",
242 )?;
243 helpers::validate_id::<WampResult, A, _>(&message_id, "WampResult")?;
244 let request_id: u64 = helpers::deser_seq_element(
245 &mut seq,
246 "Request ID must be present and type u64.",
247 )?;
248 let details: Value = helpers::deser_seq_element(
249 &mut seq,
250 "details must be present and object like.",
251 )?;
252 helpers::deser_value_is_object::<A, _>(&details, "details must be object like.")?;
253 let args: Value = helpers::deser_args_kwargs_element(
254 &mut seq,
255 "Args must be array like or null.",
256 )?;
257 let kwargs: Value = helpers::deser_args_kwargs_element(
258 &mut seq,
259 "Kwargs must be object like or null.",
260 )?;
261 Ok(WampResult {
262 request_id,
263 details,
264 args,
265 kwargs,
266 })
267 }
268 }
269
270 deserializer.deserialize_struct(
271 "WampResult",
272 &["request_id", "details", "args", "kwargs"],
273 WampResultVisitor(
274 PhantomData,
275 PhantomData,
276 PhantomData,
277 PhantomData,
278 PhantomData,
279 ),
280 )
281 }
282}
283
284#[cfg(test)]
285mod tests {
286 use serde_json::{from_str, json, to_string};
287
288 use super::WampResult;
289
290 #[test]
291 fn test() {
292 let d1 = r#"[50,7814135,{},[],{"karma":10,"userid":123}]"#;
293 let mut w1 = WampResult {
294 request_id: 7814135,
295 details: json!({}),
296 args: serde_json::Value::Null,
297 kwargs: json!({"userid":123,"karma":10}),
298 };
299 assert_ne!(from_str::<WampResult>(d1).unwrap(), w1);
300 w1.args = json!([]);
301 assert_eq!(from_str::<WampResult>(d1).unwrap(), w1);
302 assert_eq!(to_string(&w1).unwrap(), d1);
303 }
304}