diff --git a/src/music_storage/music_db.rs b/src/music_storage/music_db.rs index 4e6e226..e79eae8 100644 --- a/src/music_storage/music_db.rs +++ b/src/music_storage/music_db.rs @@ -730,49 +730,43 @@ impl MusicLibrary { // Sort the returned list of songs new_songs.par_sort_by(|a, b| { - for opt in sort_by { - let tag_a = match opt { + for sort_option in sort_by { + let tag_a = match sort_option { Tag::Field(field_selection) => match a.get_field(field_selection) { Some(field_value) => field_value, None => continue, }, - _ => match a.get_tag(&opt) { + _ => match a.get_tag(&sort_option) { Some(tag_value) => tag_value.to_owned(), None => continue, }, }; - let tag_b = match opt { + let tag_b = match sort_option { Tag::Field(field_selection) => match b.get_field(field_selection) { Some(field_value) => field_value, None => continue, }, - _ => match b.get_tag(&opt) { + _ => match b.get_tag(&sort_option) { Some(tag_value) => tag_value.to_owned(), None => continue, }, }; - // Try to parse the tags as f64 if let (Ok(num_a), Ok(num_b)) = (tag_a.parse::(), tag_b.parse::()) { // If parsing succeeds, compare as numbers - if num_a < num_b { - return std::cmp::Ordering::Less; - } else if num_a > num_b { - return std::cmp::Ordering::Greater; - } + return num_a.cmp(&num_b); } else { // If parsing fails, compare as strings - if tag_a < tag_b { - return std::cmp::Ordering::Less; - } else if tag_a > tag_b { - return std::cmp::Ordering::Greater; - } + return tag_a.cmp(&tag_b); } } // If all tags are equal, sort by Track number - a.get_tag(&Tag::Track).cmp(&b.get_tag(&Tag::Track)) + let path_a = PathBuf::from(a.get_field("location").unwrap()); + let path_b = PathBuf::from(b.get_field("location").unwrap()); + + path_a.file_name().cmp(&path_b.file_name()) }); if new_songs.len() > 0 { @@ -786,22 +780,22 @@ impl MusicLibrary { pub fn albums(&self) -> BTreeMap { let mut albums: BTreeMap = BTreeMap::new(); for result in &self.library { - let title = match result.get_tag(&Tag::Album){ + let title = match result.get_tag(&Tag::Album) { Some(title) => title, None => continue }; - let disc_num = result.get_tag(&Tag::Disk).unwrap_or(&"".to_string()).parse::().unwrap_or(1); - let norm_title = normalize(title); + + let disc_num = result.get_tag(&Tag::Disk).unwrap_or(&"".to_string()).parse::().unwrap_or(1); match albums.get_mut(&norm_title) { + // If the album is in the list, add the track to the appropriate disc in it Some(album) => { match album.discs.get_mut(&disc_num) { Some(disc) => disc.push(result), - None => { - album.discs.insert(disc_num, vec![result]); - } + None => {album.discs.insert(disc_num, vec![result]);} } }, + // If the album is not in the list, make a new one and add it None => { let new_album = Album { title, @@ -814,27 +808,29 @@ impl MusicLibrary { } } + // Sort the tracks in each disk in each album let blank = String::from(""); albums.par_iter_mut().for_each(|album| { for disc in &mut album.1.discs { disc.1.par_sort_by(|a, b| { - if let (Ok(num_a), Ok(num_b)) = ( - a.get_tag(&Tag::Title).unwrap_or(&blank).parse::(), - b.get_tag(&Tag::Title).unwrap_or(&blank).parse::() - ) { - // If parsing succeeds, compare as numbers - match num_a < num_b { - true => return std::cmp::Ordering::Less, - false => return std::cmp::Ordering::Greater - } - } - match a.get_field("location").unwrap() < b.get_field("location").unwrap() { - true => return std::cmp::Ordering::Less, - false => return std::cmp::Ordering::Greater + let a_track = a.get_tag(&Tag::Track).unwrap_or(&blank); + let b_track = b.get_tag(&Tag::Track).unwrap_or(&blank); + + if let (Ok(num_a), Ok(num_b)) = (a_track.parse::(), b_track.parse::()) { + // If parsing the track numbers succeeds, compare as numbers + num_a.cmp(&num_b) + } else { + // If parsing doesn't succeed, compare the locations + let path_a = PathBuf::from(a.get_field("location").unwrap()); + let path_b = PathBuf::from(b.get_field("location").unwrap()); + + path_a.file_name().cmp(&path_b.file_name()) } }); } }); + + // Return the albums! albums } diff --git a/src/music_storage/utils.rs b/src/music_storage/utils.rs index 1a6d8a4..59cb4d8 100644 --- a/src/music_storage/utils.rs +++ b/src/music_storage/utils.rs @@ -1,8 +1,5 @@ use std::io::{BufReader, BufWriter}; use std::{path::PathBuf, error::Error, fs}; -use flate2::Compression; -use flate2::write::ZlibEncoder; -use flate2::read::ZlibDecoder; use snap; @@ -10,37 +7,40 @@ use unidecode::unidecode; use crate::music_storage::music_db::Song; pub fn normalize(input_string: &String) -> String { + // Normalize the unicode and convert everything to lowercase let mut normalized = unidecode(input_string); // Remove non alphanumeric characters - normalized.retain(|c| c.is_alphabetic()); - normalized = normalized.to_ascii_lowercase(); + normalized.retain(|c| c.is_alphanumeric()); normalized } pub fn read_library(path: PathBuf) -> Result, Box> { + + // Create a new snap reader over the database file let database = fs::File::open(path)?; let reader = BufReader::new(database); - //let mut d = ZlibDecoder::new(reader); - let mut d = snap::read::FrameDecoder::new(reader); + // Decode the library from the serialized data into the vec let library: Vec = bincode::serde::decode_from_std_read(&mut d, bincode::config::standard().with_little_endian().with_variable_int_encoding())?; Ok(library) } pub fn write_library(library: &Vec, path: PathBuf, take_backup: bool) -> Result<(), Box> { + + // Create 2 new names for the file, a temporary one for writing out, and a backup let mut writer_name = path.clone(); writer_name.set_extension("tmp"); let mut backup_name = path.clone(); backup_name.set_extension("bkp"); + // Create a new BufWriter on the file and make a snap frame encoer for it too let writer = BufWriter::new(fs::File::create(writer_name.to_path_buf())?); - //let mut e = ZlibEncoder::new(writer, Compression::default()); - let mut e = snap::write::FrameEncoder::new(writer); + // Write out the data using bincode bincode::serde::encode_into_std_write(&library, &mut e, bincode::config::standard().with_little_endian().with_variable_int_encoding())?; if path.exists() && take_backup {