Add collection manager
This commit is contained in:
parent
1c29c68321
commit
0ca084cacc
54
src/collection/mod.rs
Normal file
54
src/collection/mod.rs
Normal file
@ -0,0 +1,54 @@
|
||||
use crate::{database::{Database, self}, library::{Library, Query, self}, Artist};
|
||||
|
||||
/// The collection type.
|
||||
pub type Collection = Vec<Artist>;
|
||||
|
||||
/// Error type for collection manager.
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// The [`CollectionManager`] failed to read/write from/to the library.
|
||||
LibraryError(String),
|
||||
/// The [`CollectionManager`] failed to read/write from/to the database.
|
||||
DatabaseError(String),
|
||||
}
|
||||
|
||||
impl From<library::Error> for Error {
|
||||
fn from(err: library::Error) -> Error {
|
||||
Error::LibraryError(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<database::Error> for Error {
|
||||
fn from(err: database::Error) -> Error {
|
||||
Error::DatabaseError(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CollectionManager {
|
||||
library: Box<dyn Library + Send + Sync>,
|
||||
database: Box<dyn Database + Send + Sync>,
|
||||
collection: Collection,
|
||||
}
|
||||
|
||||
impl CollectionManager {
|
||||
pub fn new(
|
||||
library: Box<dyn Library + Send + Sync>,
|
||||
database: Box<dyn Database + Send + Sync>,
|
||||
) -> Self {
|
||||
CollectionManager {
|
||||
library,
|
||||
database,
|
||||
collection: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rescan_library(&mut self) -> Result<(), Error> {
|
||||
self.collection = self.library.list(&Query::default())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn save_to_database(&mut self) -> Result<(), Error> {
|
||||
self.database.write(&self.collection)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
@ -3,10 +3,15 @@
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
use crate::collection::Collection;
|
||||
|
||||
use super::{Database, DatabaseRead, DatabaseWrite};
|
||||
use super::{Database, DatabaseRead, DatabaseWrite, Error};
|
||||
|
||||
impl From<serde_json::Error> for Error {
|
||||
fn from(err: serde_json::Error) -> Error {
|
||||
Error::SerDeError(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for the JSON database backend.
|
||||
pub trait JsonDatabaseBackend {
|
||||
@ -19,21 +24,18 @@ pub trait JsonDatabaseBackend {
|
||||
|
||||
/// JSON database.
|
||||
pub struct JsonDatabase {
|
||||
backend: Box<dyn JsonDatabaseBackend + Send>,
|
||||
backend: Box<dyn JsonDatabaseBackend + Send + Sync>,
|
||||
}
|
||||
|
||||
impl JsonDatabase {
|
||||
/// Create a new JSON database with the provided backend, e.g. [JsonDatabaseFileBackend].
|
||||
pub fn new(backend: Box<dyn JsonDatabaseBackend + Send>) -> Self {
|
||||
pub fn new(backend: Box<dyn JsonDatabaseBackend + Send + Sync>) -> Self {
|
||||
JsonDatabase { backend }
|
||||
}
|
||||
}
|
||||
|
||||
impl DatabaseRead for JsonDatabase {
|
||||
fn read<D>(&self, collection: &mut D) -> Result<(), std::io::Error>
|
||||
where
|
||||
D: DeserializeOwned,
|
||||
{
|
||||
fn read(&self, collection: &mut Collection) -> Result<(), Error> {
|
||||
let serialized = self.backend.read()?;
|
||||
*collection = serde_json::from_str(&serialized)?;
|
||||
Ok(())
|
||||
@ -41,10 +43,7 @@ impl DatabaseRead for JsonDatabase {
|
||||
}
|
||||
|
||||
impl DatabaseWrite for JsonDatabase {
|
||||
fn write<S>(&mut self, collection: &S) -> Result<(), std::io::Error>
|
||||
where
|
||||
S: Serialize,
|
||||
{
|
||||
fn write(&mut self, collection: &Collection) -> Result<(), Error> {
|
||||
let serialized = serde_json::to_string(&collection)?;
|
||||
self.backend.write(&serialized)?;
|
||||
Ok(())
|
||||
|
@ -1,24 +1,47 @@
|
||||
//! Module for storing MusicHoard data in a database.
|
||||
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::Serialize;
|
||||
use std::fmt;
|
||||
|
||||
use crate::collection::Collection;
|
||||
|
||||
pub mod json;
|
||||
|
||||
/// Error type for database calls.
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
/// The database experienced an I/O error.
|
||||
IoError(String),
|
||||
/// The database experienced a (de)serialisation error.
|
||||
SerDeError(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Self::IoError(ref s) => write!(f, "the database experienced an I/O error: {s}"),
|
||||
Self::SerDeError(ref s) => {
|
||||
write!(f, "the database experienced a (de)serialisation error: {s}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(err: std::io::Error) -> Error {
|
||||
Error::IoError(err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for database reads.
|
||||
pub trait DatabaseRead {
|
||||
/// Read collection from the database.
|
||||
fn read<D>(&self, collection: &mut D) -> Result<(), std::io::Error>
|
||||
where
|
||||
D: DeserializeOwned;
|
||||
fn read(&self, collection: &mut Collection) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
/// Trait for database writes.
|
||||
pub trait DatabaseWrite {
|
||||
/// Write collection to the database.
|
||||
fn write<S>(&mut self, collection: &S) -> Result<(), std::io::Error>
|
||||
where
|
||||
S: Serialize;
|
||||
fn write(&mut self, collection: &Collection) -> Result<(), Error>;
|
||||
}
|
||||
|
||||
/// Trait for database reads and writes.
|
||||
|
@ -3,6 +3,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
pub mod collection;
|
||||
pub mod database;
|
||||
pub mod library;
|
||||
|
||||
|
@ -91,7 +91,7 @@ pub trait BeetsLibraryExecutor {
|
||||
|
||||
/// Beets library.
|
||||
pub struct BeetsLibrary {
|
||||
executor: Box<dyn BeetsLibraryExecutor + Send>,
|
||||
executor: Box<dyn BeetsLibraryExecutor + Send + Sync>,
|
||||
}
|
||||
|
||||
trait LibraryPrivate {
|
||||
@ -107,7 +107,7 @@ trait LibraryPrivate {
|
||||
|
||||
impl BeetsLibrary {
|
||||
/// Create a new beets library with the provided executor, e.g. [BeetsLibraryCommandExecutor].
|
||||
pub fn new(executor: Box<dyn BeetsLibraryExecutor + Send>) -> BeetsLibrary {
|
||||
pub fn new(executor: Box<dyn BeetsLibraryExecutor + Send + Sync>) -> BeetsLibrary {
|
||||
BeetsLibrary { executor }
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
//! Module for interacting with the music library.
|
||||
|
||||
use std::{num::ParseIntError, str::Utf8Error};
|
||||
use std::{num::ParseIntError, str::Utf8Error, fmt};
|
||||
|
||||
use crate::Artist;
|
||||
|
||||
@ -111,6 +111,18 @@ pub enum Error {
|
||||
Utf8Error(String),
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match *self {
|
||||
Self::CmdExecError(ref s) => write!(f, "the library failed to execute a command: {s}"),
|
||||
Self::InvalidData(ref s) => write!(f, "the library returned invalid data: {s}"),
|
||||
Self::IoError(ref s) => write!(f, "the library experienced an I/O error: {s}"),
|
||||
Self::ParseIntError(ref s) => write!(f, "the library returned an invalid integer: {s}"),
|
||||
Self::Utf8Error(ref s) => write!(f, "the library returned invalid UTF-8: {s}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for Error {
|
||||
fn from(err: std::io::Error) -> Error {
|
||||
Error::IoError(err.to_string())
|
||||
|
Loading…
Reference in New Issue
Block a user