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;
|
pub mod library;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
|
cmp::Ordering,
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
fmt,
|
fmt,
|
||||||
|
iter::Peekable, mem,
|
||||||
};
|
};
|
||||||
|
|
||||||
use database::IDatabase;
|
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.
|
/// The album identifier.
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, PartialOrd, Ord, Eq, Hash)]
|
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, PartialOrd, Ord, Eq, Hash)]
|
||||||
pub struct AlbumId {
|
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.
|
/// The artist identifier.
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct ArtistId {
|
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.
|
/// The collection type. Currently, a collection is a list of artists.
|
||||||
pub type Collection = Vec<Artist>;
|
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`.
|
/// Error type for `musichoard`.
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@ -163,8 +238,23 @@ impl<LIB: ILibrary, DB: IDatabase> MusicHoard<LIB, DB> {
|
|||||||
|
|
||||||
pub fn rescan_library(&mut self) -> Result<(), Error> {
|
pub fn rescan_library(&mut self) -> Result<(), Error> {
|
||||||
let items = self.library.list(&Query::new())?;
|
let items = self.library.list(&Query::new())?;
|
||||||
self.collection = Self::items_to_artists(items);
|
let mut library = Self::items_to_artists(items);
|
||||||
Self::sort(&mut self.collection);
|
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(())
|
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> {
|
fn items_to_artists(items: Vec<Item>) -> Vec<Artist> {
|
||||||
let mut artists: Vec<Artist> = vec![];
|
let mut artists: Vec<Artist> = vec![];
|
||||||
let mut album_ids = HashMap::<ArtistId, HashSet<AlbumId>>::new();
|
let mut album_ids = HashMap::<ArtistId, HashSet<AlbumId>>::new();
|
||||||
|
Loading…
Reference in New Issue
Block a user