1use quick_xml::{XmlReader, Event, Element};
2
3use fromxml::{self, FromXml};
4use error::Error;
5use category::Category;
6use guid::Guid;
7use enclosure::Enclosure;
8use source::Source;
9use extension::ExtensionMap;
10use extension::itunes::ITunesItemExtension;
11use extension::dublincore::DublinCoreExtension;
12
13#[derive(Debug, Default, Clone, PartialEq)]
15pub struct Item {
16 pub title: Option<String>,
18 pub link: Option<String>,
20 pub description: Option<String>,
22 pub author: Option<String>,
24 pub categories: Vec<Category>,
26 pub comments: Option<String>,
28 pub enclosure: Option<Enclosure>,
30 pub guid: Option<Guid>,
32 pub pub_date: Option<String>,
34 pub source: Option<Source>,
36 pub content: Option<String>,
38 pub extensions: ExtensionMap,
40 pub itunes_ext: Option<ITunesItemExtension>,
42 pub dublin_core_ext: Option<DublinCoreExtension>,
44}
45
46impl FromXml for Item {
47 fn from_xml<R: ::std::io::BufRead>(mut reader: XmlReader<R>,
48 _: Element)
49 -> Result<(Self, XmlReader<R>), Error> {
50 let mut item = Item::default();
51
52 while let Some(e) = reader.next() {
53 match e {
54 Ok(Event::Start(element)) => {
55 match element.name() {
56 b"category" => {
57 let (category, reader_) = try!(Category::from_xml(reader, element));
58 reader = reader_;
59 item.categories.push(category);
60 }
61 b"guid" => {
62 let (guid, reader_) = try!(Guid::from_xml(reader, element));
63 reader = reader_;
64 item.guid = Some(guid);
65 }
66 b"enclosure" => {
67 let (enclosure, reader_) = try!(Enclosure::from_xml(reader, element));
68 reader = reader_;
69 item.enclosure = Some(enclosure);
70 }
71 b"source" => {
72 let (source, reader_) = try!(Source::from_xml(reader, element));
73 reader = reader_;
74 item.source = Some(source);
75 }
76 b"title" => item.title = element_text!(reader),
77 b"link" => item.link = element_text!(reader),
78 b"description" => item.description = element_text!(reader),
79 b"author" => item.author = element_text!(reader),
80 b"comments" => item.comments = element_text!(reader),
81 b"pubDate" => item.pub_date = element_text!(reader),
82 b"content:encoded" => item.content = element_text!(reader),
83 _ => {
84 if let Some((ns, name)) = fromxml::extension_name(&element) {
85 parse_extension!(reader, element, ns, name, item.extensions);
86 } else {
87 skip_element!(reader);
88 }
89 }
90 }
91 }
92 Ok(Event::End(_)) => {
93 if !item.extensions.is_empty() {
94 if let Some(map) = item.extensions.remove("itunes") {
95 item.itunes_ext = Some(ITunesItemExtension::from_map(map));
96 }
97
98 if let Some(map) = item.extensions.remove("dc") {
99 item.dublin_core_ext = Some(DublinCoreExtension::from_map(map));
100 }
101 }
102
103 return Ok((item, reader));
104 }
105 Err(err) => return Err(err.into()),
106 _ => {}
107 }
108 }
109
110 Err(Error::EOF)
111 }
112}