filter: document misc

This commit is contained in:
2025-12-08 16:09:18 +09:00
parent 65017ad6b3
commit 39e6b237af

View File

@@ -1,3 +1,8 @@
//! [`Filter`]s for querying the database and playlists.
//!
//! The filter syntax uses a context-free grammar, and has its own
//! set of parsers and parsing errors.
use std::fmt;
use chrono::{DateTime, Utc};
@@ -9,6 +14,8 @@ use crate::{
types::{Priority, Tag},
};
/// Represents the case sensitivity of a string comparison,
/// used in multiple filter variants.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum CaseSensitivity {
CaseSensitive,
@@ -16,6 +23,7 @@ pub enum CaseSensitivity {
CommandDependent,
}
/// Represents a comparison operator for priority comparisons.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum ComparisonOperator {
Equal,
@@ -26,30 +34,88 @@ pub enum ComparisonOperator {
LessThanOrEqual,
}
/// Represents a filter expression for querying the music database.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Filter {
/// Logical NOT of a filter. e.g.
///
/// `(!(Artist == "The Beatles"))`
Not(Box<Filter>),
/// Logical AND of multiple filters. e.g.
///
/// `((Artist == "The Beatles") AND (Album == "Abbey Road") AND (Title == "Come Together"))`
And(Vec<Filter>),
// The bool indicates whether the comparison is negated (true for !=, false for ==)
/// Equality comparison on a tag. e.g.
///
/// `(Artist == "The Beatles")` or `(Album != "Greatest Hits")`
///
/// The bool indicates whether the comparison is negated (true for !=, false for ==)
EqTag(Tag, CaseSensitivity, bool),
/// Substring containment on a tag. e.g.
///
/// `(Title contains "Symphony")` or `(Album !contains "Live")`
///
/// The bool indicates whether the comparison is negated (true for !contains, false for contains)
Contains(Tag, CaseSensitivity, bool),
/// Prefix matching on a tag. e.g.
///
/// `(Title starts_with "Symphony")` or `(Album !starts_with "Live")`
////
/// The bool indicates whether the comparison is negated (true for !starts_with, false for starts_with)
StartsWith(Tag, CaseSensitivity, bool),
/// Perl-compatible regular expression matching on a tag. e.g.
///
/// `(Composer =~ "Beethoven.*")` or `(Genre !~ "Pop.*")`
///
/// The bool indicates whether the comparison is negated (true for !~, false for =~)
PerlRegex(Tag, bool),
/// Equality comparison on the URI. e.g.
///
/// `(uri == "Rock/Classics/track01.mp3")`
EqUri(String),
/// Base path filter. e.g.
///
/// `(base "Rock/Classics")`
Base(String),
/// Filter for files added since the given timestamp. e.g.
///
/// `(added-since '1622505600')` or `(added-since '2021-06-01T00:00:00Z')`
AddedSince(DateTime<Utc>),
/// Filter for files modified since the given timestamp. e.g.
///
/// `(modified-since '1622505600')` or `(modified-since '2021-06-01T00:00:00Z')`
ModifiedSince(DateTime<Utc>),
/// Equality comparison on audio format. e.g.
///
/// `(AudioFormat == '44100:16:2')`
AudioFormatEq {
sample_rate: u32,
bits: u8,
channels: u8,
},
/// Masked equality comparison on audio format. e.g.
///
/// `(AudioFormat =~ '44100:*:2')`
AudioFormatEqMask {
sample_rate: Option<u32>,
bits: Option<u8>,
channels: Option<u8>,
},
/// Priority comparison. e.g.
///
/// `(prio >= 42)` or `(prio != 10)`
PrioCmp(ComparisonOperator, Priority),
}
@@ -243,6 +309,8 @@ impl Filter {
// TODO: There is a significant amount of error handling to be improved and tested here.
// TODO: thiserror
#[derive(Debug, Clone, PartialEq)]
pub enum FilterParserError<'a> {
/// Could not parse the response due to a syntax error.