Add code for merging
This commit is contained in:
parent
970a7786e9
commit
6a90b6cf78
98
src/lib.rs
98
src/lib.rs
@ -4,8 +4,10 @@ pub mod database;
|
||||
pub mod library;
|
||||
|
||||
use std::{
|
||||
cmp::Ordering,
|
||||
collections::{HashMap, HashSet},
|
||||
fmt,
|
||||
iter::Peekable, mem,
|
||||
};
|
||||
|
||||
use database::IDatabase;
|
||||
@ -57,6 +59,13 @@ impl Ord for Track {
|
||||
}
|
||||
}
|
||||
|
||||
impl Merge for Track {
|
||||
fn merge(self, other: Self) -> Self {
|
||||
assert_eq!(self.id, other.id);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// The album identifier.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, PartialOrd, Ord, Eq, Hash)]
|
||||
pub struct AlbumId {
|
||||
@ -83,6 +92,14 @@ impl Ord for Album {
|
||||
}
|
||||
}
|
||||
|
||||
impl Merge for Album {
|
||||
fn merge(mut self, other: Self) -> Self {
|
||||
assert_eq!(self.id, other.id);
|
||||
self.tracks = MergeSorted::new(self.tracks.into_iter(), other.tracks.into_iter()).collect();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// The artist identifier.
|
||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct ArtistId {
|
||||
@ -108,9 +125,67 @@ impl Ord for Artist {
|
||||
}
|
||||
}
|
||||
|
||||
impl Merge for Artist {
|
||||
fn merge(mut self, other: Self) -> Self {
|
||||
assert_eq!(self.id, other.id);
|
||||
self.albums = MergeSorted::new(self.albums.into_iter(), other.albums.into_iter()).collect();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// The collection type. Currently, a collection is a list of artists.
|
||||
pub type Collection = Vec<Artist>;
|
||||
|
||||
trait Merge {
|
||||
fn merge(self, other: Self) -> Self;
|
||||
}
|
||||
|
||||
struct MergeSorted<L, R>
|
||||
where
|
||||
L: Iterator<Item = R::Item>,
|
||||
R: Iterator,
|
||||
{
|
||||
left: Peekable<L>,
|
||||
right: Peekable<R>,
|
||||
}
|
||||
|
||||
impl<L, R> MergeSorted<L, R>
|
||||
where
|
||||
L: Iterator<Item = R::Item>,
|
||||
R: Iterator,
|
||||
{
|
||||
fn new(left: L, right: R) -> MergeSorted<L, R> {
|
||||
MergeSorted {
|
||||
left: left.peekable(),
|
||||
right: right.peekable(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<L, R> Iterator for MergeSorted<L, R>
|
||||
where
|
||||
L: Iterator<Item = R::Item>,
|
||||
R: Iterator,
|
||||
L::Item: Ord + Merge,
|
||||
{
|
||||
type Item = L::Item;
|
||||
|
||||
fn next(&mut self) -> Option<L::Item> {
|
||||
let which = match (self.left.peek(), self.right.peek()) {
|
||||
(Some(l), Some(r)) => l.cmp(r),
|
||||
(Some(_), None) => Ordering::Less,
|
||||
(None, Some(_)) => Ordering::Greater,
|
||||
(None, None) => return None,
|
||||
};
|
||||
|
||||
match which {
|
||||
Ordering::Less => self.left.next(),
|
||||
Ordering::Equal => Some(self.left.next().unwrap().merge(self.right.next().unwrap())),
|
||||
Ordering::Greater => self.right.next(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Error type for `musichoard`.
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum Error {
|
||||
@ -163,8 +238,23 @@ impl<LIB: ILibrary, DB: IDatabase> MusicHoard<LIB, DB> {
|
||||
|
||||
pub fn rescan_library(&mut self) -> Result<(), Error> {
|
||||
let items = self.library.list(&Query::new())?;
|
||||
self.collection = Self::items_to_artists(items);
|
||||
Self::sort(&mut self.collection);
|
||||
let mut library = Self::items_to_artists(items);
|
||||
Self::sort(&mut library);
|
||||
|
||||
let collection = mem::replace(&mut self.collection, vec![]);
|
||||
self.collection = Self::merge(library, collection);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load_from_database(&mut self) -> Result<(), Error> {
|
||||
let mut database: Collection = vec![];
|
||||
self.database.read(&mut database)?;
|
||||
Self::sort(&mut database);
|
||||
|
||||
let collection = mem::replace(&mut self.collection, vec![]);
|
||||
self.collection = Self::merge(collection, database);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -187,6 +277,10 @@ impl<LIB: ILibrary, DB: IDatabase> MusicHoard<LIB, DB> {
|
||||
}
|
||||
}
|
||||
|
||||
fn merge(primary: Vec<Artist>, secondary: Vec<Artist>) -> Vec<Artist> {
|
||||
MergeSorted::new(primary.into_iter(), secondary.into_iter()).collect()
|
||||
}
|
||||
|
||||
fn items_to_artists(items: Vec<Item>) -> Vec<Artist> {
|
||||
let mut artists: Vec<Artist> = vec![];
|
||||
let mut album_ids = HashMap::<ArtistId, HashSet<AlbumId>>::new();
|
||||
|
Loading…
Reference in New Issue
Block a user