playlist-decoder 0.10.1

a simple playlist decoder which supports: m3u, pls, asx and xspf
Documentation
use crate::PlaylistDecodeError;
use quick_xml::events::Event;
use quick_xml::Reader;

#[derive(Clone)]
pub struct PlaylistItem {
    pub title: String,
    pub url: String,
}

pub fn decode(content: &str) -> Result<Vec<PlaylistItem>, PlaylistDecodeError> {
    let mut list = vec![];
    let mut item = PlaylistItem {
        title: String::from(""),
        url: String::from(""),
    };

    let mut reader = Reader::from_str(content);
    let mut xml_stack = vec![];
    let mut buf = Vec::new();
    loop {
        match reader.read_event_into(&mut buf) {
            Ok(Event::Empty(ref e)) => {
                xml_stack.push(reader.decoder().decode(e.name().as_ref())?.to_lowercase());

                let path = xml_stack.join("/");
                for a in e.attributes() {
                    let a = a?;
                    let key = reader.decoder().decode(a.key.as_ref())?.to_lowercase();
                    let value = reader.decoder().decode(&a.value)?;
                    if path == "asx/entry/ref" {
                        if key == "href" {
                            item.url = value.to_string();
                        }
                    }
                }

                xml_stack.pop();
            }
            Ok(Event::Start(ref e)) => {
                xml_stack.push(reader.decoder().decode(e.name().as_ref())?.to_lowercase());

                let path = xml_stack.join("/");
                for a in e.attributes() {
                    let a = a?;
                    let key = reader.decoder().decode(a.key.as_ref())?.to_lowercase();
                    let value = reader.decoder().decode(&a.value)?;
                    if path == "asx/entry/ref" {
                        if key == "href" {
                            item.url = value.to_string();
                        }
                    }
                }
            }
            Ok(Event::End(_)) => {
                let path = xml_stack.join("/");
                if path == "asx/entry" {
                    list.push(item.clone());
                    item.title = String::from("");
                    item.url = String::from("");
                }
                xml_stack.pop();
            }
            Ok(Event::Text(e)) => {
                let path = xml_stack.join("/");
                if path == "asx/entry/title" {
                    item.title = e.decode()?.to_string();
                }
            }
            Ok(Event::Eof) => break,
            Err(e) => {
                println!("Error at position {}: {:?}", reader.buffer_position(), e);
                break;
            }
            _ => (), // There are several other `Event`s we do not consider here
        }
        buf.clear();
    }

    Ok(list)
}