diff --git a/src/category.rs b/src/category.rs index 71659fa..5f8f71f 100644 --- a/src/category.rs +++ b/src/category.rs @@ -1,10 +1,14 @@ -use std::io::BufRead; +use std::io::{BufRead, Write}; +use quick_xml::errors::Error as XmlError; +use quick_xml::events::{Event, BytesStart}; use quick_xml::events::attributes::Attributes; use quick_xml::reader::Reader; +use quick_xml::writer::Writer; use error::Error; use fromxml::FromXml; +use toxml::ToXml; /// Represents a category in an Atom feed #[derive(Debug, Default, Clone, PartialEq)] @@ -133,3 +137,23 @@ impl FromXml for Category { Ok(category) } } + +impl ToXml for Category { + fn to_xml(&self, writer: &mut Writer) -> Result<(), XmlError> { + let name = b"category"; + let mut element = BytesStart::borrowed(name, name.len()); + element.push_attribute(("term", &*self.term)); + + if let Some(ref scheme) = self.scheme { + element.push_attribute(("scheme", &**scheme)); + } + + if let Some(ref label) = self.label { + element.push_attribute(("label", &**label)); + } + + writer.write_event(Event::Empty(element))?; + + Ok(()) + } +} diff --git a/src/content.rs b/src/content.rs index 72059f5..84b6e79 100644 --- a/src/content.rs +++ b/src/content.rs @@ -1,10 +1,14 @@ -use std::io::BufRead; +use std::io::{BufRead, Write}; +use quick_xml::errors::Error as XmlError; +use quick_xml::events::{Event, BytesStart, BytesEnd, BytesText}; use quick_xml::events::attributes::Attributes; use quick_xml::reader::Reader; +use quick_xml::writer::Writer; use error::Error; use fromxml::FromXml; +use toxml::ToXml; use util::atom_text; /// Represents the content of an Atom entry @@ -138,3 +142,33 @@ impl FromXml for Content { Ok(content) } } + +impl ToXml for Content { + fn to_xml(&self, writer: &mut Writer) -> Result<(), XmlError> { + let name = b"content"; + let mut element = BytesStart::borrowed(name, name.len()); + + if let Some(ref content_type) = self.content_type { + if content_type == "xhtml" { + element.push_attribute(("type", "html")); + } else { + element.push_attribute(("type", &**content_type)); + } + } + + if let Some(ref src) = self.src { + element.push_attribute(("src", &**src)); + } + + writer.write_event(Event::Start(element))?; + + if let Some(ref value) = self.value { + writer + .write_event(Event::Text(BytesText::borrowed(value.as_bytes())))?; + } + + writer.write_event(Event::End(BytesEnd::borrowed(name)))?; + + Ok(()) + } +} diff --git a/src/entry.rs b/src/entry.rs index 9184b3f..922dc75 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -1,8 +1,10 @@ -use std::io::BufRead; +use std::io::{BufRead, Write}; -use quick_xml::events::Event; +use quick_xml::errors::Error as XmlError; +use quick_xml::events::{Event, BytesStart, BytesEnd}; use quick_xml::events::attributes::Attributes; use quick_xml::reader::Reader; +use quick_xml::writer::Writer; use category::Category; use content::Content; @@ -11,6 +13,7 @@ use fromxml::FromXml; use link::Link; use person::Person; use source::Source; +use toxml::{ToXml, WriterExt}; use util::atom_text; /// Represents an entry in an Atom feed @@ -32,12 +35,12 @@ pub struct Entry { links: Vec, /// The time of the initial creation or first availability of the entry. published: Option, + /// Information about rights held in and over the entry. + rights: Option, /// The source information if an entry is copied from one feed into another feed. source: Option, /// A short summary, abstract, or excerpt of the entry. summary: Option, - /// Information about rights held in and over the entry. - rights: Option, /// Contains or links to the complete content of the entry. content: Option, } @@ -291,6 +294,37 @@ impl Entry { self.published = published.into(); } + /// Return the information about the rights held in and over this entry. + /// + /// # Examples + /// + /// ``` + /// use atom_syndication::Entry; + /// + /// let mut entry = Entry::default(); + /// entry.set_rights("© 2017 John Doe".to_string()); + /// assert_eq!(entry.rights(), Some("© 2017 John Doe")); + /// ``` + pub fn rights(&self) -> Option<&str> { + self.rights.as_ref().map(|s| s.as_str()) + } + + /// Set the information about the rights held in and over this entry. + /// + /// # Examples + /// + /// ``` + /// use atom_syndication::Entry; + /// + /// let mut entry = Entry::default(); + /// entry.set_rights("© 2017 John Doe".to_string()); + /// ``` + pub fn set_rights(&mut self, rights: V) + where V: Into> + { + self.rights = rights.into(); + } + /// Return the source of this entry if it was copied from another feed. /// /// # Examples @@ -353,37 +387,6 @@ impl Entry { self.summary = summary.into(); } - /// Return the information about the rights held in and over this entry. - /// - /// # Examples - /// - /// ``` - /// use atom_syndication::Entry; - /// - /// let mut entry = Entry::default(); - /// entry.set_rights("© 2017 John Doe".to_string()); - /// assert_eq!(entry.rights(), Some("© 2017 John Doe")); - /// ``` - pub fn rights(&self) -> Option<&str> { - self.rights.as_ref().map(|s| s.as_str()) - } - - /// Set the information about the rights held in and over this entry. - /// - /// # Examples - /// - /// ``` - /// use atom_syndication::Entry; - /// - /// let mut entry = Entry::default(); - /// entry.set_rights("© 2017 John Doe".to_string()); - /// ``` - pub fn set_rights(&mut self, rights: V) - where V: Into> - { - self.rights = rights.into(); - } - /// Return the content of this entry. /// /// # Examples @@ -450,11 +453,11 @@ impl FromXml for Entry { .push(Link::from_xml(reader, element.attributes())?) } b"published" => entry.published = atom_text(reader)?, + b"rights" => entry.rights = atom_text(reader)?, b"source" => { entry.source = Some(Source::from_xml(reader, element.attributes())?) } b"summary" => entry.summary = atom_text(reader)?, - b"rights" => entry.rights = atom_text(reader)?, b"content" => { entry.content = Some(Content::from_xml(reader, element.attributes())?) } @@ -472,3 +475,43 @@ impl FromXml for Entry { Ok(entry) } } + +impl ToXml for Entry { + fn to_xml(&self, writer: &mut Writer) -> Result<(), XmlError> { + let name = b"entry"; + writer + .write_event(Event::Start(BytesStart::borrowed(name, name.len())))?; + writer.write_text_element(b"title", &*self.title)?; + writer.write_text_element(b"id", &*self.id)?; + writer.write_text_element(b"updated", &*self.updated)?; + writer.write_objects_named(&self.authors, "author")?; + writer.write_objects(&self.categories)?; + writer + .write_objects_named(&self.contributors, "contributor")?; + writer.write_objects(&self.links)?; + + if let Some(ref published) = self.published { + writer.write_text_element(b"published", &**published)?; + } + + if let Some(ref rights) = self.rights { + writer.write_text_element(b"rights", &**rights)?; + } + + if let Some(ref source) = self.source { + writer.write_object(source)?; + } + + if let Some(ref summary) = self.summary { + writer.write_text_element(b"summary", &**summary)?; + } + + if let Some(ref content) = self.content { + writer.write_object(content)?; + } + + writer.write_event(Event::End(BytesEnd::borrowed(name)))?; + + Ok(()) + } +} diff --git a/src/feed.rs b/src/feed.rs index d3717e6..85b5a4d 100644 --- a/src/feed.rs +++ b/src/feed.rs @@ -1,9 +1,11 @@ -use std::io::BufRead; +use std::io::{BufRead, Write}; use std::str::FromStr; -use quick_xml::events::Event; +use quick_xml::errors::Error as XmlError; +use quick_xml::events::{Event, BytesStart, BytesEnd}; use quick_xml::events::attributes::Attributes; use quick_xml::reader::Reader; +use quick_xml::writer::Writer; use category::Category; use error::Error; @@ -12,6 +14,7 @@ use fromxml::FromXml; use generator::Generator; use link::Link; use person::Person; +use toxml::{ToXml, WriterExt}; use util::atom_text; /// Represents an Atom feed @@ -83,6 +86,26 @@ impl Feed { Err(Error::Eof) } + /// Attempt to write this Atom feed to a writer. + /// + /// # Examples + /// + /// ```no_run + /// use std::io::BufReader; + /// use std::fs::File; + /// use atom_syndication::Feed; + /// + /// let file = File::open("example.xml").unwrap(); + /// let feed = Feed::read_from(BufReader::new(file)).unwrap(); + /// let out = File::create("out.xml").unwrap(); + /// feed.write_to(out).unwrap(); + /// ``` + pub fn write_to(&self, writer: W) -> Result { + let mut writer = Writer::new(writer); + self.to_xml(&mut writer)?; + Ok(writer.into_inner()) + } + /// Return the title of this feed. /// /// # Examples @@ -496,8 +519,8 @@ impl FromXml for Feed { match reader.read_event(&mut buf)? { Event::Start(element) => { match element.name() { - b"id" => feed.id = atom_text(reader)?.unwrap_or_default(), b"title" => feed.title = atom_text(reader)?.unwrap_or_default(), + b"id" => feed.id = atom_text(reader)?.unwrap_or_default(), b"updated" => feed.updated = atom_text(reader)?.unwrap_or_default(), b"author" => { feed.authors @@ -542,6 +565,49 @@ impl FromXml for Feed { } } +impl ToXml for Feed { + fn to_xml(&self, writer: &mut Writer) -> Result<(), XmlError> { + let name = b"feed"; + writer + .write_event(Event::Start(BytesStart::borrowed(name, name.len())))?; + writer.write_text_element(b"title", &*self.title)?; + writer.write_text_element(b"id", &*self.id)?; + writer.write_text_element(b"updated", &*self.updated)?; + writer.write_objects_named(&self.authors, "author")?; + writer.write_objects(&self.categories)?; + writer + .write_objects_named(&self.contributors, "contributor")?; + + if let Some(ref generator) = self.generator { + writer.write_object(generator)?; + } + + if let Some(ref icon) = self.icon { + writer.write_text_element(b"icon", &**icon)?; + } + + writer.write_objects(&self.links)?; + + if let Some(ref logo) = self.logo { + writer.write_text_element(b"logo", &**logo)?; + } + + if let Some(ref rights) = self.rights { + writer.write_text_element(b"rights", &**rights)?; + } + + if let Some(ref subtitle) = self.subtitle { + writer.write_text_element(b"subtitle", &**subtitle)?; + } + + writer.write_objects(&self.entries)?; + writer.write_event(Event::End(BytesEnd::borrowed(name)))?; + + Ok(()) + } +} + + impl FromStr for Feed { type Err = Error; @@ -549,3 +615,11 @@ impl FromStr for Feed { Feed::read_from(s.as_bytes()) } } + +impl ToString for Feed { + fn to_string(&self) -> String { + let buf = self.write_to(Vec::new()).unwrap_or_default(); + // this unwrap should be safe since the bytes written from the Feed are all valid utf8 + String::from_utf8(buf).unwrap() + } +} diff --git a/src/generator.rs b/src/generator.rs index c6fc360..db94983 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -1,10 +1,14 @@ -use std::io::BufRead; +use std::io::{BufRead, Write}; +use quick_xml::errors::Error as XmlError; +use quick_xml::events::{Event, BytesStart, BytesEnd, BytesText}; use quick_xml::events::attributes::Attributes; use quick_xml::reader::Reader; +use quick_xml::writer::Writer; use error::Error; use fromxml::FromXml; +use toxml::ToXml; use util::atom_text; /// Represents the generator of an Atom feed @@ -133,3 +137,25 @@ impl FromXml for Generator { Ok(generator) } } + +impl ToXml for Generator { + fn to_xml(&self, writer: &mut Writer) -> Result<(), XmlError> { + let name = b"generator"; + let mut element = BytesStart::borrowed(name, name.len()); + + if let Some(ref uri) = self.uri { + element.push_attribute(("uri", &**uri)); + } + + if let Some(ref version) = self.version { + element.push_attribute(("version", &**version)); + } + + writer.write_event(Event::Start(element))?; + writer + .write_event(Event::Text(BytesText::borrowed(self.value.as_bytes())))?; + writer.write_event(Event::End(BytesEnd::borrowed(name)))?; + + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index f4209df..e2aeb57 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,7 @@ mod source; mod error; mod fromxml; +mod toxml; mod util; pub use feed::Feed; diff --git a/src/link.rs b/src/link.rs index 5071c81..ad91048 100644 --- a/src/link.rs +++ b/src/link.rs @@ -1,10 +1,14 @@ -use std::io::BufRead; +use std::io::{BufRead, Write}; +use quick_xml::errors::Error as XmlError; +use quick_xml::events::{Event, BytesStart}; use quick_xml::events::attributes::Attributes; use quick_xml::reader::Reader; +use quick_xml::writer::Writer; use error::Error; use fromxml::FromXml; +use toxml::ToXml; /// Represents a link in an Atom feed #[derive(Debug, Clone, PartialEq)] @@ -247,3 +251,32 @@ impl FromXml for Link { Ok(link) } } + +impl ToXml for Link { + fn to_xml(&self, writer: &mut Writer) -> Result<(), XmlError> { + let name = b"link"; + let mut element = BytesStart::borrowed(name, name.len()); + element.push_attribute(("href", &*self.href)); + element.push_attribute(("rel", &*self.rel)); + + if let Some(ref hreflang) = self.hreflang { + element.push_attribute(("hreflang", &**hreflang)); + } + + if let Some(ref mime_type) = self.mime_type { + element.push_attribute(("type", &**mime_type)); + } + + if let Some(ref title) = self.title { + element.push_attribute(("title", &**title)); + } + + if let Some(ref length) = self.length { + element.push_attribute(("length", &**length)); + } + + writer.write_event(Event::Empty(element))?; + + Ok(()) + } +} diff --git a/src/person.rs b/src/person.rs index 822be1d..3a5085c 100644 --- a/src/person.rs +++ b/src/person.rs @@ -1,11 +1,14 @@ -use std::io::BufRead; +use std::io::{BufRead, Write}; +use quick_xml::errors::Error as XmlError; +use quick_xml::events::{Event, BytesStart, BytesEnd}; use quick_xml::events::attributes::Attributes; -use quick_xml::events::Event; use quick_xml::reader::Reader; +use quick_xml::writer::Writer; use error::Error; use fromxml::FromXml; +use toxml::{ToXmlNamed, WriterExt}; use util::atom_text; /// Represents a person in an Atom feed @@ -140,3 +143,27 @@ impl FromXml for Person { Ok(person) } } + +impl ToXmlNamed for Person { + fn to_xml_named(&self, writer: &mut Writer, name: N) -> Result<(), XmlError> + where W: Write, + N: AsRef<[u8]> + { + let name = name.as_ref(); + writer + .write_event(Event::Start(BytesStart::borrowed(name, name.len())))?; + writer.write_text_element(b"name", &*self.name)?; + + if let Some(ref email) = self.email { + writer.write_text_element(b"email", &*email)?; + } + + if let Some(ref uri) = self.uri { + writer.write_text_element(b"uri", &*uri)?; + } + + writer.write_event(Event::End(BytesEnd::borrowed(name)))?; + + Ok(()) + } +} \ No newline at end of file diff --git a/src/source.rs b/src/source.rs index b8b2646..2f5bfc3 100644 --- a/src/source.rs +++ b/src/source.rs @@ -1,8 +1,10 @@ -use std::io::BufRead; +use std::io::{BufRead, Write}; -use quick_xml::events::Event; +use quick_xml::errors::Error as XmlError; +use quick_xml::events::{Event, BytesStart, BytesEnd}; use quick_xml::events::attributes::Attributes; use quick_xml::reader::Reader; +use quick_xml::writer::Writer; use category::Category; use error::Error; @@ -10,6 +12,7 @@ use fromxml::FromXml; use generator::Generator; use link::Link; use person::Person; +use toxml::{ToXml, WriterExt}; use util::atom_text; /// Represents the source of an Atom entry @@ -469,3 +472,44 @@ impl FromXml for Source { Ok(source) } } + +impl ToXml for Source { + fn to_xml(&self, writer: &mut Writer) -> Result<(), XmlError> { + let name = b"source"; + writer + .write_event(Event::Start(BytesStart::borrowed(name, name.len())))?; + writer.write_text_element(b"title", &*self.title)?; + writer.write_text_element(b"id", &*self.id)?; + writer.write_text_element(b"updated", &*self.updated)?; + writer.write_objects_named(&self.authors, "author")?; + writer.write_objects(&self.categories)?; + writer + .write_objects_named(&self.contributors, "contributor")?; + + if let Some(ref generator) = self.generator { + writer.write_object(generator)?; + } + + if let Some(ref icon) = self.icon { + writer.write_text_element(b"icon", &**icon)?; + } + + writer.write_objects(&self.links)?; + + if let Some(ref logo) = self.logo { + writer.write_text_element(b"logo", &**logo)?; + } + + if let Some(ref rights) = self.rights { + writer.write_text_element(b"rights", &**rights)?; + } + + if let Some(ref subtitle) = self.subtitle { + writer.write_text_element(b"subtitle", &**subtitle)?; + } + + writer.write_event(Event::End(BytesEnd::borrowed(name)))?; + + Ok(()) + } +} diff --git a/src/toxml.rs b/src/toxml.rs new file mode 100644 index 0000000..521af68 --- /dev/null +++ b/src/toxml.rs @@ -0,0 +1,100 @@ +use std::io::Write; + +use quick_xml::errors::Error as XmlError; +use quick_xml::events::{Event, BytesStart, BytesEnd, BytesText}; +use quick_xml::writer::Writer; + +pub trait ToXml { + fn to_xml(&self, writer: &mut Writer) -> Result<(), XmlError>; +} + +impl<'a, T: ToXml> ToXml for &'a T { + fn to_xml(&self, writer: &mut Writer) -> Result<(), XmlError> { + (*self).to_xml(writer) + } +} + +pub trait ToXmlNamed { + fn to_xml_named(&self, writer: &mut Writer, name: N) -> Result<(), XmlError> + where W: Write, + N: AsRef<[u8]>; +} + +impl<'a, T: ToXmlNamed> ToXmlNamed for &'a T { + fn to_xml_named(&self, writer: &mut Writer, name: N) -> Result<(), XmlError> + where W: Write, + N: AsRef<[u8]> + { + (*self).to_xml_named(writer, name) + } +} + +pub trait WriterExt { + fn write_text_element(&mut self, name: N, text: T) -> Result<(), XmlError> + where N: AsRef<[u8]>, + T: AsRef<[u8]>; + + fn write_object(&mut self, object: T) -> Result<(), XmlError> where T: ToXml; + + fn write_object_named(&mut self, object: T, name: N) -> Result<(), XmlError> + where T: ToXmlNamed, + N: AsRef<[u8]>; + + fn write_objects(&mut self, objects: I) -> Result<(), XmlError> + where T: ToXml, + I: IntoIterator; + + fn write_objects_named(&mut self, objects: I, name: N) -> Result<(), XmlError> + where T: ToXmlNamed, + I: IntoIterator, + N: AsRef<[u8]>; +} + +impl WriterExt for Writer { + fn write_text_element(&mut self, name: N, text: T) -> Result<(), XmlError> + where N: AsRef<[u8]>, + T: AsRef<[u8]> + { + let name = name.as_ref(); + self.write_event(Event::Start(BytesStart::borrowed(name, name.len())))?; + self.write_event(Event::Text(BytesText::borrowed(text.as_ref())))?; + self.write_event(Event::End(BytesEnd::borrowed(name)))?; + Ok(()) + } + + fn write_object(&mut self, object: T) -> Result<(), XmlError> + where T: ToXml + { + object.to_xml(self) + } + + fn write_object_named(&mut self, object: T, name: N) -> Result<(), XmlError> + where T: ToXmlNamed, + N: AsRef<[u8]> + { + object.to_xml_named(self, name) + } + + fn write_objects(&mut self, objects: I) -> Result<(), XmlError> + where T: ToXml, + I: IntoIterator + { + for object in objects { + object.to_xml(self)?; + } + + Ok(()) + } + + fn write_objects_named(&mut self, objects: I, name: N) -> Result<(), XmlError> + where T: ToXmlNamed, + I: IntoIterator, + N: AsRef<[u8]> + { + for object in objects { + object.to_xml_named(self, name.as_ref())?; + } + + Ok(()) + } +} \ No newline at end of file diff --git a/tests/data/read_category.xml b/tests/data/category.xml similarity index 100% rename from tests/data/read_category.xml rename to tests/data/category.xml diff --git a/tests/data/read_entry.xml b/tests/data/entry.xml similarity index 100% rename from tests/data/read_entry.xml rename to tests/data/entry.xml diff --git a/tests/data/read_feed.xml b/tests/data/feed.xml similarity index 100% rename from tests/data/read_feed.xml rename to tests/data/feed.xml diff --git a/tests/data/read_generator.xml b/tests/data/generator.xml similarity index 100% rename from tests/data/read_generator.xml rename to tests/data/generator.xml diff --git a/tests/data/read_link.xml b/tests/data/link.xml similarity index 100% rename from tests/data/read_link.xml rename to tests/data/link.xml diff --git a/tests/data/read_person.xml b/tests/data/person.xml similarity index 100% rename from tests/data/read_person.xml rename to tests/data/person.xml diff --git a/tests/data/read_source.xml b/tests/data/source.xml similarity index 100% rename from tests/data/read_source.xml rename to tests/data/source.xml diff --git a/tests/read.rs b/tests/read.rs index d0d7bc9..5008660 100644 --- a/tests/read.rs +++ b/tests/read.rs @@ -15,7 +15,7 @@ macro_rules! feed { #[test] fn read_feed() { - let feed = feed!("tests/data/read_feed.xml"); + let feed = feed!("tests/data/feed.xml"); assert_eq!(feed.title(), "Feed Title"); assert_eq!(feed.id(), "urn:uuid:60a76c80-d399-11d9-b91C-0003939e0af6"); assert_eq!(feed.updated(), "2017-06-03T15:15:44-05:00"); @@ -32,7 +32,7 @@ fn read_feed() { #[test] fn read_entry() { - let feed = feed!("tests/data/read_entry.xml"); + let feed = feed!("tests/data/entry.xml"); assert_eq!(feed.entries().len(), 1); let entry = feed.entries().first().unwrap(); @@ -53,7 +53,7 @@ fn read_entry() { #[test] fn read_category() { - let feed = feed!("tests/data/read_category.xml"); + let feed = feed!("tests/data/category.xml"); let category = feed.categories().first().unwrap(); assert_eq!(category.term(), "technology"); assert_eq!(category.scheme(), Some("http://example.com/scheme")); @@ -62,7 +62,7 @@ fn read_category() { #[test] fn read_generator() { - let feed = feed!("tests/data/read_generator.xml"); + let feed = feed!("tests/data/generator.xml"); let generator = feed.generator().unwrap(); assert_eq!(generator.value(), "Example Generator"); assert_eq!(generator.uri(), Some("http://example.com/generator")); @@ -71,7 +71,7 @@ fn read_generator() { #[test] fn read_link() { - let feed = feed!("tests/data/read_link.xml"); + let feed = feed!("tests/data/link.xml"); let link = feed.links().first().unwrap(); assert_eq!(link.rel(), "enclosure"); assert_eq!(link.href(), "http://example.com/audio.mp3"); @@ -83,7 +83,7 @@ fn read_link() { #[test] fn read_person() { - let feed = feed!("tests/data/read_person.xml"); + let feed = feed!("tests/data/person.xml"); let person = feed.authors().first().unwrap(); assert_eq!(person.name(), "John Doe"); assert_eq!(person.email(), Some("johndoe@example.com")); @@ -92,7 +92,7 @@ fn read_person() { #[test] fn read_source() { - let feed = feed!("tests/data/read_source.xml"); + let feed = feed!("tests/data/source.xml"); let entry = feed.entries().first().unwrap(); assert!(entry.source().is_some()); diff --git a/tests/write.rs b/tests/write.rs new file mode 100644 index 0000000..9b12bc9 --- /dev/null +++ b/tests/write.rs @@ -0,0 +1,56 @@ +extern crate atom_syndication as atom; + +use std::io::BufReader; +use std::fs::File; + +use atom::Feed; + +macro_rules! feed { + ($f:expr) => ({ + let file = File::open($f).unwrap(); + let reader = BufReader::new(file); + Feed::read_from(reader).unwrap() + }) +} + +#[test] +fn write_feed() { + let feed = feed!("tests/data/feed.xml"); + assert_eq!(feed.to_string().parse::().unwrap(), feed); +} + +#[test] +fn write_entry() { + let feed = feed!("tests/data/entry.xml"); + assert_eq!(feed.to_string().parse::().unwrap(), feed); +} + +#[test] +fn write_category() { + let feed = feed!("tests/data/category.xml"); + assert_eq!(feed.to_string().parse::().unwrap(), feed); +} + +#[test] +fn write_generator() { + let feed = feed!("tests/data/generator.xml"); + assert_eq!(feed.to_string().parse::().unwrap(), feed); +} + +#[test] +fn write_link() { + let feed = feed!("tests/data/link.xml"); + assert_eq!(feed.to_string().parse::().unwrap(), feed); +} + +#[test] +fn write_person() { + let feed = feed!("tests/data/person.xml"); + assert_eq!(feed.to_string().parse::().unwrap(), feed); +} + +#[test] +fn write_source() { + let feed = feed!("tests/data/source.xml"); + assert_eq!(feed.to_string().parse::().unwrap(), feed); +}