Break down the musichoard files #165
@ -8,7 +8,7 @@ use musichoard::{
|
||||
MusicHoard, MusicHoardBuilder, NoLibrary,
|
||||
};
|
||||
|
||||
type MH = MusicHoard<NoLibrary, JsonDatabase<JsonDatabaseFileBackend>>;
|
||||
type MH = MusicHoard<JsonDatabase<JsonDatabaseFileBackend>, NoLibrary>;
|
||||
|
||||
#[derive(StructOpt, Debug)]
|
||||
#[structopt(about = "musichoard-edit: edit the MusicHoard database",
|
||||
|
@ -18,13 +18,13 @@ use crate::core::{
|
||||
/// The Music Hoard. It is responsible for pulling information from both the library and the
|
||||
/// database, ensuring its consistent and writing back any changes.
|
||||
#[derive(Debug)]
|
||||
pub struct MusicHoard<LIB, DB> {
|
||||
pub struct MusicHoard<Database, Library> {
|
||||
collection: Collection,
|
||||
pre_commit: Collection,
|
||||
library: LIB,
|
||||
database: DB,
|
||||
library_cache: HashMap<ArtistId, Artist>,
|
||||
database: Database,
|
||||
database_cache: Collection,
|
||||
library: Library,
|
||||
library_cache: HashMap<ArtistId, Artist>,
|
||||
}
|
||||
|
||||
/// Phantom type for when a library implementation is not needed.
|
||||
@ -35,28 +35,28 @@ pub struct NoLibrary;
|
||||
#[derive(Debug)]
|
||||
pub struct NoDatabase;
|
||||
|
||||
impl Default for MusicHoard<NoLibrary, NoDatabase> {
|
||||
impl Default for MusicHoard<NoDatabase, NoLibrary> {
|
||||
/// Create a new [`MusicHoard`] without any library or database.
|
||||
fn default() -> Self {
|
||||
MusicHoard::empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl MusicHoard<NoLibrary, NoDatabase> {
|
||||
impl MusicHoard<NoDatabase, NoLibrary> {
|
||||
/// Create a new [`MusicHoard`] without any library or database.
|
||||
pub fn empty() -> Self {
|
||||
MusicHoard {
|
||||
collection: vec![],
|
||||
pre_commit: vec![],
|
||||
library: NoLibrary,
|
||||
database: NoDatabase,
|
||||
library_cache: HashMap::new(),
|
||||
database_cache: vec![],
|
||||
library: NoLibrary,
|
||||
library_cache: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<LIB, DB> MusicHoard<LIB, DB> {
|
||||
impl<Database, Library> MusicHoard<Database, Library> {
|
||||
/// Retrieve the [`Collection`].
|
||||
pub fn get_collection(&self) -> &Collection {
|
||||
&self.collection
|
||||
@ -191,16 +191,16 @@ impl<LIB, DB> MusicHoard<LIB, DB> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<LIB: ILibrary> MusicHoard<LIB, NoDatabase> {
|
||||
impl<Library: ILibrary> MusicHoard<NoDatabase, Library> {
|
||||
/// Create a new [`MusicHoard`] with the provided [`ILibrary`] and no database.
|
||||
pub fn library(library: LIB) -> Self {
|
||||
pub fn library(library: Library) -> Self {
|
||||
MusicHoard {
|
||||
collection: vec![],
|
||||
pre_commit: vec![],
|
||||
library,
|
||||
database: NoDatabase,
|
||||
library_cache: HashMap::new(),
|
||||
database_cache: vec![],
|
||||
library,
|
||||
library_cache: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -211,7 +211,7 @@ impl<LIB: ILibrary> MusicHoard<LIB, NoDatabase> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<LIB: ILibrary, DB> MusicHoard<LIB, DB> {
|
||||
impl<Database, Library: ILibrary> MusicHoard<Database, Library> {
|
||||
fn rescan_library_inner(&mut self) -> Result<Collection, Error> {
|
||||
let items = self.library.list(&Query::new())?;
|
||||
self.library_cache = Self::items_to_artists(items)?;
|
||||
@ -221,30 +221,30 @@ impl<LIB: ILibrary, DB> MusicHoard<LIB, DB> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB: IDatabase> MusicHoard<NoLibrary, DB> {
|
||||
impl<Database: IDatabase> MusicHoard<Database, NoLibrary> {
|
||||
/// Create a new [`MusicHoard`] with the provided [`IDatabase`] and no library.
|
||||
pub fn database(database: DB) -> Result<Self, Error> {
|
||||
pub fn database(database: Database) -> Result<Self, Error> {
|
||||
let mut mh = MusicHoard {
|
||||
collection: vec![],
|
||||
pre_commit: vec![],
|
||||
library: NoLibrary,
|
||||
database,
|
||||
library_cache: HashMap::new(),
|
||||
database_cache: vec![],
|
||||
library: NoLibrary,
|
||||
library_cache: HashMap::new(),
|
||||
};
|
||||
mh.reload_database()?;
|
||||
Ok(mh)
|
||||
}
|
||||
}
|
||||
|
||||
impl<LIB> MusicHoard<LIB, NoDatabase> {
|
||||
impl<Library> MusicHoard<NoDatabase, Library> {
|
||||
fn commit(&mut self) -> Result<(), Error> {
|
||||
self.collection = self.pre_commit.clone();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<LIB, DB: IDatabase> MusicHoard<LIB, DB> {
|
||||
impl<Database: IDatabase, Library> MusicHoard<Database, Library> {
|
||||
/// Load the database and merge with the in-memory collection.
|
||||
pub fn reload_database(&mut self) -> Result<(), Error> {
|
||||
self.database_cache = self.database.load()?;
|
||||
@ -448,16 +448,16 @@ impl<LIB, DB: IDatabase> MusicHoard<LIB, DB> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<LIB: ILibrary, DB: IDatabase> MusicHoard<LIB, DB> {
|
||||
impl<Database: IDatabase, Library: ILibrary> MusicHoard<Database, Library> {
|
||||
/// Create a new [`MusicHoard`] with the provided [`ILibrary`] and [`IDatabase`].
|
||||
pub fn new(library: LIB, database: DB) -> Result<Self, Error> {
|
||||
pub fn new(database: Database, library: Library) -> Result<Self, Error> {
|
||||
let mut mh = MusicHoard {
|
||||
collection: vec![],
|
||||
pre_commit: vec![],
|
||||
library,
|
||||
database,
|
||||
library_cache: HashMap::new(),
|
||||
database_cache: vec![],
|
||||
library,
|
||||
library_cache: HashMap::new(),
|
||||
};
|
||||
mh.reload_database()?;
|
||||
Ok(mh)
|
||||
@ -542,7 +542,7 @@ mod tests {
|
||||
database.expect_load().times(1).returning(|| Ok(vec![]));
|
||||
database.expect_save().times(4).returning(|_| Ok(()));
|
||||
|
||||
type MH = MusicHoard<NoLibrary, MockIDatabase>;
|
||||
type MH = MusicHoard<MockIDatabase, NoLibrary>;
|
||||
let mut music_hoard: MH = MusicHoard::database(database).unwrap();
|
||||
|
||||
let artist_1_id = ArtistId::new("the artist");
|
||||
@ -935,7 +935,7 @@ mod tests {
|
||||
.times(1)
|
||||
.return_once(|_| Ok(()));
|
||||
|
||||
let mut music_hoard = MusicHoard::new(library, database).unwrap();
|
||||
let mut music_hoard = MusicHoard::new(database, library).unwrap();
|
||||
|
||||
music_hoard.rescan_library().unwrap();
|
||||
assert_eq!(music_hoard.get_collection(), &*LIBRARY_COLLECTION);
|
||||
@ -1083,7 +1083,7 @@ mod tests {
|
||||
.times(1)
|
||||
.return_once(|| Ok(FULL_COLLECTION.to_owned()));
|
||||
|
||||
let music_hoard = MusicHoard::new(library, database).unwrap();
|
||||
let music_hoard = MusicHoard::new(database, library).unwrap();
|
||||
|
||||
assert_eq!(music_hoard.get_collection(), &*FULL_COLLECTION);
|
||||
}
|
||||
|
@ -8,71 +8,77 @@ use crate::{
|
||||
|
||||
/// Builder for [`MusicHoard`]. Its purpose is to make it easier to set various combinations of
|
||||
/// library/database or their absence.
|
||||
pub struct MusicHoardBuilder<LIB, DB> {
|
||||
library: LIB,
|
||||
database: DB,
|
||||
pub struct MusicHoardBuilder<Database, Library> {
|
||||
database: Database,
|
||||
library: Library,
|
||||
}
|
||||
|
||||
impl Default for MusicHoardBuilder<NoLibrary, NoDatabase> {
|
||||
impl Default for MusicHoardBuilder<NoDatabase, NoLibrary> {
|
||||
/// Create a [`MusicHoardBuilder`].
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl MusicHoardBuilder<NoLibrary, NoDatabase> {
|
||||
impl MusicHoardBuilder<NoDatabase, NoLibrary> {
|
||||
/// Create a [`MusicHoardBuilder`].
|
||||
pub fn new() -> Self {
|
||||
MusicHoardBuilder {
|
||||
library: NoLibrary,
|
||||
database: NoDatabase,
|
||||
library: NoLibrary,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<LIB, DB> MusicHoardBuilder<LIB, DB> {
|
||||
impl<Database, Library> MusicHoardBuilder<Database, Library> {
|
||||
/// Set a library for [`MusicHoard`].
|
||||
pub fn set_library<NEWLIB: ILibrary>(self, library: NEWLIB) -> MusicHoardBuilder<NEWLIB, DB> {
|
||||
pub fn set_library<NewLibrary: ILibrary>(
|
||||
self,
|
||||
library: NewLibrary,
|
||||
) -> MusicHoardBuilder<Database, NewLibrary> {
|
||||
MusicHoardBuilder {
|
||||
library,
|
||||
database: self.database,
|
||||
library,
|
||||
}
|
||||
}
|
||||
|
||||
/// Set a database for [`MusicHoard`].
|
||||
pub fn set_database<NEWDB: IDatabase>(self, database: NEWDB) -> MusicHoardBuilder<LIB, NEWDB> {
|
||||
pub fn set_database<NewDatabase: IDatabase>(
|
||||
self,
|
||||
database: NewDatabase,
|
||||
) -> MusicHoardBuilder<NewDatabase, Library> {
|
||||
MusicHoardBuilder {
|
||||
library: self.library,
|
||||
database,
|
||||
library: self.library,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MusicHoardBuilder<NoLibrary, NoDatabase> {
|
||||
impl MusicHoardBuilder<NoDatabase, NoLibrary> {
|
||||
/// Build [`MusicHoard`] with the currently set library and database.
|
||||
pub fn build(self) -> MusicHoard<NoLibrary, NoDatabase> {
|
||||
pub fn build(self) -> MusicHoard<NoDatabase, NoLibrary> {
|
||||
MusicHoard::empty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<LIB: ILibrary> MusicHoardBuilder<LIB, NoDatabase> {
|
||||
impl<Library: ILibrary> MusicHoardBuilder<NoDatabase, Library> {
|
||||
/// Build [`MusicHoard`] with the currently set library and database.
|
||||
pub fn build(self) -> MusicHoard<LIB, NoDatabase> {
|
||||
pub fn build(self) -> MusicHoard<NoDatabase, Library> {
|
||||
MusicHoard::library(self.library)
|
||||
}
|
||||
}
|
||||
|
||||
impl<DB: IDatabase> MusicHoardBuilder<NoLibrary, DB> {
|
||||
impl<Database: IDatabase> MusicHoardBuilder<Database, NoLibrary> {
|
||||
/// Build [`MusicHoard`] with the currently set library and database.
|
||||
pub fn build(self) -> Result<MusicHoard<NoLibrary, DB>, Error> {
|
||||
pub fn build(self) -> Result<MusicHoard<Database, NoLibrary>, Error> {
|
||||
MusicHoard::database(self.database)
|
||||
}
|
||||
}
|
||||
|
||||
impl<LIB: ILibrary, DB: IDatabase> MusicHoardBuilder<LIB, DB> {
|
||||
impl<Database: IDatabase, Library: ILibrary> MusicHoardBuilder<Database, Library> {
|
||||
/// Build [`MusicHoard`] with the currently set library and database.
|
||||
pub fn build(self) -> Result<MusicHoard<LIB, DB>, Error> {
|
||||
MusicHoard::new(self.library, self.database)
|
||||
pub fn build(self) -> Result<MusicHoard<Database, Library>, Error> {
|
||||
MusicHoard::new(self.database, self.library)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ struct DbOpt {
|
||||
no_database: bool,
|
||||
}
|
||||
|
||||
fn with<LIB: ILibrary, DB: IDatabase>(builder: MusicHoardBuilder<LIB, DB>) {
|
||||
fn with<Database: IDatabase, Library: ILibrary>(builder: MusicHoardBuilder<Database, Library>) {
|
||||
let music_hoard = builder.build().expect("failed to initialise MusicHoard");
|
||||
|
||||
// Initialize the terminal user interface.
|
||||
@ -76,7 +76,10 @@ fn with<LIB: ILibrary, DB: IDatabase>(builder: MusicHoardBuilder<LIB, DB>) {
|
||||
Tui::run(terminal, app, ui, handler, listener).expect("failed to run tui");
|
||||
}
|
||||
|
||||
fn with_database<LIB: ILibrary>(db_opt: DbOpt, builder: MusicHoardBuilder<LIB, NoDatabase>) {
|
||||
fn with_database<Library: ILibrary>(
|
||||
db_opt: DbOpt,
|
||||
builder: MusicHoardBuilder<NoDatabase, Library>,
|
||||
) {
|
||||
if db_opt.no_database {
|
||||
with(builder.set_database(NullDatabase));
|
||||
} else {
|
||||
@ -103,7 +106,7 @@ fn with_database<LIB: ILibrary>(db_opt: DbOpt, builder: MusicHoardBuilder<LIB, N
|
||||
};
|
||||
}
|
||||
|
||||
fn with_library(lib_opt: LibOpt, db_opt: DbOpt, builder: MusicHoardBuilder<NoLibrary, NoDatabase>) {
|
||||
fn with_library(lib_opt: LibOpt, db_opt: DbOpt, builder: MusicHoardBuilder<NoDatabase, NoLibrary>) {
|
||||
if lib_opt.no_library {
|
||||
with_database(db_opt, builder.set_library(NullLibrary));
|
||||
} else if let Some(uri) = lib_opt.beets_ssh_uri {
|
||||
|
@ -14,9 +14,9 @@ pub trait IMusicHoard {
|
||||
}
|
||||
|
||||
// GRCOV_EXCL_START
|
||||
impl<LIB: ILibrary, DB: IDatabase> IMusicHoard for MusicHoard<LIB, DB> {
|
||||
impl<Database: IDatabase, Library: ILibrary> IMusicHoard for MusicHoard<Database, Library> {
|
||||
fn rescan_library(&mut self) -> Result<(), musichoard::Error> {
|
||||
MusicHoard::<LIB, DB>::rescan_library(self)
|
||||
MusicHoard::<Database, Library>::rescan_library(self)
|
||||
}
|
||||
|
||||
fn reload_database(&mut self) -> Result<(), musichoard::Error> {
|
||||
|
@ -29,7 +29,7 @@ fn merge_library_then_database() {
|
||||
let backend = JsonDatabaseFileBackend::new(&*database::json::DATABASE_TEST_FILE);
|
||||
let database = JsonDatabase::new(backend);
|
||||
|
||||
let mut music_hoard = MusicHoard::new(library, database).unwrap();
|
||||
let mut music_hoard = MusicHoard::new(database, library).unwrap();
|
||||
|
||||
music_hoard.rescan_library().unwrap();
|
||||
music_hoard.reload_database().unwrap();
|
||||
@ -52,7 +52,7 @@ fn merge_database_then_library() {
|
||||
let backend = JsonDatabaseFileBackend::new(&*database::json::DATABASE_TEST_FILE);
|
||||
let database = JsonDatabase::new(backend);
|
||||
|
||||
let mut music_hoard = MusicHoard::new(library, database).unwrap();
|
||||
let mut music_hoard = MusicHoard::new(database, library).unwrap();
|
||||
|
||||
music_hoard.reload_database().unwrap();
|
||||
music_hoard.rescan_library().unwrap();
|
||||
|
Loading…
Reference in New Issue
Block a user