Break down the musichoard files #165

Merged
wojtek merged 9 commits from 164---break-down-the-musichoard-files into main 2024-03-09 22:52:04 +01:00
6 changed files with 64 additions and 55 deletions
Showing only changes of commit f95afd5f9a - Show all commits

View File

@ -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",

View File

@ -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);
}

View File

@ -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)
}
}

View File

@ -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 {

View File

@ -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> {

View File

@ -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();