From 45d8523b3d3a98ef554d72b6f9e47b0082bcebf7 Mon Sep 17 00:00:00 2001 From: figsoda Date: Sat, 31 Oct 2020 13:33:51 -0400 Subject: [PATCH] replace `IfNot` with `Not`, `And`, `Or` and `Xor` --- src/config.rs | 31 ++++--------------------------- src/layout.rs | 50 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 34 insertions(+), 47 deletions(-) diff --git a/src/config.rs b/src/config.rs index 1bbe92d..578df56 100644 --- a/src/config.rs +++ b/src/config.rs @@ -65,6 +65,10 @@ pub enum Condition { TitleExist, ArtistExist, AlbumExist, + Not(Box), + And(Box, Box), + Or(Box, Box), + Xor(Box, Box), } impl<'de> Deserialize<'de> for Texts { @@ -110,7 +114,6 @@ impl<'de> Deserialize<'de> for Texts { QueueAlbum, Parts, If, - IfNot, } struct IfVisitor; @@ -137,30 +140,6 @@ impl<'de> Deserialize<'de> for Texts { } } - struct IfNotVisitor; - impl<'de> Visitor<'de> for IfNotVisitor { - type Value = Texts; - - fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { - formatter.write_str("IfNot variant") - } - - fn visit_seq>( - self, - mut sa: A, - ) -> Result { - let cond = sa - .next_element()? - .ok_or_else(|| de::Error::invalid_length(0, &self))?; - let no = sa.next_element()?.map_or_else( - || Err(de::Error::invalid_length(1, &self)), - |x| Ok(Box::new(x)), - )?; - let yes = Box::new(sa.next_element()?.unwrap_or(Texts::Empty)); - Ok(Texts::If(cond, yes, no)) - } - } - let (variant, va) = ea.variant()?; macro_rules! unit_variant { @@ -185,7 +164,6 @@ impl<'de> Deserialize<'de> for Texts { Variant::QueueAlbum => unit_variant!(QueueAlbum), Variant::Parts => Ok(Texts::Parts(va.newtype_variant()?)), Variant::If => va.tuple_variant(3, IfVisitor), - Variant::IfNot => va.tuple_variant(3, IfNotVisitor), } } } @@ -207,7 +185,6 @@ impl<'de> Deserialize<'de> for Texts { "QueueAlbum", "Parts", "If", - "IfNot", ], TextsVisitor, ) diff --git a/src/layout.rs b/src/layout.rs index 76739d9..0adbdd4 100644 --- a/src/layout.rs +++ b/src/layout.rs @@ -244,26 +244,7 @@ fn flatten( } } Texts::If(cond, box yes, box no) => { - let xs = if match cond { - Condition::Playing => current_track.is_some(), - Condition::Repeat => status.repeat, - Condition::Random => status.random, - Condition::Single => status.single == Some(true), - Condition::Oneshot => status.single == None, - Condition::Consume => status.consume, - Condition::TitleExist => { - matches!(current_track, Some(Track { title: Some(_), .. })) - } - Condition::ArtistExist => matches!( - current_track, - Some(Track { - artist: Some(_), .. - }), - ), - Condition::AlbumExist => { - matches!(current_track, Some(Track { album: Some(_), .. })) - } - } { + let xs = if eval_cond(cond, status, current_track) { yes } else { no @@ -272,3 +253,32 @@ fn flatten( } } } + +fn eval_cond(cond: &Condition, status: &Status, current_track: Option<&Track>) -> bool { + match cond { + Condition::Playing => current_track.is_some(), + Condition::Repeat => status.repeat, + Condition::Random => status.random, + Condition::Single => status.single == Some(true), + Condition::Oneshot => status.single == None, + Condition::Consume => status.consume, + Condition::TitleExist => matches!(current_track, Some(Track { title: Some(_), .. })), + Condition::ArtistExist => matches!( + current_track, + Some(Track { + artist: Some(_), .. + }), + ), + Condition::AlbumExist => matches!(current_track, Some(Track { album: Some(_), .. })), + Condition::Not(box x) => !eval_cond(x, status, current_track), + Condition::And(box x, box y) => { + eval_cond(x, status, current_track) && eval_cond(y, status, current_track) + } + Condition::Or(box x, box y) => { + eval_cond(x, status, current_track) || eval_cond(y, status, current_track) + } + Condition::Xor(box x, box y) => { + eval_cond(x, status, current_track) ^ eval_cond(y, status, current_track) + } + } +}