diff --git a/src/core/collection/artist.rs b/src/core/collection/artist.rs index 8ba0dca..ada3dd4 100644 --- a/src/core/collection/artist.rs +++ b/src/core/collection/artist.rs @@ -5,7 +5,7 @@ use std::{ use crate::core::collection::{ album::{Album, AlbumLibId}, - merge::{Merge, MergeId}, + merge::{Merge, MergeName}, musicbrainz::{MbArtistRef, MbRefOption}, }; @@ -30,11 +30,9 @@ pub struct ArtistInfo { pub properties: HashMap>, } -impl MergeId for Artist { - type Id = ArtistId; - - fn id(&self) -> &Self::Id { - &self.meta.id +impl MergeName for Artist { + fn name(&self) -> &str { + &self.meta.id.name } } diff --git a/src/core/collection/merge.rs b/src/core/collection/merge.rs index 42d833a..bf9f061 100644 --- a/src/core/collection/merge.rs +++ b/src/core/collection/merge.rs @@ -80,36 +80,30 @@ where } } -pub trait MergeId { - type Id; - - fn id(&self) -> &Self::Id; +pub trait MergeName { + fn name(&self) -> &str; } -pub struct MergeCollections { - _id: PhantomData, +pub struct MergeCollections { _t: PhantomData, _it: PhantomData, } -impl MergeCollections +impl MergeCollections where - ID: Eq + Hash + Clone, - T: MergeId + Merge + Ord, - IT: IntoIterator, + T: MergeName + Merge + Ord, + IT: IntoIterator)>, { - pub fn merge(mut primary: HashMap, secondary: IT) -> Vec { - for secondary_item in secondary { - if let Some(ref mut primary_item) = primary.get_mut(secondary_item.id()) { - primary_item.merge_in_place(secondary_item); - } else { - primary.insert(secondary_item.id().clone(), secondary_item); + pub fn merge_by_name(primary_items: &mut Vec, secondary: IT) { + for (name, mut secondary_items) in secondary.into_iter() { + match primary_items.iter_mut().find(|item| item.name() == &name) { + Some(ref mut primary_item) => { + // We do not support merging multiple DB items with same name yet. + assert_eq!(secondary_items.len(), 1); + primary_item.merge_in_place(secondary_items.pop().unwrap()); + } + None => primary_items.append(&mut secondary_items), } } - - let mut collection: Vec = primary.into_values().collect(); - collection.sort_unstable(); - - collection } } diff --git a/src/core/musichoard/base.rs b/src/core/musichoard/base.rs index 71496e9..32a429c 100644 --- a/src/core/musichoard/base.rs +++ b/src/core/musichoard/base.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use crate::core::{ collection::{ album::{Album, AlbumId}, @@ -57,7 +59,20 @@ impl IMusicHoardBasePrivate for MusicHoard } fn merge_collections(&self) -> Collection { - MergeCollections::merge(self.library_cache.clone(), self.database_cache.clone()) + let mut primary = self.library_cache.clone(); + let mut secondary = HashMap::>::new(); + + for artist in self.database_cache.iter().cloned() { + secondary + .entry(artist.meta.id.name.clone()) + .or_default() + .push(artist); + } + + MergeCollections::merge_by_name(&mut primary, secondary); + primary.sort_unstable(); + + primary } fn get_artist<'a>(collection: &'a Collection, artist_id: &ArtistId) -> Option<&'a Artist> { @@ -118,11 +133,7 @@ mod tests { expected.sort_unstable(); let mut mh = MusicHoard { - library_cache: left - .clone() - .into_iter() - .map(|a| (a.meta.id.clone(), a)) - .collect(), + library_cache: left.clone(), database_cache: right.clone(), ..Default::default() }; @@ -132,11 +143,7 @@ mod tests { // The merge is completely non-overlapping so it should be commutative. let mut mh = MusicHoard { - library_cache: right - .clone() - .into_iter() - .map(|a| (a.meta.id.clone(), a)) - .collect(), + library_cache: right.clone(), database_cache: left.clone(), ..Default::default() }; @@ -156,11 +163,7 @@ mod tests { expected.sort_unstable(); let mut mh = MusicHoard { - library_cache: left - .clone() - .into_iter() - .map(|a| (a.meta.id.clone(), a)) - .collect(), + library_cache: left.clone(), database_cache: right.clone(), ..Default::default() }; @@ -170,11 +173,7 @@ mod tests { // The merge does not overwrite any data so it should be commutative. let mut mh = MusicHoard { - library_cache: right - .clone() - .into_iter() - .map(|a| (a.meta.id.clone(), a)) - .collect(), + library_cache: right.clone(), database_cache: left.clone(), ..Default::default() }; @@ -207,11 +206,7 @@ mod tests { expected.rotate_right(1); let mut mh = MusicHoard { - library_cache: left - .clone() - .into_iter() - .map(|a| (a.meta.id.clone(), a)) - .collect(), + library_cache: left.clone(), database_cache: right.clone(), ..Default::default() }; @@ -221,11 +216,7 @@ mod tests { // The merge overwrites the sort data, but no data is erased so it should be commutative. let mut mh = MusicHoard { - library_cache: right - .clone() - .into_iter() - .map(|a| (a.meta.id.clone(), a)) - .collect(), + library_cache: right.clone(), database_cache: left.clone(), ..Default::default() }; diff --git a/src/core/musichoard/builder.rs b/src/core/musichoard/builder.rs index 41eba10..5ea72ce 100644 --- a/src/core/musichoard/builder.rs +++ b/src/core/musichoard/builder.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use crate::core::{ interface::{database::IDatabase, library::ILibrary}, musichoard::{database::IMusicHoardDatabase, Error, MusicHoard, NoDatabase, NoLibrary}, @@ -69,7 +67,7 @@ impl MusicHoard { database: NoDatabase, database_cache: vec![], library: NoLibrary, - library_cache: HashMap::new(), + library_cache: vec![], } } } @@ -90,7 +88,7 @@ impl MusicHoard { database: NoDatabase, database_cache: vec![], library, - library_cache: HashMap::new(), + library_cache: vec![], } } } @@ -111,7 +109,7 @@ impl MusicHoard { database, database_cache: vec![], library: NoLibrary, - library_cache: HashMap::new(), + library_cache: vec![], }; mh.reload_database()?; Ok(mh) @@ -134,7 +132,7 @@ impl MusicHoard { database, database_cache: vec![], library, - library_cache: HashMap::new(), + library_cache: vec![], }; mh.reload_database()?; Ok(mh) diff --git a/src/core/musichoard/library.rs b/src/core/musichoard/library.rs index 056494d..d439272 100644 --- a/src/core/musichoard/library.rs +++ b/src/core/musichoard/library.rs @@ -42,12 +42,12 @@ impl MusicHoard { fn rescan_library_inner(&mut self) -> Result { let items = self.library.list(&Query::new())?; self.library_cache = Self::items_to_artists(items)?; - Self::sort_albums_and_tracks(self.library_cache.values_mut()); + Self::sort_albums_and_tracks(self.library_cache.iter_mut()); Ok(self.merge_collections()) } - fn items_to_artists(items: Vec) -> Result, Error> { + fn items_to_artists(items: Vec) -> Result { let mut collection = HashMap::::new(); for item in items.into_iter() { @@ -122,7 +122,7 @@ impl MusicHoard { } } - Ok(collection) + Ok(collection.into_values().collect()) } } diff --git a/src/core/musichoard/mod.rs b/src/core/musichoard/mod.rs index 435ec7d..f6ba502 100644 --- a/src/core/musichoard/mod.rs +++ b/src/core/musichoard/mod.rs @@ -10,15 +10,9 @@ pub use base::IMusicHoardBase; pub use database::IMusicHoardDatabase; pub use library::IMusicHoardLibrary; -use std::{ - collections::HashMap, - fmt::{self, Display}, -}; +use std::fmt::{self, Display}; -use crate::core::collection::{ - artist::{Artist, ArtistId}, - Collection, -}; +use crate::core::collection::Collection; use crate::core::interface::{ database::{LoadError as DatabaseLoadError, SaveError as DatabaseSaveError}, @@ -35,7 +29,7 @@ pub struct MusicHoard { database: Database, database_cache: Collection, library: Library, - library_cache: HashMap, + library_cache: Collection, } /// Phantom type for when a library implementation is not needed.