Use sets for queries

This commit is contained in:
Wojciech Kozlowski 2023-04-14 00:17:30 +02:00
parent 9192c4bdb4
commit dcf82e88ff
2 changed files with 46 additions and 34 deletions

View File

@ -296,8 +296,7 @@ mod tests {
#[test] #[test]
fn test_query() { fn test_query() {
assert_eq!( let mut query = Query::new()
Query::new()
.exclude(Field::AlbumTitle(String::from("some.album"))) .exclude(Field::AlbumTitle(String::from("some.album")))
.include(Field::TrackNumber(5)) .include(Field::TrackNumber(5))
.include(Field::TrackArtist(vec![ .include(Field::TrackArtist(vec![
@ -305,17 +304,20 @@ mod tests {
String::from("some.artist.2"), String::from("some.artist.2"),
])) ]))
.exclude(Field::All(String::from("some.all"))) .exclude(Field::All(String::from("some.all")))
.to_args(), .to_args();
query.sort();
assert_eq!(
query,
vec![ vec![
String::from("track:5"),
String::from("artist:some.artist.1; some.artist.2"),
String::from("^album:some.album"), String::from("^album:some.album"),
String::from("^some.all"), String::from("^some.all"),
String::from("artist:some.artist.1; some.artist.2"),
String::from("track:5"),
] ]
); );
assert_eq!( let mut query = Query::default()
Query::default()
.exclude(Field::AlbumArtist(String::from("some.albumartist"))) .exclude(Field::AlbumArtist(String::from("some.albumartist")))
.include(Field::AlbumYear(3030)) .include(Field::AlbumYear(3030))
.include(Field::TrackTitle(String::from("some.track"))) .include(Field::TrackTitle(String::from("some.track")))
@ -323,12 +325,16 @@ mod tests {
String::from("some.artist.1"), String::from("some.artist.1"),
String::from("some.artist.2"), String::from("some.artist.2"),
])) ]))
.to_args(), .to_args();
query.sort();
assert_eq!(
query,
vec![ vec![
String::from("year:3030"),
String::from("title:some.track"),
String::from("^albumartist:some.albumartist"), String::from("^albumartist:some.albumartist"),
String::from("^artist:some.artist.1; some.artist.2"), String::from("^artist:some.artist.1; some.artist.2"),
String::from("title:some.track"),
String::from("year:3030"),
] ]
); );
} }
@ -439,16 +445,20 @@ mod tests {
let arguments = vec![ let arguments = vec![
"ls".to_string(), "ls".to_string(),
LIST_FORMAT_ARG.to_string(), LIST_FORMAT_ARG.to_string(),
String::from("track:5"),
String::from("artist:some.artist"),
String::from("^album:some.album"), String::from("^album:some.album"),
String::from("artist:some.artist"),
String::from("track:5"),
]; ];
let result = Ok(vec![]); let result = Ok(vec![]);
let mut executor = MockBeetsLibraryExecutor::new(); let mut executor = MockBeetsLibraryExecutor::new();
executor executor
.expect_exec() .expect_exec()
.with(predicate::eq(arguments)) .with(predicate::function(move |x: &[String]| {
let mut y = x.to_owned();
y[2..].sort();
y == arguments
}))
.times(1) .times(1)
.return_once(|_| result); .return_once(|_| result);

View File

@ -1,6 +1,6 @@
//! Module for interacting with the music library. //! Module for interacting with the music library.
use std::{fmt, num::ParseIntError, str::Utf8Error}; use std::{collections::HashSet, fmt, num::ParseIntError, str::Utf8Error};
#[cfg(test)] #[cfg(test)]
use mockall::automock; use mockall::automock;
@ -10,7 +10,7 @@ use crate::Artist;
pub mod beets; pub mod beets;
/// Individual fields that can be queried on. /// Individual fields that can be queried on.
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, Hash, PartialEq, Eq)]
pub enum Field { pub enum Field {
AlbumArtist(String), AlbumArtist(String),
AlbumYear(u32), AlbumYear(u32),
@ -24,8 +24,8 @@ pub enum Field {
/// A library query. Can include or exclude particular fields. /// A library query. Can include or exclude particular fields.
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct Query { pub struct Query {
include: Vec<Field>, include: HashSet<Field>,
exclude: Vec<Field>, exclude: HashSet<Field>,
} }
impl Default for Query { impl Default for Query {
@ -39,20 +39,20 @@ impl Query {
/// Create an empty query. /// Create an empty query.
pub fn new() -> Self { pub fn new() -> Self {
Query { Query {
include: vec![], include: HashSet::new(),
exclude: vec![], exclude: HashSet::new(),
} }
} }
/// Refine the query to include a particular search term. /// Refine the query to include a particular search term.
pub fn include(&mut self, field: Field) -> &mut Self { pub fn include(&mut self, field: Field) -> &mut Self {
self.include.push(field); self.include.insert(field);
self self
} }
/// Refine the query to exclude a particular search term. /// Refine the query to exclude a particular search term.
pub fn exclude(&mut self, field: Field) -> &mut Self { pub fn exclude(&mut self, field: Field) -> &mut Self {
self.exclude.push(field); self.exclude.insert(field);
self self
} }
} }
@ -121,11 +121,13 @@ mod tests {
let mut rhs = Query::new(); let mut rhs = Query::new();
assert_eq!( assert_eq!(
lhs.include(Field::AlbumArtist(String::from("some.artist"))) lhs.include(Field::AlbumArtist(String::from("some.artist")))
.exclude(Field::TrackTitle(String::from("some.title")))
.exclude(Field::TrackTitle(String::from("some.title"))) .exclude(Field::TrackTitle(String::from("some.title")))
.include(Field::TrackNumber(6)), .include(Field::TrackNumber(6)),
rhs.exclude(Field::TrackTitle(String::from("some.title"))) rhs.exclude(Field::TrackTitle(String::from("some.title")))
.include(Field::TrackNumber(6))
.include(Field::AlbumArtist(String::from("some.artist"))) .include(Field::AlbumArtist(String::from("some.artist")))
.include(Field::TrackNumber(6)), .include(Field::AlbumArtist(String::from("some.artist"))),
) )
} }