1use crate::{XmlDeserialize, XmlError, XmlSerialize};
2use http::uri::InvalidUri;
3use quick_xml::events::{BytesEnd, BytesStart, BytesText, Event};
4use quick_xml::name::Namespace;
5use std::collections::HashMap;
6use std::num::{ParseFloatError, ParseIntError};
7use std::str::FromStr;
8use std::{convert::Infallible, io::BufRead};
9use thiserror::Error;
10
11pub trait ValueSerialize {
12 fn serialize(&self) -> String;
13}
14
15pub trait ValueDeserialize: Sized {
16 fn deserialize(val: &str) -> Result<Self, XmlError>;
17}
18
19#[derive(Debug, Error)]
20pub enum ParseValueError {
21 #[error(transparent)]
22 Infallible(#[from] Infallible),
23 #[error(transparent)]
24 ParseIntError(#[from] ParseIntError),
25 #[error(transparent)]
26 ParseFloatError(#[from] ParseFloatError),
27 #[error(transparent)]
28 InvalidUri(#[from] InvalidUri),
29 #[error("{0}")]
30 Other(String),
31}
32
33macro_rules! impl_value_parse {
34 ($t:ty) => {
35 impl ValueSerialize for $t {
36 fn serialize(&self) -> String {
37 self.to_string()
38 }
39 }
40
41 impl ValueDeserialize for $t {
42 fn deserialize(val: &str) -> Result<Self, XmlError> {
43 val.parse()
44 .map_err(ParseValueError::from)
45 .map_err(XmlError::from)
46 }
47 }
48 };
49}
50
51impl_value_parse!(String);
52impl_value_parse!(i8);
53impl_value_parse!(u8);
54impl_value_parse!(i16);
55impl_value_parse!(u16);
56impl_value_parse!(f32);
57impl_value_parse!(i32);
58impl_value_parse!(u32);
59impl_value_parse!(f64);
60impl_value_parse!(i64);
61impl_value_parse!(u64);
62impl_value_parse!(isize);
63impl_value_parse!(usize);
64
65impl ValueSerialize for &str {
66 fn serialize(&self) -> String {
67 (*self).to_string()
68 }
69}
70
71impl ValueDeserialize for http::Uri {
72 fn deserialize(val: &str) -> Result<Self, XmlError> {
73 Self::from_str(val).map_err(|err| XmlError::InvalidValue(ParseValueError::InvalidUri(err)))
74 }
75}
76
77impl ValueSerialize for http::Uri {
78 fn serialize(&self) -> String {
79 self.to_string()
80 }
81}
82
83impl<T: ValueDeserialize> XmlDeserialize for T {
84 fn deserialize<R: BufRead>(
85 reader: &mut quick_xml::NsReader<R>,
86 _start: &BytesStart,
87 empty: bool,
88 ) -> Result<Self, XmlError> {
89 let mut string = String::new();
90
91 if !empty {
92 let mut buf = Vec::new();
93 loop {
94 match reader.read_event_into(&mut buf)? {
95 Event::Text(text) => {
96 string.push_str(&text);
97 }
98 Event::CData(cdata) => {
99 string.push_str(&cdata);
100 }
101 Event::GeneralRef(gref) => {
102 if let Some(char) = gref.resolve_char_ref()? {
103 string.push(char);
104 } else if let Some(text) =
105 quick_xml::escape::resolve_xml_entity(&gref.xml11_content())
106 {
107 string.push_str(text);
108 } else {
109 return Err(XmlError::UnsupportedEvent("invalid XML ref"));
110 }
111 }
112 Event::End(_) => break,
113 Event::Eof => return Err(XmlError::Eof),
114 _ => return Err(XmlError::UnsupportedEvent("todo")),
115 }
116 }
117 }
118
119 ValueDeserialize::deserialize(&string)
120 }
121}
122
123impl<T: ValueSerialize> XmlSerialize for T {
124 fn serialize(
125 &self,
126 ns: Option<Namespace>,
127 tag: Option<&str>,
128 namespaces: &HashMap<Namespace, &str>,
129 writer: &mut quick_xml::Writer<&mut Vec<u8>>,
130 ) -> std::io::Result<()> {
131 let prefix = ns.and_then(|ns| namespaces.get(&ns)).map(|prefix| {
132 if prefix.is_empty() {
133 String::new()
134 } else {
135 [*prefix, ":"].concat()
136 }
137 });
138 let has_prefix = prefix.is_some();
139 let tagname = tag.map(|tag| [&prefix.unwrap_or_default(), tag].concat());
140 if let Some(tagname) = tagname.as_ref() {
141 let mut bytes_start = BytesStart::new(tagname);
142 if !has_prefix && let Some(ns) = &ns {
143 bytes_start.push_attribute(("xmlns", ns.as_ref()));
144 }
145 writer.write_event(Event::Start(bytes_start))?;
146 }
147 writer.write_event(Event::Text(BytesText::new(&self.serialize())))?;
148 if let Some(tagname) = tagname {
149 writer.write_event(Event::End(BytesEnd::new(tagname)))?;
150 }
151 Ok(())
152 }
153
154 fn attributes<'a>(&self) -> Option<Vec<quick_xml::events::attributes::Attribute<'a>>> {
155 None
156 }
157}