You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
3.0 KiB

use std::fs::File;
use std::io::{self, BufRead, Write};
use std::path::Path;
use std::string::String;
fn read_lines<P>(path: P) -> io::Result<io::Lines<io::BufReader<File>>>
where P: AsRef<Path>, {
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<String>, display: Option<String>, 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<Vec<PlaylistTrack>>
}
impl Playlist {
pub fn new(path: &str, tracks: Vec<PlaylistTrack>) -> Playlist {
Playlist {
path: String::from(path),
tracks: Box::new(tracks)
}
}
pub fn read(path: &str) -> Result<Playlist, io::Error> {
let mut playlist_tracks: Vec<PlaylistTrack> = Vec::new();
let lines = read_lines(path)?;
let mut found_header = false;
let mut duration: Option<String> = None;
let mut display: Option<String> = 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(())
}
}