use ferroui_system::threading::tasks::{Task, TaskCompletionSource};
use ferroui_system::IDisposable;
use std::cell::{Cell, RefCell};
use std::fmt;
#[derive(Default)]
pub struct TestSequencer {
completed_phases: Cell<i64>,
current_phase: Cell<i64>,
waiting: RefCell<Option<TaskCompletionSource<()>>>,
disposed: Cell<bool>,
}
impl fmt::Debug for TestSequencer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}, {}", self.completed_phases(), self.current_phase())
}
}
impl TestSequencer {
pub fn new() -> Self {
Self::default()
}
pub fn completed_phases(&self) -> i64 {
self.completed_phases.get()
}
pub fn current_phase(&self) -> i64 {
self.current_phase.get()
}
pub fn advance_phase_async(&self) -> Task<()> {
self.advance_phase_async_with("")
}
pub fn advance_phase_async_with(&self, comment: &str) -> Task<()> {
let _ = comment;
assert!(!self.disposed.get(), "Cannot access a disposed object. Object name: 'TestSequencer'.");
let waiting = self.waiting.borrow_mut().take();
match waiting {
None => {
self.current_phase.set(self.completed_phases.get() + 1);
let source = TaskCompletionSource::new();
let task = source.task();
*self.waiting.borrow_mut() = Some(source);
task
}
Some(first) => {
self.completed_phases.set(self.completed_phases.get() + 1);
first.set_result(());
Task::from_result(())
}
}
}
}
impl IDisposable for TestSequencer {
fn dispose(&self) {
if self.disposed.replace(true) {
return;
}
let waiting = self.waiting.borrow_mut().take();
if let Some(waiting) = waiting {
let _ = waiting.try_set_canceled();
}
}
}