Skip to content

Commit 3848ff9

Browse files
authored
Merge pull request #31 from farodin91/restructure
Restructure and add rust like conversion to and from
2 parents d5a1284 + a151a89 commit 3848ff9

File tree

11 files changed

+575
-450
lines changed

11 files changed

+575
-450
lines changed
File renamed without changes.

src/de/mod.rs

Lines changed: 374 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,374 @@
1+
use std::str::FromStr;
2+
use std::convert::From;
3+
use std::io::Read;
4+
5+
use serde::de::{self, Deserialize, Visitor};
6+
use xml::reader::{EventReader, ParserConfig, XmlEvent};
7+
use xml::name::OwnedName;
8+
9+
use error::{Error, ErrorKind, Result};
10+
use self::map::MapAccess;
11+
use self::seq::SeqAccess;
12+
use self::var::EnumAccess;
13+
14+
mod map;
15+
mod seq;
16+
mod var;
17+
18+
/// A convenience method for deserialize some object from a string.
19+
///
20+
/// ```rust
21+
/// # #[macro_use]
22+
/// # extern crate serde_derive;
23+
/// # extern crate serde;
24+
/// # extern crate serde_xml_rs;
25+
/// # use serde_xml_rs::from_str;
26+
/// #[derive(Debug, Deserialize, PartialEq)]
27+
/// struct Item {
28+
/// name: String,
29+
/// source: String,
30+
/// }
31+
/// # fn main() {
32+
/// let s = r##"<item name="hello" source="world.rs" />"##;
33+
/// let item: Item = from_str(s).unwrap();
34+
/// assert_eq!(item, Item { name: "hello".to_string(),source: "world.rs".to_string()});
35+
/// # }
36+
/// ```
37+
pub fn from_str<'de, T: de::Deserialize<'de>>(s: &str) -> Result<T> {
38+
from_reader(s.as_bytes())
39+
}
40+
41+
42+
/// A convenience method for deserialize some object from a reader.
43+
///
44+
/// ```rust
45+
/// # #[macro_use]
46+
/// # extern crate serde_derive;
47+
/// # extern crate serde;
48+
/// # extern crate serde_xml_rs;
49+
/// # use serde_xml_rs::from_reader;
50+
/// #[derive(Debug, Deserialize, PartialEq)]
51+
/// struct Item {
52+
/// name: String,
53+
/// source: String,
54+
/// }
55+
/// # fn main() {
56+
/// let s = r##"<item name="hello" source="world.rs" />"##;
57+
/// let item: Item = from_reader(s.as_bytes()).unwrap();
58+
/// assert_eq!(item, Item { name: "hello".to_string(),source: "world.rs".to_string()});
59+
/// # }
60+
/// ```
61+
pub fn from_reader<'de, R: Read, T: Deserialize<'de>>(reader: R) -> Result<T> {
62+
T::deserialize(&mut Deserializer::new_from_reader(reader))
63+
}
64+
65+
pub struct Deserializer<R: Read> {
66+
depth: usize,
67+
reader: EventReader<R>,
68+
peeked: Option<XmlEvent>,
69+
is_map_value: bool,
70+
}
71+
72+
impl<'de, R: Read> Deserializer<R> {
73+
pub fn new(reader: EventReader<R>) -> Self {
74+
Deserializer {
75+
depth: 0,
76+
reader: reader,
77+
peeked: None,
78+
is_map_value: false,
79+
}
80+
}
81+
82+
pub fn new_from_reader(reader: R) -> Self {
83+
let config = ParserConfig::new()
84+
.trim_whitespace(true)
85+
.whitespace_to_characters(true)
86+
.cdata_to_characters(true)
87+
.ignore_comments(true)
88+
.coalesce_characters(true);
89+
90+
Self::new(EventReader::new_with_config(reader, config))
91+
}
92+
93+
fn peek(&mut self) -> Result<&XmlEvent> {
94+
if self.peeked.is_none() {
95+
self.peeked = Some(self.inner_next()?);
96+
}
97+
debug_expect!(self.peeked.as_ref(), Some(peeked) => {
98+
debug!("Peeked {:?}", peeked);
99+
Ok(peeked)
100+
})
101+
}
102+
103+
fn inner_next(&mut self) -> Result<XmlEvent> {
104+
loop {
105+
match self.reader.next().map_err(ErrorKind::Syntax)? {
106+
XmlEvent::StartDocument { .. } |
107+
XmlEvent::EndDocument { .. } |
108+
XmlEvent::ProcessingInstruction { .. } |
109+
XmlEvent::Comment(_) => { /* skip */ },
110+
111+
other => return Ok(other),
112+
}
113+
}
114+
}
115+
116+
fn next(&mut self) -> Result<XmlEvent> {
117+
let next = if let Some(peeked) = self.peeked.take() {
118+
peeked
119+
} else {
120+
self.inner_next()?
121+
};
122+
match next {
123+
XmlEvent::StartElement { .. } => {
124+
self.depth += 1;
125+
},
126+
XmlEvent::EndElement { .. } => {
127+
self.depth -= 1;
128+
},
129+
_ => {},
130+
}
131+
debug!("Fetched {:?}", next);
132+
Ok(next)
133+
}
134+
135+
fn set_map_value(&mut self) {
136+
self.is_map_value = true;
137+
}
138+
139+
pub fn unset_map_value(&mut self) -> bool {
140+
::std::mem::replace(&mut self.is_map_value, false)
141+
}
142+
143+
fn read_inner_value<V: Visitor<'de>, F: FnOnce(&mut Self) -> Result<V::Value>>(
144+
&mut self,
145+
f: F,
146+
) -> Result<V::Value> {
147+
if self.unset_map_value() {
148+
debug_expect!(self.next(), Ok(XmlEvent::StartElement { name, .. }) => {
149+
let result = f(self)?;
150+
self.expect_end_element(name)?;
151+
Ok(result)
152+
})
153+
} else {
154+
f(self)
155+
}
156+
}
157+
158+
fn expect_end_element(&mut self, start_name: OwnedName) -> Result<()> {
159+
expect!(self.next()?, XmlEvent::EndElement { name, .. } => {
160+
if name == start_name {
161+
Ok(())
162+
} else {
163+
Err(ErrorKind::Custom(format!(
164+
"End tag </{}> didn't match the start tag <{}>",
165+
name.local_name,
166+
start_name.local_name
167+
)).into())
168+
}
169+
})
170+
}
171+
172+
fn parse_type<N, C, V, F>(&mut self, visit: F) -> Result<V::Value>
173+
where
174+
N: FromStr<Err = C>,
175+
Error: From<C>,
176+
V: Visitor<'de>,
177+
F: FnOnce(N) -> Result<V::Value>,
178+
{
179+
if let XmlEvent::StartElement { .. } = *self.peek()? {
180+
self.set_map_value()
181+
}
182+
self.read_inner_value::<V, _>(|this| {
183+
if let XmlEvent::EndElement { .. } = *this.peek()? {
184+
return Err(
185+
ErrorKind::UnexpectedToken("EndElement".into(), "Characters".into()).into(),
186+
);
187+
}
188+
189+
expect!(this.next()?, XmlEvent::Characters(s) => {
190+
let value = s.parse::<N>()?;
191+
visit(value)
192+
})
193+
})
194+
}
195+
}
196+
197+
impl<'de, 'a, R: Read> de::Deserializer<'de> for &'a mut Deserializer<R> {
198+
type Error = Error;
199+
200+
forward_to_deserialize_any! {
201+
newtype_struct identifier
202+
}
203+
204+
fn deserialize_struct<V: Visitor<'de>>(
205+
self,
206+
_name: &'static str,
207+
fields: &'static [&'static str],
208+
visitor: V,
209+
) -> Result<V::Value> {
210+
self.unset_map_value();
211+
expect!(self.next()?, XmlEvent::StartElement { name, attributes, .. } => {
212+
let map_value = visitor.visit_map(MapAccess::new(
213+
self,
214+
attributes,
215+
fields.contains(&"$value")
216+
))?;
217+
self.expect_end_element(name)?;
218+
Ok(map_value)
219+
})
220+
}
221+
222+
fn deserialize_u64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
223+
self.parse_type::<u64, ::std::num::ParseIntError, V, _>(|value| visitor.visit_u64(value))
224+
}
225+
226+
fn deserialize_u32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
227+
self.parse_type::<u32, ::std::num::ParseIntError, V, _>(|value| visitor.visit_u32(value))
228+
}
229+
230+
fn deserialize_u16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
231+
self.parse_type::<u16, ::std::num::ParseIntError, V, _>(|value| visitor.visit_u16(value))
232+
}
233+
234+
fn deserialize_u8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
235+
self.parse_type::<u8, ::std::num::ParseIntError, V, _>(|value| visitor.visit_u8(value))
236+
}
237+
238+
fn deserialize_i64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
239+
self.parse_type::<i64, ::std::num::ParseIntError, V, _>(|value| visitor.visit_i64(value))
240+
}
241+
242+
fn deserialize_i32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
243+
self.parse_type::<i32, ::std::num::ParseIntError, V, _>(|value| visitor.visit_i32(value))
244+
}
245+
246+
fn deserialize_i16<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
247+
self.parse_type::<i16, ::std::num::ParseIntError, V, _>(|value| visitor.visit_i16(value))
248+
}
249+
250+
fn deserialize_i8<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
251+
self.parse_type::<i8, ::std::num::ParseIntError, V, _>(|value| visitor.visit_i8(value))
252+
}
253+
254+
fn deserialize_f32<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
255+
self.parse_type::<f32, ::std::num::ParseFloatError, V, _>(|value| visitor.visit_f32(value))
256+
}
257+
258+
fn deserialize_f64<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
259+
self.parse_type::<f64, ::std::num::ParseFloatError, V, _>(|value| visitor.visit_f64(value))
260+
}
261+
262+
fn deserialize_bool<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
263+
self.parse_type::<bool, ::std::str::ParseBoolError, V, _>(|value| visitor.visit_bool(value))
264+
}
265+
266+
fn deserialize_char<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
267+
self.deserialize_string(visitor)
268+
}
269+
270+
fn deserialize_str<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
271+
self.deserialize_string(visitor)
272+
}
273+
274+
fn deserialize_bytes<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
275+
self.deserialize_string(visitor)
276+
}
277+
278+
fn deserialize_byte_buf<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
279+
self.deserialize_string(visitor)
280+
}
281+
282+
fn deserialize_unit<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
283+
if let XmlEvent::StartElement { .. } = *self.peek()? {
284+
self.set_map_value()
285+
}
286+
self.read_inner_value::<V, _>(
287+
|this| expect!(this.peek()?, &XmlEvent::EndElement { .. } => visitor.visit_unit()),
288+
)
289+
}
290+
291+
fn deserialize_unit_struct<V: Visitor<'de>>(
292+
self,
293+
_name: &'static str,
294+
visitor: V,
295+
) -> Result<V::Value> {
296+
self.deserialize_unit(visitor)
297+
}
298+
299+
fn deserialize_tuple_struct<V: Visitor<'de>>(
300+
self,
301+
_name: &'static str,
302+
len: usize,
303+
visitor: V,
304+
) -> Result<V::Value> {
305+
self.deserialize_tuple(len, visitor)
306+
}
307+
308+
fn deserialize_tuple<V: Visitor<'de>>(self, len: usize, visitor: V) -> Result<V::Value> {
309+
visitor.visit_seq(SeqAccess::new(self, Some(len)))
310+
}
311+
312+
fn deserialize_enum<V: Visitor<'de>>(
313+
self,
314+
_name: &'static str,
315+
_variants: &'static [&'static str],
316+
visitor: V,
317+
) -> Result<V::Value> {
318+
self.read_inner_value::<V, _>(|this| visitor.visit_enum(EnumAccess::new(this)))
319+
}
320+
321+
fn deserialize_string<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
322+
if let XmlEvent::StartElement { .. } = *self.peek()? {
323+
self.set_map_value()
324+
}
325+
self.read_inner_value::<V, _>(|this| {
326+
if let XmlEvent::EndElement { .. } = *this.peek()? {
327+
return visitor.visit_str("");
328+
}
329+
expect!(this.next()?, XmlEvent::Characters(s) => {
330+
visitor.visit_string(s)
331+
})
332+
})
333+
}
334+
335+
fn deserialize_seq<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
336+
visitor.visit_seq(SeqAccess::new(self, None))
337+
}
338+
339+
fn deserialize_map<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
340+
self.unset_map_value();
341+
expect!(self.next()?, XmlEvent::StartElement { name, attributes, .. } => {
342+
let map_value = visitor.visit_map(MapAccess::new(self, attributes, false))?;
343+
self.expect_end_element(name)?;
344+
Ok(map_value)
345+
})
346+
}
347+
348+
fn deserialize_option<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
349+
match *self.peek()? {
350+
XmlEvent::EndElement { .. } => visitor.visit_none(),
351+
_ => visitor.visit_some(self),
352+
}
353+
}
354+
355+
fn deserialize_ignored_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
356+
self.unset_map_value();
357+
let depth = self.depth;
358+
loop {
359+
self.next()?;
360+
if self.depth == depth {
361+
break;
362+
}
363+
}
364+
visitor.visit_unit()
365+
}
366+
367+
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
368+
match *self.peek()? {
369+
XmlEvent::StartElement { .. } => self.deserialize_map(visitor),
370+
XmlEvent::EndElement { .. } => self.deserialize_unit(visitor),
371+
_ => self.deserialize_string(visitor),
372+
}
373+
}
374+
}
File renamed without changes.
File renamed without changes.

src/error.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ error_chain! {
1212

1313
foreign_links {
1414
Io(::std::io::Error);
15+
FromUtf8Error(::std::string::FromUtf8Error);
1516
ParseIntError(::std::num::ParseIntError);
1617
ParseFloatError(::std::num::ParseFloatError);
1718
ParseBoolError(::std::str::ParseBoolError);

0 commit comments

Comments
 (0)