pub fn cycled<T: Copy + PartialEq>(choices: &[T], current: T, delta: i8) -> T {
let position = choices
.iter()
.position(|choice| *choice == current)
.expect("the current choice is among the choices");
choices[(position as isize + isize::from(delta)).rem_euclid(choices.len() as isize) as usize]
}
macro_rules! cyclic {
(
$(#[$meta:meta])*
$vis:vis enum $name:ident {
$($(#[$variant_meta:meta])* $variant:ident $(= $discriminant:tt)?),+ $(,)?
}
) => {
$(#[$meta])*
$vis enum $name {
$($(#[$variant_meta])* $variant $(= $discriminant)?),+
}
impl $name {
$vis const CHOICES: &[Self] = &[$(Self::$variant),+];
$vis fn cycle(self, delta: i8) -> Self {
$crate::ui::cycle::cycled(Self::CHOICES, self, delta)
}
}
};
}
pub(crate) use cyclic;