pub trait CycleFilter: Clone + Copy + Default {
#[must_use]
fn next(&self) -> Self;
#[must_use]
fn prev(&self) -> Self;
fn display_name(&self) -> &str;
}
#[derive(Debug, Clone)]
pub struct FilterState<F: CycleFilter> {
pub current: F,
}
impl<F: CycleFilter> Default for FilterState<F> {
fn default() -> Self {
Self::new()
}
}
impl<F: CycleFilter> FilterState<F> {
#[must_use]
pub fn new() -> Self {
Self {
current: F::default(),
}
}
pub const fn with_filter(filter: F) -> Self {
Self { current: filter }
}
pub fn next(&mut self) {
self.current = self.current.next();
}
pub fn prev(&mut self) {
self.current = self.current.prev();
}
pub const fn set(&mut self, filter: F) {
self.current = filter;
}
pub fn reset(&mut self) {
self.current = F::default();
}
pub fn display_name(&self) -> &str {
self.current.display_name()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Clone, Copy, Default, Debug, PartialEq, Eq)]
enum TestFilter {
#[default]
All,
FilterA,
FilterB,
}
impl CycleFilter for TestFilter {
fn next(&self) -> Self {
match self {
Self::All => Self::FilterA,
Self::FilterA => Self::FilterB,
Self::FilterB => Self::All,
}
}
fn prev(&self) -> Self {
match self {
Self::All => Self::FilterB,
Self::FilterA => Self::All,
Self::FilterB => Self::FilterA,
}
}
fn display_name(&self) -> &str {
match self {
Self::All => "All Items",
Self::FilterA => "Filter A",
Self::FilterB => "Filter B",
}
}
}
#[test]
fn test_filter_state_cycling() {
let mut state = FilterState::<TestFilter>::new();
assert_eq!(state.current, TestFilter::All);
assert_eq!(state.display_name(), "All Items");
state.next();
assert_eq!(state.current, TestFilter::FilterA);
assert_eq!(state.display_name(), "Filter A");
state.next();
assert_eq!(state.current, TestFilter::FilterB);
state.next();
assert_eq!(state.current, TestFilter::All);
state.prev();
assert_eq!(state.current, TestFilter::FilterB);
}
#[test]
fn test_filter_state_set_reset() {
let mut state = FilterState::<TestFilter>::new();
state.set(TestFilter::FilterB);
assert_eq!(state.current, TestFilter::FilterB);
state.reset();
assert_eq!(state.current, TestFilter::All);
}
#[test]
fn test_filter_state_with_initial() {
let state = FilterState::with_filter(TestFilter::FilterA);
assert_eq!(state.current, TestFilter::FilterA);
}
}