diff --git a/src/database/json/mod.rs b/src/database/json/mod.rs index 0398292..475d7e5 100644 --- a/src/database/json/mod.rs +++ b/src/database/json/mod.rs @@ -6,7 +6,7 @@ use serde::Serialize; #[cfg(test)] use mockall::automock; -use super::{Database, Error}; +use super::{Error, IDatabase}; pub mod backend; @@ -39,7 +39,7 @@ impl JsonDatabase { } } -impl Database for JsonDatabase { +impl IDatabase for JsonDatabase { fn read(&self, collection: &mut D) -> Result<(), Error> { let serialized = self.backend.read()?; *collection = serde_json::from_str(&serialized)?; diff --git a/src/database/mod.rs b/src/database/mod.rs index 8434b7b..91bc687 100644 --- a/src/database/mod.rs +++ b/src/database/mod.rs @@ -10,6 +10,16 @@ use mockall::automock; #[cfg(feature = "database-json")] pub mod json; +/// Trait for interacting with the database. +#[cfg_attr(test, automock)] +pub trait IDatabase { + /// Read collection from the database. + fn read(&self, collection: &mut D) -> Result<(), Error>; + + /// Write collection to the database. + fn write(&mut self, collection: &S) -> Result<(), Error>; +} + /// Error type for database calls. #[derive(Debug)] pub enum Error { @@ -36,16 +46,6 @@ impl From for Error { } } -/// Trait for interacting with the database. -#[cfg_attr(test, automock)] -pub trait Database { - /// Read collection from the database. - fn read(&self, collection: &mut D) -> Result<(), Error>; - - /// Write collection to the database. - fn write(&mut self, collection: &S) -> Result<(), Error>; -} - #[cfg(test)] mod tests { use std::io; diff --git a/src/lib.rs b/src/lib.rs index 586f3b4..e01004a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,8 +5,8 @@ pub mod library; use std::fmt; -use database::Database; -use library::{Library, Query}; +use database::IDatabase; +use library::{ILibrary, Query}; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -99,7 +99,7 @@ pub struct MusicHoard { collection: Collection, } -impl MusicHoard { +impl MusicHoard { /// Create a new [`MusicHoard`] with the provided [`Library`] and [`Database`]. pub fn new(library: LIB, database: DB) -> Self { MusicHoard { @@ -133,7 +133,7 @@ mod tests { use mockall::predicate; use once_cell::sync::Lazy; - use crate::{database::MockDatabase, library::MockLibrary}; + use crate::{database::MockIDatabase, library::MockILibrary}; use super::*; @@ -141,8 +141,8 @@ mod tests { #[test] fn read_get_write() { - let mut library = MockLibrary::new(); - let mut database = MockDatabase::new(); + let mut library = MockILibrary::new(); + let mut database = MockIDatabase::new(); let library_input = Query::new(); let library_result = Ok(COLLECTION.to_owned()); @@ -171,8 +171,8 @@ mod tests { #[test] fn library_error() { - let mut library = MockLibrary::new(); - let database = MockDatabase::new(); + let mut library = MockILibrary::new(); + let database = MockIDatabase::new(); let library_result = Err(library::Error::Invalid(String::from("invalid data"))); @@ -193,8 +193,8 @@ mod tests { #[test] fn database_error() { - let library = MockLibrary::new(); - let mut database = MockDatabase::new(); + let library = MockILibrary::new(); + let mut database = MockIDatabase::new(); let database_result = Err(database::Error::IoError(String::from("I/O error"))); diff --git a/src/library/beets/mod.rs b/src/library/beets/mod.rs index d066ea0..9a15fec 100644 --- a/src/library/beets/mod.rs +++ b/src/library/beets/mod.rs @@ -11,7 +11,7 @@ use mockall::automock; use crate::{Album, AlbumId, Artist, ArtistId, Track, TrackFormat}; -use super::{Error, Field, Library, Query}; +use super::{Error, Field, ILibrary, Query}; pub mod executor; @@ -101,7 +101,7 @@ impl BeetsLibrary { } } -impl Library for BeetsLibrary { +impl ILibrary for BeetsLibrary { fn list(&mut self, query: &Query) -> Result, Error> { let cmd = Self::list_cmd_and_args(query); let output = self.executor.exec(&cmd)?; diff --git a/src/library/mod.rs b/src/library/mod.rs index e73eb14..506e54e 100644 --- a/src/library/mod.rs +++ b/src/library/mod.rs @@ -10,6 +10,13 @@ use crate::Artist; #[cfg(feature = "library-beets")] pub mod beets; +/// Trait for interacting with the music library. +#[cfg_attr(test, automock)] +pub trait ILibrary { + /// List lirbary items that match the a specific query. + fn list(&mut self, query: &Query) -> Result, Error>; +} + /// Individual fields that can be queried on. #[derive(Debug, Hash, PartialEq, Eq)] pub enum Field { @@ -103,13 +110,6 @@ impl From for Error { } } -/// Trait for interacting with the music library. -#[cfg_attr(test, automock)] -pub trait Library { - /// List lirbary items that match the a specific query. - fn list(&mut self, query: &Query) -> Result, Error>; -} - #[cfg(test)] mod tests { use std::io; diff --git a/src/main.rs b/src/main.rs index ff4dd14..84c3078 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,21 +7,21 @@ use structopt::StructOpt; use musichoard::{ database::{ json::{backend::JsonDatabaseFileBackend, JsonDatabase}, - Database, + IDatabase, }, library::{ beets::{ executor::{ssh::BeetsLibrarySshExecutor, BeetsLibraryProcessExecutor}, BeetsLibrary, }, - Library, + ILibrary, }, MusicHoard, }; mod tui; -use tui::ui::MhUi; -use tui::{event::EventChannel, handler::TuiEventHandler, listener::TuiEventListener, Tui}; +use tui::ui::Ui; +use tui::{event::EventChannel, handler::TuiEventHandler, listener::EventListener, Tui}; #[derive(StructOpt)] struct Opt { @@ -39,7 +39,7 @@ struct Opt { database_file_path: PathBuf, } -fn with(lib: LIB, db: DB) { +fn with(lib: LIB, db: DB) { let music_hoard = MusicHoard::new(lib, db); // Initialize the terminal user interface. @@ -47,10 +47,10 @@ fn with(lib: LIB, db: DB) { let terminal = Terminal::new(backend).expect("failed to initialise terminal"); let channel = EventChannel::new(); - let listener = TuiEventListener::new(channel.sender()); + let listener = EventListener::new(channel.sender()); let handler = TuiEventHandler::new(channel.receiver()); - let ui = MhUi::new(music_hoard).expect("failed to initialise ui"); + let ui = Ui::new(music_hoard).expect("failed to initialise ui"); // Run the TUI application. Tui::run(terminal, ui, handler, listener).expect("failed to run tui"); diff --git a/src/tui/handler.rs b/src/tui/handler.rs index b9346f6..006ae34 100644 --- a/src/tui/handler.rs +++ b/src/tui/handler.rs @@ -5,7 +5,7 @@ use mockall::automock; use super::{ event::{Event, EventError, EventReceiver}, - ui::Ui, + ui::IUi, }; #[cfg_attr(test, automock)] @@ -28,7 +28,7 @@ impl TuiEventHandler { } } -impl EventHandler for TuiEventHandler { +impl EventHandler for TuiEventHandler { fn handle_next_event(&self, ui: &mut UI) -> Result<(), EventError> { match self.events.recv()? { Event::Key(key_event) => Self::handle_key_event(ui, key_event), @@ -39,7 +39,7 @@ impl EventHandler for TuiEventHandler { } } -impl EventHandlerPrivate for TuiEventHandler { +impl EventHandlerPrivate for TuiEventHandler { fn handle_key_event(ui: &mut UI, key_event: KeyEvent) { match key_event.code { // Exit application on `ESC` or `q`. diff --git a/src/tui/lib.rs b/src/tui/lib.rs index b503cbb..89a6242 100644 --- a/src/tui/lib.rs +++ b/src/tui/lib.rs @@ -1,4 +1,4 @@ -use musichoard::{MusicHoard, library::Library, database::Database, Collection}; +use musichoard::{database::IDatabase, library::ILibrary, Collection, MusicHoard}; #[cfg(test)] use mockall::automock; @@ -18,7 +18,7 @@ impl From for Error { } // GRCOV_EXCL_START -impl IMusicHoard for MusicHoard { +impl IMusicHoard for MusicHoard { fn rescan_library(&mut self) -> Result<(), Error> { Ok(MusicHoard::rescan_library(self)?) } diff --git a/src/tui/listener.rs b/src/tui/listener.rs index 53c78da..404c03e 100644 --- a/src/tui/listener.rs +++ b/src/tui/listener.rs @@ -7,22 +7,22 @@ use mockall::automock; use super::event::{Event, EventError, EventSender}; #[cfg_attr(test, automock)] -pub trait EventListener { +pub trait IEventListener { fn spawn(self) -> thread::JoinHandle; } -pub struct TuiEventListener { +pub struct EventListener { events: EventSender, } // GRCOV_EXCL_START -impl TuiEventListener { +impl EventListener { pub fn new(events: EventSender) -> Self { - TuiEventListener { events } + EventListener { events } } } -impl EventListener for TuiEventListener { +impl IEventListener for EventListener { fn spawn(self) -> thread::JoinHandle { thread::spawn(move || { loop { diff --git a/src/tui/mod.rs b/src/tui/mod.rs index 014d380..e3ab46a 100644 --- a/src/tui/mod.rs +++ b/src/tui/mod.rs @@ -14,8 +14,8 @@ use std::marker::PhantomData; use self::event::EventError; use self::handler::EventHandler; -use self::listener::EventListener; -use self::ui::Ui; +use self::listener::IEventListener; +use self::ui::IUi; #[derive(Debug, PartialEq, Eq)] pub enum Error { @@ -42,7 +42,7 @@ pub struct Tui { _phantom: PhantomData, } -impl Tui { +impl Tui { fn init(&mut self) -> Result<(), Error> { self.terminal.hide_cursor()?; self.terminal.clear()?; @@ -72,7 +72,7 @@ impl Tui { term: Terminal, ui: UI, handler: impl EventHandler, - listener: impl EventListener, + listener: impl IEventListener, ) -> Result<(), Error> { let mut tui = Tui { terminal: term, @@ -131,7 +131,7 @@ impl Tui { term: Terminal, ui: UI, handler: impl EventHandler, - listener: impl EventListener, + listener: impl IEventListener, ) -> Result<(), Error> { Self::enable()?; let result = Self::main(term, ui, handler, listener); @@ -164,8 +164,8 @@ mod tests { event::EventError, handler::MockEventHandler, lib::MockIMusicHoard, - listener::MockEventListener, - ui::{MhUi, Ui}, + listener::MockIEventListener, + ui::{IUi, Ui}, Error, Tui, }; @@ -174,17 +174,17 @@ mod tests { Terminal::new(backend).unwrap() } - pub fn ui(collection: Collection) -> MhUi { + pub fn ui(collection: Collection) -> Ui { let mut music_hoard = MockIMusicHoard::new(); music_hoard.expect_rescan_library().returning(|| Ok(())); music_hoard.expect_get_collection().return_const(collection); - MhUi::new(music_hoard).unwrap() + Ui::new(music_hoard).unwrap() } - fn listener() -> MockEventListener { - let mut listener = MockEventListener::new(); + fn listener() -> MockIEventListener { + let mut listener = MockIEventListener::new(); listener.expect_spawn().return_once(|| { thread::spawn(|| { thread::park(); @@ -194,11 +194,11 @@ mod tests { listener } - fn handler() -> MockEventHandler> { + fn handler() -> MockEventHandler> { let mut handler = MockEventHandler::new(); handler .expect_handle_next_event() - .return_once(|ui: &mut MhUi| { + .return_once(|ui: &mut Ui| { ui.quit(); Ok(()) }); @@ -246,7 +246,7 @@ mod tests { let listener_handle: thread::JoinHandle = thread::spawn(|| error); while !listener_handle.is_finished() {} - let mut listener = MockEventListener::new(); + let mut listener = MockIEventListener::new(); listener.expect_spawn().return_once(|| listener_handle); let mut handler = MockEventHandler::new(); @@ -269,7 +269,7 @@ mod tests { let listener_handle: thread::JoinHandle = thread::spawn(|| panic!()); while !listener_handle.is_finished() {} - let mut listener = MockEventListener::new(); + let mut listener = MockIEventListener::new(); listener.expect_spawn().return_once(|| listener_handle); let mut handler = MockEventHandler::new(); diff --git a/src/tui/ui.rs b/src/tui/ui.rs index e51b12e..1fdc1cf 100644 --- a/src/tui/ui.rs +++ b/src/tui/ui.rs @@ -9,6 +9,19 @@ use ratatui::{ use super::{lib::IMusicHoard, Error}; +pub trait IUi { + fn is_running(&self) -> bool; + fn quit(&mut self); + + fn increment_category(&mut self); + fn decrement_category(&mut self); + + fn increment_selection(&mut self); + fn decrement_selection(&mut self); + + fn render(&mut self, frame: &mut Frame<'_, B>); +} + struct TrackSelection { state: ListState, } @@ -236,7 +249,7 @@ impl Selection { } } -pub struct MhUi { +pub struct Ui { music_hoard: MH, selection: Selection, running: bool, @@ -425,11 +438,11 @@ impl<'a, 'b> TrackState<'a, 'b> { } } -impl MhUi { +impl Ui { pub fn new(mut music_hoard: MH) -> Result { music_hoard.rescan_library()?; let selection = Selection::new(Some(music_hoard.get_collection())); - Ok(MhUi { + Ok(Ui { music_hoard, selection, running: true, @@ -509,20 +522,7 @@ impl MhUi { } } -pub trait Ui { - fn is_running(&self) -> bool; - fn quit(&mut self); - - fn increment_category(&mut self); - fn decrement_category(&mut self); - - fn increment_selection(&mut self); - fn decrement_selection(&mut self); - - fn render(&mut self, frame: &mut Frame<'_, B>); -} - -impl Ui for MhUi { +impl IUi for Ui { fn is_running(&self) -> bool { self.running } @@ -767,7 +767,7 @@ mod tests { .expect_get_collection() .return_const(COLLECTION.to_owned()); - let mut ui = MhUi::new(music_hoard).unwrap(); + let mut ui = Ui::new(music_hoard).unwrap(); assert!(ui.is_running()); ui.quit(); @@ -786,7 +786,7 @@ mod tests { .expect_get_collection() .return_const(COLLECTION.to_owned()); - let mut ui = MhUi::new(music_hoard).unwrap(); + let mut ui = Ui::new(music_hoard).unwrap(); assert!(ui.is_running()); assert_eq!(ui.selection.active, Category::Artist); @@ -885,7 +885,7 @@ mod tests { .return_once(|| Ok(())); music_hoard.expect_get_collection().return_const(collection); - let mut app = MhUi::new(music_hoard).unwrap(); + let mut app = Ui::new(music_hoard).unwrap(); assert!(app.is_running()); assert_eq!(app.selection.active, Category::Artist); @@ -921,7 +921,7 @@ mod tests { .return_once(|| Ok(())); music_hoard.expect_get_collection().return_const(collection); - let mut app = MhUi::new(music_hoard).unwrap(); + let mut app = Ui::new(music_hoard).unwrap(); assert!(app.is_running()); assert_eq!(app.selection.active, Category::Artist); @@ -969,7 +969,7 @@ mod tests { .return_once(|| Ok(())); music_hoard.expect_get_collection().return_const(collection); - let mut app = MhUi::new(music_hoard).unwrap(); + let mut app = Ui::new(music_hoard).unwrap(); assert!(app.is_running()); assert_eq!(app.selection.active, Category::Artist); diff --git a/tests/database/json.rs b/tests/database/json.rs index 55ea7a6..07fbdf6 100644 --- a/tests/database/json.rs +++ b/tests/database/json.rs @@ -3,7 +3,7 @@ use std::{fs, path::PathBuf}; use musichoard::{ database::{ json::{backend::JsonDatabaseFileBackend, JsonDatabase}, - Database, + IDatabase, }, Artist, }; diff --git a/tests/library/beets.rs b/tests/library/beets.rs index 3d9215c..eb8f5f6 100644 --- a/tests/library/beets.rs +++ b/tests/library/beets.rs @@ -9,7 +9,7 @@ use once_cell::sync::Lazy; use musichoard::{ library::{ beets::{executor::BeetsLibraryProcessExecutor, BeetsLibrary}, - Field, Library, Query, + Field, ILibrary, Query, }, Artist, };