Skip to content

Commit

Permalink
Added writing
Browse files Browse the repository at this point in the history
  • Loading branch information
James Hurst committed Jun 11, 2017
1 parent 9cb8e2b commit 338c840
Show file tree
Hide file tree
Showing 19 changed files with 516 additions and 54 deletions.
26 changes: 25 additions & 1 deletion src/category.rs
Original file line number Diff line number Diff line change
@@ -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)]
Expand Down Expand Up @@ -133,3 +137,23 @@ impl FromXml for Category {
Ok(category)
}
}

impl ToXml for Category {
fn to_xml<W: Write>(&self, writer: &mut Writer<W>) -> 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(())
}
}
36 changes: 35 additions & 1 deletion src/content.rs
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -138,3 +142,33 @@ impl FromXml for Content {
Ok(content)
}
}

impl ToXml for Content {
fn to_xml<W: Write>(&self, writer: &mut Writer<W>) -> 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(())
}
}
115 changes: 79 additions & 36 deletions src/entry.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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
Expand All @@ -32,12 +35,12 @@ pub struct Entry {
links: Vec<Link>,
/// The time of the initial creation or first availability of the entry.
published: Option<String>,
/// Information about rights held in and over the entry.
rights: Option<String>,
/// The source information if an entry is copied from one feed into another feed.
source: Option<Source>,
/// A short summary, abstract, or excerpt of the entry.
summary: Option<String>,
/// Information about rights held in and over the entry.
rights: Option<String>,
/// Contains or links to the complete content of the entry.
content: Option<Content>,
}
Expand Down Expand Up @@ -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<V>(&mut self, rights: V)
where V: Into<Option<String>>
{
self.rights = rights.into();
}

/// Return the source of this entry if it was copied from another feed.
///
/// # Examples
Expand Down Expand Up @@ -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<V>(&mut self, rights: V)
where V: Into<Option<String>>
{
self.rights = rights.into();
}

/// Return the content of this entry.
///
/// # Examples
Expand Down Expand Up @@ -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())?)
}
Expand All @@ -472,3 +475,43 @@ impl FromXml for Entry {
Ok(entry)
}
}

impl ToXml for Entry {
fn to_xml<W: Write>(&self, writer: &mut Writer<W>) -> 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(())
}
}
80 changes: 77 additions & 3 deletions src/feed.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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<W: Write>(&self, writer: W) -> Result<W, Error> {
let mut writer = Writer::new(writer);
self.to_xml(&mut writer)?;
Ok(writer.into_inner())
}

/// Return the title of this feed.
///
/// # Examples
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -542,10 +565,61 @@ impl FromXml for Feed {
}
}

impl ToXml for Feed {
fn to_xml<W: Write>(&self, writer: &mut Writer<W>) -> 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;

fn from_str(s: &str) -> Result<Self, Error> {
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()
}
}
Loading

0 comments on commit 338c840

Please sign in to comment.