use std::fs::File; use std::io::{self, BufRead, Write}; use std::path::Path; use std::string::String; fn read_lines

(path: P) -> io::Result>> where P: AsRef, { let file = File::open(path)?; Ok(io::BufReader::new(file).lines()) } #[derive(Debug)] pub struct PlaylistTrack { pub duration: String, pub display: String, pub track: String } impl PlaylistTrack { pub fn new(duration: Option, display: Option, track: &str) -> PlaylistTrack { PlaylistTrack { duration: duration.unwrap_or(String::from("")), display: display.unwrap_or(String::from("")), track: String::from(track) } } pub fn render(&self) -> String { format!("#EXTINFO:{},{}\n{}\n", self.duration, self.display, self.track) } } #[derive(Debug)] pub struct Playlist { pub path: String, pub tracks: Box> } impl Playlist { pub fn new(path: &str, tracks: Vec) -> Playlist { Playlist { path: String::from(path), tracks: Box::new(tracks) } } pub fn read(path: &str) -> Result { let mut playlist_tracks: Vec = Vec::new(); let lines = read_lines(path)?; let mut found_header = false; let mut duration: Option = None; let mut display: Option = None; lines.for_each(|read_line| { if read_line.is_ok() { let line = read_line.unwrap(); if line.len() > 0 { if line.starts_with("#") { if line.starts_with("#EXTINF:") { found_header = true; let slice = String::from(&line[8..]); let split = slice.split(","); let parts: Vec<&str> = split.collect(); if parts[0].len() > 0 { duration = Some(String::from(parts[0])) } if parts[1].len() > 0 { display = Some(String::from(parts[1])) } } } else { if ! found_header { panic!("Misformatted m3u!!!"); } let track = &line; playlist_tracks.push(PlaylistTrack::new(duration.clone(), display.clone(), track)); duration = None; display = None; found_header = false; } } } }); Ok(Playlist::new(path, playlist_tracks)) } pub fn write(&self, path: &str) -> Result<(), io::Error> { let mut file = File::create(path)?; file.write("#EXTM3U\n".as_bytes())?; for track in &*self.tracks { file.write(track.render().as_bytes())?; } Ok(()) } }