Update docs

This commit is contained in:
Wojciech Kozlowski 2023-03-31 21:18:03 +09:00
parent b1058f5a0b
commit 9f0cffdd4d
4 changed files with 55 additions and 30 deletions

View File

@ -1,3 +1,5 @@
//! Module for storing MusicHoard data in a JSON file database.
use std::fs::File;
use std::io::{Read, Write};
use std::path::Path;

View File

@ -1,3 +1,5 @@
//! Module for storing MusicHoard data in a database.
use serde::de::DeserializeOwned;
use serde::Serialize;
@ -5,6 +7,7 @@ pub mod json;
/// Trait for database reads.
pub trait DatabaseRead {
/// Read collection from the database.
fn read<D>(&mut self, collection: &mut D) -> Result<(), std::io::Error>
where
D: DeserializeOwned;
@ -12,6 +15,7 @@ pub trait DatabaseRead {
/// 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;

View File

@ -1,3 +1,6 @@
//! Module for interacting with the music library via
//! [beets](https://beets.readthedocs.io/en/stable/).
use std::{collections::HashSet, fmt::Display, process::Command};
use crate::{Album, AlbumId, Track};
@ -23,7 +26,7 @@ impl<T: SimpleOption + Display> QueryOptionArgBeets for QueryOption<T> {
Self::Exclude(value) => ("^", value),
Self::None => return None,
};
Some(format!("{}{}:{}", negate, option_name, value))
Some(format!("{}{}{}", negate, option_name, value))
}
}
@ -34,7 +37,7 @@ impl QueryOptionArgBeets for QueryOption<Vec<String>> {
Self::Exclude(value) => ("^", value),
Self::None => return None,
};
Some(format!("{}{}:{}", negate, option_name, vec.join("; ")))
Some(format!("{}{}{}", negate, option_name, vec.join("; ")))
}
}
@ -42,38 +45,45 @@ impl QueryArgsBeets for Query {
fn to_args(&self) -> Vec<String> {
let mut arguments: Vec<String> = vec![];
if let Some(album_artist) = self.album_artist.to_arg("albumartist") {
if let Some(album_artist) = self.album_artist.to_arg("albumartist:") {
arguments.push(album_artist);
};
if let Some(album_year) = self.album_year.to_arg("year") {
if let Some(album_year) = self.album_year.to_arg("year:") {
arguments.push(album_year);
};
if let Some(album_title) = self.album_title.to_arg("album") {
if let Some(album_title) = self.album_title.to_arg("album:") {
arguments.push(album_title);
};
if let Some(track_number) = self.track_number.to_arg("track") {
if let Some(track_number) = self.track_number.to_arg("track:") {
arguments.push(track_number);
};
if let Some(track_title) = self.track_title.to_arg("title") {
if let Some(track_title) = self.track_title.to_arg("title:") {
arguments.push(track_title);
};
if let Some(track_artist) = self.track_artist.to_arg("artist") {
if let Some(track_artist) = self.track_artist.to_arg("artist:") {
arguments.push(track_artist);
};
if let Some(all) = self.all.to_arg("") {
arguments.push(all);
}
arguments
}
}
/// Trait for invoking beets commands.
pub trait BeetsExecutor {
/// Invoke beets with the provided arguments.
fn exec(&mut self, arguments: Vec<String>) -> Result<Vec<String>, Error>;
}
/// Struct for interacting with the music library via beets.
pub struct Beets {
executor: Box<dyn BeetsExecutor>,
}
@ -179,6 +189,7 @@ impl LibraryPrivate for Beets {
}
}
/// Executor for executing beets commands on the local system.
pub struct SystemExecutor {
bin: String,
}
@ -295,19 +306,21 @@ mod tests {
#[test]
fn test_query() {
let query = Query::new()
.album_title(QueryOption::exclude(String::from("some.album")))
.track_number(QueryOption::include(5))
.track_artist(QueryOption::include(vec![
.album_title(QueryOption::Exclude(String::from("some.album")))
.track_number(QueryOption::Include(5))
.track_artist(QueryOption::Include(vec![
String::from("some.artist.1"),
String::from("some.artist.2"),
]));
]))
.all(QueryOption::Exclude(String::from("some.all")));
assert_eq!(
query.to_args(),
vec![
String::from("^album:some.album"),
String::from("track:5"),
String::from("artist:some.artist.1; some.artist.2")
String::from("artist:some.artist.1; some.artist.2"),
String::from("^some.all"),
]
);
}
@ -396,9 +409,9 @@ mod tests {
#[test]
fn test_list_query() {
let query = Query::new()
.album_title(QueryOption::exclude(String::from("some.album")))
.track_number(QueryOption::include(5))
.track_artist(QueryOption::include(vec![String::from("some.artist")]));
.album_title(QueryOption::Exclude(String::from("some.album")))
.track_number(QueryOption::Include(5))
.track_artist(QueryOption::Include(vec![String::from("some.artist")]));
let executor = TestExecutor {
arguments: Some(vec![

View File

@ -1,3 +1,5 @@
//! Module for interacting with the music library.
use std::{num::ParseIntError, str::Utf8Error};
use crate::Album;
@ -15,23 +17,12 @@ pub enum QueryOption<T> {
}
impl<T> QueryOption<T> {
/// Create an inclusive query option.
pub fn include(value: T) -> Self {
QueryOption::Include(value)
}
pub fn exclude(value: T) -> Self {
QueryOption::Exclude(value)
}
pub fn none() -> Self {
QueryOption::None
}
/// Return `true` if [QueryOption] is not [QueryOption::None].
pub fn is_some(&self) -> bool {
!matches!(self, QueryOption::None)
}
/// Return `true` if [QueryOption] is [QueryOption::None].
pub fn is_none(&self) -> bool {
matches!(self, QueryOption::None)
}
@ -39,7 +30,7 @@ impl<T> QueryOption<T> {
impl<T> Default for QueryOption<T> {
fn default() -> Self {
Self::none()
Self::None
}
}
@ -52,42 +43,56 @@ pub struct Query {
track_number: QueryOption<u32>,
track_title: QueryOption<String>,
track_artist: QueryOption<Vec<String>>,
all: QueryOption<String>,
}
impl Query {
/// Create an empty query.
pub fn new() -> Self {
Query::default()
}
/// Refine the query to a specific album artist.
pub fn album_artist(mut self, album_artist: QueryOption<String>) -> Self {
self.album_artist = album_artist;
self
}
/// Refine the query to a specific album year.
pub fn album_year(mut self, album_year: QueryOption<u32>) -> Self {
self.album_year = album_year;
self
}
/// Refine the query to a specific album title.
pub fn album_title(mut self, album_title: QueryOption<String>) -> Self {
self.album_title = album_title;
self
}
/// Refine the query to a specific track number.
pub fn track_number(mut self, track_number: QueryOption<u32>) -> Self {
self.track_number = track_number;
self
}
/// Refine the query to a specific track title.
pub fn track_title(mut self, track_title: QueryOption<String>) -> Self {
self.track_title = track_title;
self
}
/// Refine the query to a specific set of track artists.
pub fn track_artist(mut self, track_artist: QueryOption<Vec<String>>) -> Self {
self.track_artist = track_artist;
self
}
/// Refine the query for all fields.
pub fn all(mut self, all: QueryOption<String>) -> Self {
self.all = all;
self
}
}
/// Error type for library calls.
@ -123,5 +128,6 @@ impl From<Utf8Error> for Error {
/// Trait for interacting with the music library.
pub trait Library {
/// List lirbary items that match the a specific query.
fn list(&mut self, query: &Query) -> Result<Vec<Album>, Error>;
}