danceinterpreter-rs 0.3.0

Danceinterpreter in Rust
use std::io;
use std::io::Result;
use std::path::{Path, PathBuf};

use crate::dataloading::id3tagreader::read_song_info_from_filepath;
use crate::dataloading::songinfo::SongInfo;
use percent_encoding::percent_decode_str;
use url::Url;

pub fn load_tag_data_from_m3u(path: &Path) -> Result<Vec<SongInfo>> {
    let files = load_m3u_content_from_path(path)?;
    let mut songtags: Vec<SongInfo> = Vec::new();

    for file in files {
        let tag = read_song_info_from_filepath(&file).map_err(|e| {
            io::Error::new(
                io::ErrorKind::InvalidData,
                format!("Error reading tag from file: {}", e),
            )
        })?;
        songtags.push(tag);
    }

    Ok(songtags)
}

fn load_m3u_content_from_path(path: &Path) -> Result<Vec<PathBuf>> {
    let m3u_content = std::fs::read_to_string(path)?;
    let root = path.parent().unwrap();

    let entries = m3u_content.lines().filter(|x| !x.starts_with('#'));

    let absolute_paths = entries
        .map(|entry| parse_file_uri(entry).unwrap_or(parse_encoded_file_name(entry)))
        .map(|entry| root.join(entry));

    let accessible_files = absolute_paths.filter(|entry| entry.exists());

    Ok(accessible_files.collect::<Vec<PathBuf>>())
}

fn parse_file_uri(uri: &str) -> Option<PathBuf> {
    let uri = Url::parse(uri).ok()?;
    uri.to_file_path().ok()
}

fn parse_encoded_file_name(file: &str) -> PathBuf {
    PathBuf::from(percent_decode_str(file).decode_utf8_lossy().to_string())
}

#[cfg(test)]
#[macro_use]
mod tests {
    use std::path::Path;

    use crate::dataloading::m3uloader::{load_m3u_content_from_path, load_tag_data_from_m3u};
    use crate::test_file;

    #[test]
    fn m3u_path_parsing() {
        let result = load_m3u_content_from_path(Path::new(test_file!("m3u_validation_test.m3u")));
        assert!(result.is_ok());
        #[cfg(not(windows))]
        assert_eq!(result.unwrap().len(), 4);
        #[cfg(windows)]
        assert_eq!(result.unwrap().len(), 2);
    }

    #[test]
    fn m3u_files_id3_tag_loading() {
        let result = load_tag_data_from_m3u(Path::new(test_file!("id3_read_test.m3u")));
        assert!(result.is_ok());
        let res = result.unwrap()[0].clone();
        assert_eq!(res.title, "Sine Test");
        assert_eq!(res.artist, "K7");
        assert_eq!(res.dance, "Test Dance");
    }
}