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.and_then(|ns| namespaces.get(&ns)).map(|prefix| {
118 if prefix.is_empty() {
119 String::new()
120 } else {
121 [*prefix, ":"].concat()
122 }
123 });
124 let has_prefix = prefix.is_some();
125 let tagname = tag.map(|tag| [&prefix.unwrap_or_default(), tag].concat());
126 if let Some(tagname) = tagname.as_ref() {
127 let mut bytes_start = BytesStart::new(tagname);
128 if !has_prefix && let Some(ns) = &ns {
129 bytes_start.push_attribute((b"xmlns".as_ref(), ns.as_ref()));
130 }
131 writer.write_event(Event::Start(bytes_start))?;
132 }
133 writer.write_event(Event::Text(BytesText::new(&self.serialize())))?;
134 if let Some(tagname) = tagname {
135 writer.write_event(Event::End(BytesEnd::new(tagname)))?;
136 }
137 Ok(())
138 }
139
140 fn attributes<'a>(&self) -> Option<Vec<quick_xml::events::attributes::Attribute<'a>>> {
141 None
142 }
143}