<commit_before>#![feature(old_io)]

extern crate xml;

use xml::attribute::Attribute;
use xml::common::XmlVersion;
use xml::name::Name;
use xml::namespace::Namespace;
use xml::writer::EventWriter;
use xml::writer::events::XmlEvent;


trait Write {
    fn write<W: Writer>(&self, writer: W) -> Result<(), ()>;
}


trait ToXml<'a> {
    // todo: get rid of namespace parameter
    fn to_xml(&'a self, namespace: &'a Namespace) -> Vec<XmlEvent>;
}


/// RSS version 2.0
pub struct Rss(pub Vec<Channel>);

impl<'a> ToXml<'a> for Rss {
    fn to_xml(&'a self, namespace: &'a Namespace) -> Vec<XmlEvent> {
        let mut events = vec![];

        // <?xml version="1.0" encoding="UTF-8"?>
        events.push(XmlEvent::StartDocument{ 
            version: XmlVersion::Version10,
            encoding: Some("UTF-8"),
            standalone: None,
        });

        // <rss version="2.0">
        events.push(XmlEvent::StartElement {
            name: Name::local("rss"),
            attributes: vec![
                Attribute::new(Name::local("version"), "2.0"),
            ],
            namespace: namespace,
        });

        /*
        let &Rss(ref channels) = self;
        for channel in channels {
            for event in channel.to_xml(namespace) {
                events.push(event);
            }
        }
        */

        // </rss>
        events.push(XmlEvent::EndElement {
            name: Name::local("rss"),
        });
        
        events
    }
}

impl Write for Rss {
    fn write<W: Writer>(&self, writer: W) -> Result<(), ()> {
        let mut event_writer = EventWriter::new(writer);

        let namespace = Namespace::empty();
        let events = self.to_xml(&namespace);

        for event in events {
            event_writer.write(event);
        };

        Ok(())
    }
}


pub struct Channel {
    pub title: String,
    pub link: String,
    pub description: String,
    pub items: Vec<Item>,
}

/*
impl<'a> ToXml<'a> for Channel {
    fn to_xml(&self) -> Vec<XmlEvent> {
        vec![]
    }
}
*/

pub struct Item {
    pub title: Option<String>,
    pub link: Option<String>,
    pub description: Option<String>,
}


#[test]
fn test_consruct() {
    use std::old_io;
    let rss = Rss(vec![]);
    rss.write(old_io::stdout());
}<commit_msg>Implement to_xml for Channel<commit_after>#![feature(old_io)]

extern crate xml;

use xml::attribute::Attribute;
use xml::common::XmlVersion;
use xml::name::Name;
use xml::namespace::Namespace;
use xml::writer::EventWriter;
use xml::writer::events::XmlEvent;


fn add_block<'a>(events: &mut Vec<XmlEvent<'a>>, namespace: &'a Namespace, tag_name: &'static str, chars: &'a String) {
    // <(tag_name)>
    events.push(XmlEvent::StartElement {
        name: Name::local(tag_name),
        attributes: vec![],
        namespace: namespace,
    });

    events.push(XmlEvent::Characters(chars));
    
    // </(tag_name)>
    events.push(XmlEvent::EndElement {
        name: Name::local(tag_name),
    });
}


trait Write {
    fn write<W: Writer>(&self, writer: W) -> Result<(), ()>;
}


trait ToXml<'a> {
    // todo: get rid of namespace parameter
    fn to_xml(&'a self, namespace: &'a Namespace) -> Vec<XmlEvent>;
}


/// RSS version 2.0
pub struct Rss(pub Vec<Channel>);

impl<'a> ToXml<'a> for Rss {
    fn to_xml(&'a self, namespace: &'a Namespace) -> Vec<XmlEvent> {
        let mut events = vec![];

        // <?xml version="1.0" encoding="UTF-8"?>
        events.push(XmlEvent::StartDocument{ 
            version: XmlVersion::Version10,
            encoding: Some("UTF-8"),
            standalone: None,
        });

        // <rss version="2.0">
        events.push(XmlEvent::StartElement {
            name: Name::local("rss"),
            attributes: vec![
                Attribute::new(Name::local("version"), "2.0"),
            ],
            namespace: namespace,
        });

        let &Rss(ref channels) = self;
        for channel in channels {
            for event in channel.to_xml(namespace) {
                events.push(event);
            }
        }

        // </rss>
        events.push(XmlEvent::EndElement {
            name: Name::local("rss"),
        });
        
        events
    }
}

impl Write for Rss {
    fn write<W: Writer>(&self, writer: W) -> Result<(), ()> {
        let mut event_writer = EventWriter::new(writer);

        let namespace = Namespace::empty();
        let events = self.to_xml(&namespace);

        for event in events {
            event_writer.write(event);
        };

        Ok(())
    }
}


pub struct Channel {
    pub title: String,
    pub link: String,
    pub description: String,
    pub items: Vec<Item>,
}

impl<'a> ToXml<'a> for Channel {
    fn to_xml(&'a self, namespace: &'a Namespace) -> Vec<XmlEvent> {
        let mut events = vec![];

        // <channel>
        events.push(XmlEvent::StartElement {
            name: Name::local("channel"),
            attributes: vec![],
            namespace: namespace,
        });

        add_block(&mut events, namespace, "title", &self.title);
        add_block(&mut events, namespace, "link", &self.link);
        add_block(&mut events, namespace, "description", &self.description);

        // </channel>
        events.push(XmlEvent::EndElement {
            name: Name::local("channel"),
        });

        events
    }
}

pub struct Item {
    pub title: Option<String>,
    pub link: Option<String>,
    pub description: Option<String>,
}


#[test]
fn test_consruct() {
    use std::old_io;

    let channel = Channel {
        title: String::from_str("My Blog"),
        link: String::from_str("http://myblog.com"),
        description: String::from_str("Where I write stuff"),
        items: vec![],
    };

    let rss = Rss(vec![channel]);
    rss.write(old_io::stdout());
}
{'fraction_non_alphanumeric': 0.16046190968631507, 'fraction_numerical': 0.004136504653567736, 'mean_word_length': 2.2766798418972334, 'pattern_counts': {'":': 0, '<': 50, '<?xml version=': 2, '>': 60, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 27}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2787154', 'n_tokens_mistral': 1825, 'n_tokens_neox': 1788, 'n_words': 419}