xml_rpc/xmlfmt/
parse.rs

1use super::error::{Result, ResultExt};
2use super::{Call, Fault, Response, Value};
3use base64::{engine::general_purpose::STANDARD, Engine as _};
4use regex::Regex;
5use std;
6use std::collections::HashMap;
7
8fn wrap_in_string(content: String) -> String {
9    lazy_static! {
10        static ref RE1: Regex = Regex::new(r"<value\s*/>").unwrap();
11        static ref RE2: Regex = Regex::new(r"<value\s*>\s*<string\s*/>\s*</value\s*>").unwrap();
12        static ref RE3: Regex = Regex::new(r"<value\s*>(?P<rest>[^<>]*)</value\s*>").unwrap();
13    }
14    RE3.replace_all(
15        &RE2.replace_all(
16            &RE1.replace_all(&content, "<value><string></string></value>"),
17            "<value><string></string></value>",
18        ),
19        "<value><string>$rest</string></value>",
20    )
21    .into()
22}
23
24#[allow(dead_code)]
25pub fn xml<T: std::io::Read>(mut r: T) -> Result<Value> {
26    let mut content = String::new();
27    r.read_to_string(&mut content)
28        .chain_err(|| "Failed to read data source.")?;
29    let data: XmlValue = serde_xml_rs::from_str(&wrap_in_string(content))
30        .chain_err(|| "Failed to parse XML-RPC data.")?;
31    data.into()
32}
33
34pub fn call<T: std::io::Read>(mut r: T) -> Result<Call> {
35    let mut content = String::new();
36    r.read_to_string(&mut content)
37        .chain_err(|| "Failed to read data source.")?;
38    let data: XmlCall = serde_xml_rs::from_str(&wrap_in_string(content))
39        .chain_err(|| "Failed to parse XML-RPC call.")?;
40    data.into()
41}
42
43pub fn response<T: std::io::Read>(mut r: T) -> Result<Response> {
44    let mut content = String::new();
45    r.read_to_string(&mut content)
46        .chain_err(|| "Failed to read data source.")?;
47    let data: XmlResponse = serde_xml_rs::from_str(&wrap_in_string(content))
48        .chain_err(|| "Failed to parse XML-RPC response.")?;
49    data.into()
50}
51
52#[derive(Debug, PartialEq, Deserialize)]
53enum XmlValue {
54    #[serde(rename = "i4")]
55    I4(i32),
56    #[serde(rename = "int")]
57    Int(i32),
58    #[serde(rename = "boolean")]
59    Bool(i32),
60    #[serde(rename = "string")]
61    Str(String),
62    #[serde(rename = "double")]
63    Double(String),
64    #[serde(rename = "dateTime.iso8601")]
65    DateTime(String),
66    #[serde(rename = "base64")]
67    Base64(String),
68    #[serde(rename = "array")]
69    Array(XmlArray),
70    #[serde(rename = "struct")]
71    Struct(XmlStruct),
72}
73
74impl From<XmlValue> for Result<Value> {
75    fn from(val: XmlValue) -> Self {
76        Ok(match val {
77            XmlValue::I4(v) | XmlValue::Int(v) => Value::Int(v),
78            XmlValue::Bool(v) => Value::Bool(v != 0),
79            XmlValue::Str(v) => Value::String(v),
80            XmlValue::Double(v) => Value::Double(v.parse().chain_err(|| "Failed to parse double")?),
81            XmlValue::DateTime(v) => Value::DateTime(v),
82            XmlValue::Base64(v) => Value::Base64(
83                STANDARD
84                    .decode(v.as_bytes())
85                    .chain_err(|| "Failed to parse base64")?,
86            ),
87            XmlValue::Array(v) => {
88                let items: Result<Vec<Value>> = v.into();
89                Value::Array(items?)
90            }
91            XmlValue::Struct(v) => {
92                let items: Result<HashMap<String, Value>> = v.into();
93                Value::Struct(items?)
94            }
95        })
96    }
97}
98
99#[derive(Debug, PartialEq, Deserialize)]
100#[serde(rename = "methodCall")]
101struct XmlCall {
102    #[serde(rename = "methodName")]
103    pub name: String,
104    pub params: XmlParams,
105}
106
107impl From<XmlCall> for Result<Call> {
108    fn from(val: XmlCall) -> Self {
109        let params: Result<Vec<Value>> = val.params.into();
110        Ok(Call {
111            name: val.name,
112            params: params?,
113        })
114    }
115}
116
117#[derive(Debug, PartialEq, Deserialize)]
118enum XmlResponseResult {
119    #[serde(rename = "params")]
120    Success(XmlParams),
121    #[serde(rename = "fault")]
122    Failure { value: XmlValue },
123}
124
125impl From<XmlResponseResult> for Result<Response> {
126    fn from(val: XmlResponseResult) -> Self {
127        match val {
128            XmlResponseResult::Success(params) => {
129                let params: Result<Vec<Value>> = params.into();
130                Ok(Ok(params?))
131            }
132            XmlResponseResult::Failure { value: v } => {
133                use serde::Deserialize;
134
135                let val: Result<Value> = v.into();
136
137                Ok(Err(
138                    Fault::deserialize(val?).chain_err(|| "Failed to decode fault structure")?
139                ))
140            }
141        }
142    }
143}
144
145#[derive(Debug, PartialEq, Deserialize)]
146enum XmlResponse {
147    #[serde(rename = "methodResponse")]
148    Response(XmlResponseResult),
149}
150
151impl From<XmlResponse> for Result<Response> {
152    fn from(val: XmlResponse) -> Self {
153        match val {
154            XmlResponse::Response(v) => v.into(),
155        }
156    }
157}
158
159#[derive(Debug, PartialEq, Deserialize)]
160struct XmlParams {
161    #[serde(rename = "param", default)]
162    pub params: Vec<XmlParamData>,
163}
164
165impl From<XmlParams> for Result<Vec<Value>> {
166    fn from(val: XmlParams) -> Self {
167        val.params
168            .into_iter()
169            .map(Into::<Result<Value>>::into)
170            .collect()
171    }
172}
173
174#[derive(Debug, PartialEq, Deserialize)]
175struct XmlParamData {
176    pub value: XmlValue,
177}
178
179impl From<XmlParamData> for Result<Value> {
180    fn from(val: XmlParamData) -> Self {
181        val.value.into()
182    }
183}
184
185#[derive(Debug, PartialEq, Deserialize)]
186struct XmlArray {
187    #[serde(rename = "data")]
188    pub data: XmlArrayData,
189}
190
191impl From<XmlArray> for Result<Vec<Value>> {
192    fn from(val: XmlArray) -> Self {
193        val.data.into()
194    }
195}
196
197#[derive(Debug, PartialEq, Deserialize)]
198struct XmlArrayData {
199    #[serde(default)]
200    pub value: Vec<XmlValue>,
201}
202
203impl From<XmlArrayData> for Result<Vec<Value>> {
204    fn from(val: XmlArrayData) -> Self {
205        val.value
206            .into_iter()
207            .map(Into::<Result<Value>>::into)
208            .collect()
209    }
210}
211
212#[derive(Debug, PartialEq, Deserialize)]
213struct XmlStruct {
214    #[serde(rename = "member", default)]
215    pub members: Vec<XmlStructItem>,
216}
217
218impl From<XmlStruct> for Result<HashMap<String, Value>> {
219    fn from(val: XmlStruct) -> Self {
220        val.members
221            .into_iter()
222            .map(Into::<Result<(String, Value)>>::into)
223            .collect()
224    }
225}
226
227#[derive(Debug, PartialEq, Deserialize)]
228struct XmlStructItem {
229    pub name: String,
230    pub value: XmlValue,
231}
232
233impl From<XmlStructItem> for Result<(String, Value)> {
234    fn from(val: XmlStructItem) -> Self {
235        let value: Result<Value> = val.value.into();
236        Ok((val.name, value?))
237    }
238}