Use AsRef and Into for better API calls #38
@ -1,7 +1,7 @@
|
|||||||
//! Module for storing MusicHoard data in a JSON file database.
|
//! Module for storing MusicHoard data in a JSON file database.
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@ -60,10 +60,8 @@ pub struct JsonDatabaseFileBackend {
|
|||||||
|
|
||||||
impl JsonDatabaseFileBackend {
|
impl JsonDatabaseFileBackend {
|
||||||
/// Create a [`JsonDatabaseFileBackend`] that will read/write to the provided path.
|
/// Create a [`JsonDatabaseFileBackend`] that will read/write to the provided path.
|
||||||
pub fn new(path: &Path) -> Self {
|
pub fn new<P: Into<PathBuf>>(path: P) -> Self {
|
||||||
JsonDatabaseFileBackend {
|
JsonDatabaseFileBackend { path: path.into() }
|
||||||
path: path.to_path_buf(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,7 +142,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn artists_to_json(artists: &Vec<Artist>) -> String {
|
fn artists_to_json(artists: &[Artist]) -> String {
|
||||||
let mut artists_strings: Vec<String> = vec![];
|
let mut artists_strings: Vec<String> = vec![];
|
||||||
for artist in artists.iter() {
|
for artist in artists.iter() {
|
||||||
artists_strings.push(artist_to_json(artist));
|
artists_strings.push(artist_to_json(artist));
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, HashSet},
|
collections::{HashMap, HashSet},
|
||||||
path::{Path, PathBuf},
|
ffi::OsString,
|
||||||
|
path::PathBuf,
|
||||||
process::Command,
|
process::Command,
|
||||||
str,
|
str,
|
||||||
};
|
};
|
||||||
@ -80,7 +81,7 @@ impl ToBeetsArgs for Query {
|
|||||||
#[cfg_attr(test, automock)]
|
#[cfg_attr(test, automock)]
|
||||||
pub trait BeetsLibraryExecutor {
|
pub trait BeetsLibraryExecutor {
|
||||||
/// Invoke beets with the provided arguments.
|
/// Invoke beets with the provided arguments.
|
||||||
fn exec(&mut self, arguments: &[String]) -> Result<Vec<String>, Error>;
|
fn exec<S: AsRef<str> + 'static>(&mut self, arguments: &[S]) -> Result<Vec<String>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Beets library.
|
/// Beets library.
|
||||||
@ -90,7 +91,7 @@ pub struct BeetsLibrary<BLE> {
|
|||||||
|
|
||||||
trait LibraryPrivate {
|
trait LibraryPrivate {
|
||||||
fn list_cmd_and_args(query: &Query) -> Vec<String>;
|
fn list_cmd_and_args(query: &Query) -> Vec<String>;
|
||||||
fn list_to_artists(list_output: Vec<String>) -> Result<Vec<Artist>, Error>;
|
fn list_to_artists<S: AsRef<str>>(list_output: &[S]) -> Result<Vec<Artist>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<BLE: BeetsLibraryExecutor> BeetsLibrary<BLE> {
|
impl<BLE: BeetsLibraryExecutor> BeetsLibrary<BLE> {
|
||||||
@ -104,7 +105,7 @@ impl<BLE: BeetsLibraryExecutor> Library for BeetsLibrary<BLE> {
|
|||||||
fn list(&mut self, query: &Query) -> Result<Vec<Artist>, Error> {
|
fn list(&mut self, query: &Query) -> Result<Vec<Artist>, Error> {
|
||||||
let cmd = Self::list_cmd_and_args(query);
|
let cmd = Self::list_cmd_and_args(query);
|
||||||
let output = self.executor.exec(&cmd)?;
|
let output = self.executor.exec(&cmd)?;
|
||||||
Self::list_to_artists(output)
|
Self::list_to_artists(&output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,11 +117,11 @@ impl<BLE: BeetsLibraryExecutor> LibraryPrivate for BeetsLibrary<BLE> {
|
|||||||
cmd
|
cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
fn list_to_artists(list_output: Vec<String>) -> Result<Vec<Artist>, Error> {
|
fn list_to_artists<S: AsRef<str>>(list_output: &[S]) -> Result<Vec<Artist>, Error> {
|
||||||
let mut artists: Vec<Artist> = vec![];
|
let mut artists: Vec<Artist> = vec![];
|
||||||
let mut album_ids = HashMap::<ArtistId, HashSet<AlbumId>>::new();
|
let mut album_ids = HashMap::<ArtistId, HashSet<AlbumId>>::new();
|
||||||
|
|
||||||
for line in list_output.iter() {
|
for line in list_output.iter().map(|s| s.as_ref()) {
|
||||||
if line.is_empty() {
|
if line.is_empty() {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -199,22 +200,22 @@ impl<BLE: BeetsLibraryExecutor> LibraryPrivate for BeetsLibrary<BLE> {
|
|||||||
|
|
||||||
/// Beets library executor that executes beets commands in their own process.
|
/// Beets library executor that executes beets commands in their own process.
|
||||||
pub struct BeetsLibraryCommandExecutor {
|
pub struct BeetsLibraryCommandExecutor {
|
||||||
bin: String,
|
bin: OsString,
|
||||||
config: Option<PathBuf>,
|
config: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BeetsLibraryCommandExecutor {
|
impl BeetsLibraryCommandExecutor {
|
||||||
/// Create a new [`BeetsLibraryCommandExecutor`] that uses the provided beets executable.
|
/// Create a new [`BeetsLibraryCommandExecutor`] that uses the provided beets executable.
|
||||||
pub fn new(bin: &str) -> Self {
|
pub fn new<S: Into<OsString>>(bin: S) -> Self {
|
||||||
BeetsLibraryCommandExecutor {
|
BeetsLibraryCommandExecutor {
|
||||||
bin: bin.to_string(),
|
bin: bin.into(),
|
||||||
config: None,
|
config: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update the configuration file passed to the beets executable.
|
/// Update the configuration file passed to the beets executable.
|
||||||
pub fn config(mut self, path: Option<&Path>) -> Self {
|
pub fn config<P: Into<PathBuf>>(mut self, path: Option<P>) -> Self {
|
||||||
self.config = path.map(|p| p.to_path_buf());
|
self.config = path.map(|p| p.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -227,13 +228,13 @@ impl Default for BeetsLibraryCommandExecutor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl BeetsLibraryExecutor for BeetsLibraryCommandExecutor {
|
impl BeetsLibraryExecutor for BeetsLibraryCommandExecutor {
|
||||||
fn exec(&mut self, arguments: &[String]) -> Result<Vec<String>, Error> {
|
fn exec<S: AsRef<str> + 'static>(&mut self, arguments: &[S]) -> Result<Vec<String>, Error> {
|
||||||
let mut cmd = Command::new(&self.bin);
|
let mut cmd = Command::new(&self.bin);
|
||||||
if let Some(ref path) = self.config {
|
if let Some(ref path) = self.config {
|
||||||
cmd.arg("--config");
|
cmd.arg("--config");
|
||||||
cmd.arg(path);
|
cmd.arg(path);
|
||||||
}
|
}
|
||||||
let output = cmd.args(arguments).output()?;
|
let output = cmd.args(arguments.iter().map(|s| s.as_ref())).output()?;
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
return Err(Error::CmdExec(
|
return Err(Error::CmdExec(
|
||||||
String::from_utf8_lossy(&output.stderr).to_string(),
|
String::from_utf8_lossy(&output.stderr).to_string(),
|
||||||
@ -281,7 +282,7 @@ mod tests {
|
|||||||
strings
|
strings
|
||||||
}
|
}
|
||||||
|
|
||||||
fn artists_to_beets_string(artists: &Vec<Artist>) -> Vec<String> {
|
fn artists_to_beets_string(artists: &[Artist]) -> Vec<String> {
|
||||||
let mut strings = vec![];
|
let mut strings = vec![];
|
||||||
for artist in artists.iter() {
|
for artist in artists.iter() {
|
||||||
strings.append(&mut artist_to_beets_string(artist));
|
strings.append(&mut artist_to_beets_string(artist));
|
||||||
|
@ -14,7 +14,7 @@ struct TrackSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TrackSelection {
|
impl TrackSelection {
|
||||||
fn initialise(tracks: &Vec<Track>) -> Option<TrackSelection> {
|
fn initialise(tracks: &[Track]) -> Option<TrackSelection> {
|
||||||
if !tracks.is_empty() {
|
if !tracks.is_empty() {
|
||||||
Some(TrackSelection { index: 0 })
|
Some(TrackSelection { index: 0 })
|
||||||
} else {
|
} else {
|
||||||
@ -43,7 +43,7 @@ struct AlbumSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AlbumSelection {
|
impl AlbumSelection {
|
||||||
fn initialise(albums: &Vec<Album>) -> Option<AlbumSelection> {
|
fn initialise(albums: &[Album]) -> Option<AlbumSelection> {
|
||||||
if !albums.is_empty() {
|
if !albums.is_empty() {
|
||||||
Some(AlbumSelection {
|
Some(AlbumSelection {
|
||||||
index: 0,
|
index: 0,
|
||||||
@ -77,7 +77,7 @@ struct ArtistSelection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ArtistSelection {
|
impl ArtistSelection {
|
||||||
fn initialise(artists: &Vec<Artist>) -> Option<ArtistSelection> {
|
fn initialise(artists: &[Artist]) -> Option<ArtistSelection> {
|
||||||
if !artists.is_empty() {
|
if !artists.is_empty() {
|
||||||
Some(ArtistSelection {
|
Some(ArtistSelection {
|
||||||
index: 0,
|
index: 0,
|
||||||
|
Loading…
Reference in New Issue
Block a user