pub(crate) trait UnwindLevel {
fn unwind(&mut self) -> bool;
}
pub(crate) fn unwind_one(levels: &mut [&mut dyn UnwindLevel]) -> bool {
levels.iter_mut().any(|level| level.unwind())
}
#[cfg(test)]
mod tests {
use super::*;
struct StubLevel {
has_something_live: bool,
was_asked_to_unwind: bool,
}
impl StubLevel {
fn armed() -> Self {
Self {
has_something_live: true,
was_asked_to_unwind: false,
}
}
fn empty() -> Self {
Self {
has_something_live: false,
was_asked_to_unwind: false,
}
}
}
impl UnwindLevel for StubLevel {
fn unwind(&mut self) -> bool {
self.was_asked_to_unwind = true;
if self.has_something_live {
self.has_something_live = false;
true
} else {
false
}
}
}
#[test]
fn unwind_one_with_nothing_live_at_any_level_is_inert() {
let mut a = StubLevel::empty();
let mut b = StubLevel::empty();
let unwound = unwind_one(&mut [&mut a, &mut b]);
assert!(!unwound);
}
#[test]
fn unwind_one_cancels_only_the_innermost_live_level_and_stops_there() {
let mut innermost = StubLevel::armed();
let mut outer = StubLevel::armed();
let unwound = unwind_one(&mut [&mut innermost, &mut outer]);
assert!(unwound);
assert!(
!innermost.has_something_live,
"the innermost level must have been the one cancelled"
);
assert!(
outer.has_something_live,
"a single press must not also unwind the next level in the same call"
);
assert!(
!outer.was_asked_to_unwind,
"the outer level must not even be tried once an earlier level has unwound"
);
}
#[test]
fn unwind_one_falls_through_to_a_later_level_only_when_the_earlier_one_is_already_empty() {
let mut innermost = StubLevel::empty();
let mut outer = StubLevel::armed();
let unwound = unwind_one(&mut [&mut innermost, &mut outer]);
assert!(unwound);
assert!(!outer.has_something_live);
}
}