1use quick_xml::{events::Event, name::QName, Reader, Writer};
5use serde::Deserialize;
6use serde_transcode::transcode;
7
8mod error;
9mod util;
10mod value;
11
12use util::{ReaderExt, ValueDeserializer, ValueSerializer, WriterExt};
13
14pub use error::{Error, Fault, Result};
15pub use value::{to_value, Value};
16
17pub fn response_from_str<'a, T>(input: &'a str) -> Result<T>
30where
31 T: serde::de::Deserialize<'a>,
32{
33 let mut reader = Reader::from_str(input);
34 reader.expand_empty_elements(true);
35 reader.trim_text(true);
36
37 loop {
40 match reader.read_event().map_err(error::DecodingError::from)? {
41 Event::Decl(_) => continue,
42 Event::Start(e) if e.name() == QName(b"methodResponse") => {
43 break;
44 }
45 e => return Err(error::DecodingError::UnexpectedEvent(format!("{:?}", e)).into()),
46 };
47 }
48
49 match reader.read_event().map_err(error::DecodingError::from)? {
50 Event::Start(e) if e.name() == QName(b"params") => {
51 reader.expect_tag(QName(b"param"))?;
52 reader.expect_tag(QName(b"value"))?;
53 let deserializer = ValueDeserializer::new(&mut reader)?;
54 let ret = T::deserialize(deserializer)?;
55 reader
56 .read_to_end(QName(b"param"))
57 .map_err(error::DecodingError::from)?;
58 reader
59 .read_to_end(e.name())
60 .map_err(error::DecodingError::from)?;
61 Ok(ret)
62 }
63 Event::Start(e) if e.name() == QName(b"fault") => {
64 reader.expect_tag(QName(b"value"))?;
67 let deserializer = ValueDeserializer::new(&mut reader)?;
68 let fault: Fault = Fault::deserialize(deserializer)?;
69
70 reader
74 .read_to_end(e.name())
75 .map_err(error::DecodingError::from)?;
76
77 Err(fault.into())
78 }
79 e => Err(error::DecodingError::UnexpectedEvent(format!("{:?}", e)).into()),
80 }
81}
82
83pub fn response_to_string(params: impl Iterator<Item = Value>) -> Result<String> {
93 let mut writer = Writer::new(Vec::new());
94 writer.write_decl()?;
95
96 writer.write_start_tag("methodResponse")?;
97 writer.write_start_tag("params")?;
98 for value in params {
99 writer.write_start_tag("param")?;
100
101 let deserializer = value::Deserializer::from_value(value);
102 let serializer = ValueSerializer::new(&mut writer);
103 transcode(deserializer, serializer)?;
104
105 writer.write_end_tag("param")?;
106 }
107 writer.write_end_tag("params")?;
108 writer.write_end_tag("methodResponse")?;
109 Ok(String::from_utf8(writer.into_inner()).map_err(error::EncodingError::from)?)
110}
111
112pub fn request_from_str(request: &str) -> Result<(String, Vec<Value>)> {
118 let mut reader = Reader::from_str(request);
119 reader.expand_empty_elements(true);
120 reader.trim_text(true);
121
122 loop {
124 match reader.read_event().map_err(error::DecodingError::from)? {
125 Event::Decl(_) => continue,
126 Event::Start(e) if e.name() == QName(b"methodCall") => {
127 break;
128 }
129 e => return Err(error::DecodingError::UnexpectedEvent(format!("{:?}", e)).into()),
130 };
131 }
132
133 let method_name = match reader.read_event().map_err(error::DecodingError::from)? {
138 Event::Start(e) if e.name() == QName(b"methodName") => reader
139 .read_text(e.name())
140 .map_err(error::DecodingError::from)?,
141 e => return Err(error::DecodingError::UnexpectedEvent(format!("{:?}", e)).into()),
142 };
143
144 match reader.read_event().map_err(error::DecodingError::from)? {
145 Event::Start(e) if e.name() == QName(b"params") => {
146 let mut params = Vec::new();
147
148 let params = loop {
149 break match reader.read_event().map_err(error::DecodingError::from)? {
150 Event::Start(e) if e.name() == QName(b"param") => {
152 reader.expect_tag(QName(b"value"))?;
153 let deserializer = ValueDeserializer::new(&mut reader)?;
154 let serializer = value::Serializer::new();
155 let x = transcode(deserializer, serializer)?;
156 params.push(x);
157
158 reader
159 .read_to_end(e.name())
160 .map_err(error::DecodingError::from)?;
161
162 continue;
163 }
164
165 Event::End(e) if e.name() == QName(b"params") => params,
167 e => {
168 return Err(error::DecodingError::UnexpectedEvent(format!("{:?}", e)).into())
169 }
170 };
171 };
172
173 Ok((method_name.into_owned(), params))
177 }
178 e => Err(error::DecodingError::UnexpectedEvent(format!("{:?}", e)).into()),
179 }
180}
181
182pub fn request_to_string(name: &str, args: Vec<Value>) -> Result<String> {
189 let mut writer = Writer::new(Vec::new());
190
191 writer.write_decl()?;
192
193 writer.write_start_tag("methodCall")?;
194 writer.write_tag("methodName", name)?;
195
196 writer.write_start_tag("params")?;
197 for value in args {
198 writer.write_start_tag("param")?;
199
200 let deserializer = value::Deserializer::from_value(value);
201 let serializer = ValueSerializer::new(&mut writer);
202 transcode(deserializer, serializer)?;
203
204 writer.write_end_tag("param")?;
205 }
206 writer.write_end_tag("params")?;
207 writer.write_end_tag("methodCall")?;
208
209 Ok(String::from_utf8(writer.into_inner()).map_err(error::EncodingError::from)?)
210}
211
212pub fn value_from_str(input: &str) -> Result<Value> {
218 let mut reader = Reader::from_str(input);
219 reader.expand_empty_elements(true);
220 reader.trim_text(true);
221
222 reader.expect_tag(QName(b"value"))?;
223 let deserializer = ValueDeserializer::new(&mut reader)?;
224 let serializer = value::Serializer::new();
225 transcode(deserializer, serializer)
226}
227
228pub fn value_to_string<I>(val: I) -> Result<String>
235where
236 I: Into<Value>,
237{
238 let d = value::Deserializer::from_value(val.into());
239 let mut writer = Writer::new(Vec::new());
240 let s = ValueSerializer::new(&mut writer);
241 transcode(d, s)?;
242 Ok(String::from_utf8(writer.into_inner()).map_err(error::EncodingError::from)?)
243}
244
245pub fn from_values<T: serde::de::DeserializeOwned>(values: Vec<Value>) -> Result<T> {
262 let val = Value::Array(values);
266 from_value(val)
267}
268
269pub fn from_value<T: serde::de::DeserializeOwned>(value: Value) -> Result<T> {
277 let d = value::Deserializer::from_value(value);
278 T::deserialize(d)
279}
280
281#[cfg(test)]
282mod tests {
283 use super::*;
284
285 #[test]
286 fn test_stringify_request() {
287 assert_eq!(
288 request_to_string("hello world", vec![]).unwrap(),
289 r#"<?xml version="1.0" encoding="utf-8"?><methodCall><methodName>hello world</methodName><params></params></methodCall>"#.to_owned()
290 )
291 }
292
293 #[test]
295 fn parse_int_values() {
296 assert_eq!(
297 value_from_str("<value><int>42</int></value>")
298 .unwrap()
299 .as_i32(),
300 Some(42)
301 );
302
303 assert_eq!(
304 value_from_str("<value><int>-42</int></value>")
305 .unwrap()
306 .as_i32(),
307 Some(-42)
308 );
309
310 assert_eq!(
311 value_from_str("<value><int>2147483647</int></value>")
312 .unwrap()
313 .as_i32(),
314 Some(2147483647)
315 );
316 }
317
318 #[test]
320 fn parse_long_values() {
321 assert_eq!(
322 value_from_str("<value><int>42</int></value>")
323 .unwrap()
324 .as_i64(),
325 Some(42)
326 );
327
328 assert_eq!(
329 value_from_str("<value><int>9223372036854775807</int></value>")
330 .unwrap()
331 .as_i64(),
332 Some(9223372036854775807)
333 );
334 }
335
336 #[test]
338 fn parse_boolean_values() {
339 assert_eq!(
340 value_from_str("<value><boolean>1</boolean></value>")
341 .unwrap()
342 .as_bool(),
343 Some(true)
344 );
345 assert_eq!(
346 value_from_str("<value><boolean>0</boolean></value>")
347 .unwrap()
348 .as_bool(),
349 Some(false)
350 );
351 }
352
353 #[test]
356 fn parse_string_values() {
357 assert_eq!(
358 value_from_str("<value><string>hello</string></value>")
359 .unwrap()
360 .as_str(),
361 Some("hello")
362 );
363
364 assert_eq!(
365 value_from_str("<value>world</value>").unwrap().as_str(),
366 Some("world")
367 );
368
369 assert_eq!(value_from_str("<value />").unwrap().as_str(), Some(""));
370 }
371
372 #[test]
374 fn parse_double_values() {
375 assert_eq!(
376 value_from_str("<value><double>1</double></value>")
377 .unwrap()
378 .as_f64(),
379 Some(1.0)
380 );
381 assert_eq!(
382 value_from_str("<value><double>0</double></value>")
383 .unwrap()
384 .as_f64(),
385 Some(0.0)
386 );
387 assert_eq!(
388 value_from_str("<value><double>42</double></value>")
389 .unwrap()
390 .as_f64(),
391 Some(42.0)
392 );
393 assert_eq!(
394 value_from_str("<value><double>3.14</double></value>")
395 .unwrap()
396 .as_f64(),
397 Some(3.14)
398 );
399 assert_eq!(
400 value_from_str("<value><double>-3.14</double></value>")
401 .unwrap()
402 .as_f64(),
403 Some(-3.14)
404 );
405 }
406
407 #[test]
411 fn parse_base64_values() {
412 assert_eq!(
413 value_from_str("<value><base64>aGVsbG8gd29ybGQ=</base64></value>")
414 .unwrap()
415 .as_bytes(),
416 Some(&b"hello world"[..])
417 );
418 }
419
420 #[test]
424 fn parse_array_values() {
425 assert_eq!(
426 value_from_str(
427 "<value><array><data><value></value><value><nil /></value></data></array></value>"
428 )
429 .unwrap()
430 .as_array(),
431 Some(&[Value::String("".to_owned()), Value::Nil][..])
432 );
433 }
434
435 #[test]
437 fn parse_nil_values() {
438 assert_eq!(
439 value_from_str("<value><nil /></value>").unwrap(),
440 Value::Nil
441 );
442 }
443
444 #[test]
445 fn parse_fault() {
446 let err = response_from_str::<String>(
447 r#"<?xml version="1.0" encoding="utf-8"?>
448 <methodResponse>
449 <fault>
450 <value>
451 <struct>
452 <member>
453 <name>faultCode</name>
454 <value><int>4</int></value>
455 </member>
456 <member>
457 <name>faultString</name>
458 <value><string>Too many parameters.</string></value>
459 </member>
460 </struct>
461 </value>
462 </fault>
463 </methodResponse>"#,
464 )
465 .unwrap_err();
466
467 match err {
468 error::Error::Fault(f) => assert_eq!(
469 f,
470 error::Fault {
471 fault_code: 4,
472 fault_string: "Too many parameters.".into(),
473 }
474 ),
475 _ => {
476 println!("{:?}", err);
477 assert!(false);
478 }
479 }
480 }
481
482 #[test]
483 fn parse_value() {
484 let val: String = response_from_str(
485 r#"<?xml version="1.0" encoding="utf-8"?>
486 <methodResponse>
487 <params>
488 <param><value><string>hello world</string></value></param>
489 </params>
490 </methodResponse>"#,
491 )
492 .unwrap();
493
494 assert_eq!(val, "hello world".to_string());
495 }
496
497 #[test]
498 fn test_parse_request_multiple_params() {
499 let val = r#"<?xml version=\"1.0\"?>
500 <methodCall>
501 <methodName>requestTopic</methodName>
502 <params>
503 <param><value>/rosout</value></param>
504 <param><value><int>42</int></value></param>
505 <param><value><array><data><value><array><data><value>TCPROS</value></data></array></value></data></array></value></param>
506 </params>
507 </methodCall>"#;
508
509 let (method, vals) = request_from_str(val).unwrap();
510 assert_eq!(&method, "requestTopic");
511
512 let (a, b, c): (String, i32, Vec<Vec<String>>) = from_values(vals).unwrap();
515
516 assert_eq!(a, "/rosout");
517 assert_eq!(b, 42);
518 assert_eq!(c, vec![vec!["TCPROS".to_string()]]);
519 }
520
521 #[test]
522 fn test_response_to_value() {
523 let val: Value = response_from_str(
526 r#"<?xml version="1.0" encoding="utf-8"?>
527 <methodResponse>
528 <params>
529 <param><value><string>hello world</string></value></param>
530 </params>
531 </methodResponse>"#,
532 )
533 .unwrap();
534
535 assert_eq!(val, Value::String("hello world".to_string()));
536 }
537
538 #[test]
539 fn test_from_values() {
540 let vals = vec![
541 Value::Int(32),
542 Value::Double(1.0),
543 Value::String("hello".to_string()),
544 ];
545
546 let (a, b, c): (i32, f64, String) = from_values(vals).unwrap();
547 assert_eq!(a, 32);
548 assert_eq!(b, 1.0);
549 assert_eq!(c, "hello");
550 }
551}