diff --git a/src/filter.rs b/src/filter.rs index d75a152..5502ab7 100644 --- a/src/filter.rs +++ b/src/filter.rs @@ -1,4 +1,4 @@ -use std::str::SplitWhitespace; +use std::{fmt, str::SplitWhitespace}; use serde::{Deserialize, Serialize}; @@ -51,6 +51,102 @@ pub enum Filter { PrioCmp(ComparisonOperator, Priority), } +impl fmt::Display for Filter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Filter::Not(inner) => write!(f, "(NOT ({}))", inner), + Filter::And(left, right) => write!(f, "({} AND {})", left, right), + Filter::EqTag(tag, case_sensitivity, negated) => { + let op = if *negated { "!=" } else { "==" }; + let cs = match case_sensitivity { + CaseSensitivity::CaseSensitive => "_cs", + CaseSensitivity::CaseInsensitive => "_ci", + CaseSensitivity::CommandDependent => "", + }; + write!(f, "({} {}{} '{}')", tag.key(), op, cs, tag.value()) + } + Filter::Contains(tag, case_sensitivity, negated) => { + let op = if *negated { "!contains" } else { "contains" }; + let cs = match case_sensitivity { + CaseSensitivity::CaseSensitive => "_cs", + CaseSensitivity::CaseInsensitive => "_ci", + CaseSensitivity::CommandDependent => "", + }; + write!(f, "({} {}{} '{}')", tag.key(), op, cs, tag.value()) + } + Filter::StartsWith(tag, case_sensitivity, negated) => { + let op = if *negated { + "!starts_with" + } else { + "starts_with" + }; + let cs = match case_sensitivity { + CaseSensitivity::CaseSensitive => "_cs", + CaseSensitivity::CaseInsensitive => "_ci", + CaseSensitivity::CommandDependent => "", + }; + write!(f, "({} {}{} '{}')", tag.key(), op, cs, tag.value()) + } + Filter::PerlRegex(tag) => { + write!(f, "({} =~ '{}')", tag.key(), tag.value()) + } + Filter::NegPerlRegex(tag) => { + write!(f, "({} !~ '{}')", tag.key(), tag.value()) + } + Filter::EqUri(uri) => { + write!(f, "(uri == '{}')", uri) + } + Filter::Base(path) => { + write!(f, "(base '{}')", path) + } + Filter::ModifiedSince(timestamp) => { + write!(f, "(modified-since '{}')", timestamp) + } + Filter::AudioFormatEq { + sample_rate, + bits, + channels, + } => { + write!( + f, + "(AudioFormat == '{}:{}:{}')", + sample_rate, bits, channels + ) + } + Filter::AudioFormatEqMask { + sample_rate, + bits, + channels, + } => { + let sr_str = match sample_rate { + Some(sr) => sr.to_string(), + None => "*".to_string(), + }; + let bits_str = match bits { + Some(b) => b.to_string(), + None => "*".to_string(), + }; + let ch_str = match channels { + Some(c) => c.to_string(), + None => "*".to_string(), + }; + write!(f, "(AudioFormat =~ '{}:{}:{}')", sr_str, bits_str, ch_str) + } + Filter::PrioCmp(op, prio) => { + let op_str = match op { + ComparisonOperator::Equal => "==", + ComparisonOperator::NotEqual => "!=", + ComparisonOperator::GreaterThan => ">", + ComparisonOperator::GreaterThanOrEqual => ">=", + ComparisonOperator::LessThan => "<", + ComparisonOperator::LessThanOrEqual => "<=", + }; + write!(f, "(prio {} {})", op_str, prio) + } + } + } +} + pub fn parse_filter(parts: &mut SplitWhitespace<'_>) -> Result { // TODO: count parentheses and extract the full filter string unimplemented!()