rosrust/rosxmlrpc/
client.rs

1use super::error::{ErrorKind, Result, ResultExt};
2use super::{Response, ResponseError, ResponseInfo};
3use serde::{Deserialize, Serialize};
4use xml_rpc::{self, Params, Url, Value};
5
6pub struct Client {
7    master_uri: Url,
8}
9
10impl Client {
11    pub fn new(master_uri: &str) -> Result<Client> {
12        let master_uri = master_uri
13            .parse()
14            .chain_err(|| ErrorKind::BadUri(master_uri.into()))?;
15        Ok(Client { master_uri })
16    }
17
18    pub fn request_tree_with_tree(&self, name: &str, params: Params) -> Response<Value> {
19        let call_result = xml_rpc::call_value(&self.master_uri, name, params);
20
21        let server_response = call_result.map_err(|err| {
22            ResponseError::Client(format!("Failed to perform call to server: {}", err))
23        })?;
24
25        let response_parameters = server_response.map_err(|fault| {
26            ResponseError::Client(format!(
27                "Unexpected fault #{} received from server: {}",
28                fault.code, fault.message
29            ))
30        })?;
31
32        let response_parameters = remove_array_wrappers(&response_parameters[..]);
33
34        ResponseInfo::from_array(response_parameters)?.into()
35    }
36
37    pub fn request_tree<S>(&self, name: &str, params: &S) -> Response<Value>
38    where
39        S: Serialize,
40    {
41        let params = xml_rpc::into_params(params).map_err(bad_request_structure)?;
42        self.request_tree_with_tree(name, params)
43    }
44
45    pub fn request<'a, S, D>(&self, name: &str, params: &S) -> Response<D>
46    where
47        S: Serialize,
48        D: Deserialize<'a>,
49    {
50        let data = self.request_tree(name, params)?;
51        Deserialize::deserialize(data).map_err(bad_response_structure)
52    }
53}
54
55fn remove_array_wrappers(mut data: &[Value]) -> &[Value] {
56    while let [Value::Array(ref children)] = data[..] {
57        data = children;
58    }
59    data
60}
61
62fn bad_request_structure<T: ::std::fmt::Display>(err: T) -> ResponseError {
63    ResponseError::Client(format!("Failed to serialize parameters: {}", err))
64}
65
66pub(crate) fn bad_response_structure<T: ::std::fmt::Display>(err: T) -> ResponseError {
67    ResponseError::Server(format!("Response data has unexpected structure: {}", err))
68}