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