1use std::any::TypeId;
2
3use serde::de::DeserializeOwned;
4use serde_json::Value;
5
6use crate::{ApiError, ApiResult, MimeType, ResponseBody};
7
8#[derive(Debug)]
10pub struct Xml;
11
12impl Xml {
13 fn do_try_parse<T>(text: String) -> ApiResult<T>
14 where
15 T: 'static + DeserializeOwned,
16 {
17 let type_id = TypeId::of::<T>();
18 if type_id == TypeId::of::<()>() {
19 serde_json::from_value(Value::Null).map_err(|_| ApiError::Impossible)
20 } else if type_id == TypeId::of::<String>() {
21 let value = serde_json::Value::String(text);
22 serde_json::from_value(value).map_err(|_| ApiError::Impossible)
23 } else {
24 quick_xml::de::from_str(&text).map_err(ApiError::DecodeXml)
25 }
26 }
27
28 pub fn try_parse<T>(body: ResponseBody) -> ApiResult<T>
30 where
31 T: 'static + DeserializeOwned,
32 {
33 let type_id = TypeId::of::<T>();
34 if type_id == TypeId::of::<()>() {
35 return serde_json::from_value(Value::Null).map_err(|_| ApiError::Impossible);
36 }
37
38 match body {
39 ResponseBody::Xml(xml) => Self::do_try_parse(xml),
40 ResponseBody::Text(text) => {
41 log::debug!("Treat text as xml for decoding");
42 Self::do_try_parse(text)
43 }
44 _ => Err(ApiError::IncompatibleContentType(
45 MimeType::Xml,
46 body.mime_type(),
47 )),
48 }
49 }
50}