use crate::{Child, Execution, PhaseSpec, PlanError, Pulse, Report, SharedPulse, Total};
use alloc::{sync::Arc, vec::Vec};
use core::fmt;
use enough::{Stop, StopReason};
#[derive(Clone)]
pub(crate) enum StopSource<'a> {
Borrowed(&'a dyn Stop),
Owned(Arc<dyn Stop>),
}
impl StopSource<'_> {
pub(crate) fn get(&self) -> &dyn Stop {
match self {
Self::Borrowed(stop) => *stop,
Self::Owned(stop) => stop.as_ref(),
}
}
pub(crate) fn owned(&self) -> Result<Arc<dyn Stop>, PlanError> {
match self {
Self::Borrowed(_) => Err(PlanError::NotShareable),
Self::Owned(stop) => Ok(stop.clone()),
}
}
}
pub struct StopOnly<'a> {
stop: StopSource<'a>,
}
impl StopOnly<'static> {
pub fn new(stop: impl Stop + 'static) -> Self {
Self {
stop: StopSource::Owned(Arc::new(stop)),
}
}
}
impl<'a> StopOnly<'a> {
pub fn borrowed(stop: &'a dyn Stop) -> Self {
Self {
stop: StopSource::Borrowed(stop),
}
}
}
impl fmt::Debug for StopOnly<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("StopOnly")
.field("owned", &matches!(self.stop, StopSource::Owned(_)))
.finish()
}
}
impl Stop for StopOnly<'_> {
#[track_caller]
fn check(&self) -> Result<(), StopReason> {
self.stop.get().check()
}
fn may_stop(&self) -> bool {
self.stop.get().may_stop()
}
}
impl Report for StopOnly<'_> {
fn advance(&self, _: u64) {}
fn may_report(&self) -> bool {
false
}
}
impl Pulse for StopOnly<'_> {
fn split(&self, _: Execution, parts: &[PhaseSpec<'_>]) -> Result<Vec<Child<'_>>, PlanError> {
PhaseSpec::validate_split(parts)?;
Ok(crate::pulse::untracked_children(self, parts.len()))
}
fn set_total(&self, _: Total) -> Result<(), PlanError> {
Ok(())
}
fn share(&self) -> Result<SharedPulse, PlanError> {
Ok(SharedPulse::new(StopOnly {
stop: StopSource::Owned(self.stop.owned()?),
}))
}
}