use core::cmp::Ordering;
use core::future::Future;
use crate::awaitable::IntoStateMachine;
use crate::Outcome;
pub trait Superstate<M>
where
M: IntoStateMachine,
{
fn call_handler(
&mut self,
shared_storage: &mut M,
event: &M::Event<'_>,
context: &mut M::Context<'_>,
) -> impl Future<Output = Outcome<M::State>>;
#[allow(unused)]
fn call_entry_action(
&mut self,
shared_storage: &mut M,
context: &mut M::Context<'_>,
) -> impl Future<Output = ()> {
core::future::ready(())
}
#[allow(unused)]
fn call_exit_action(
&mut self,
shared_storage: &mut M,
context: &mut M::Context<'_>,
) -> impl Future<Output = ()> {
core::future::ready(())
}
fn superstate(&mut self) -> Option<Self>
where
Self: Sized,
{
None
}
}
pub trait SuperstateExt<M>: Superstate<M>
where
Self: Sized,
M: IntoStateMachine,
for<'sub> M::Superstate<'sub>: Superstate<M>,
{
fn same_state(lhs: &M::Superstate<'_>, rhs: &M::Superstate<'_>) -> bool {
use core::mem::{discriminant, transmute, Discriminant};
let lhs: Discriminant<M::Superstate<'_>> = unsafe { transmute(discriminant(lhs)) };
let rhs: Discriminant<M::Superstate<'_>> = unsafe { transmute(discriminant(rhs)) };
lhs == rhs
}
fn depth(&mut self) -> usize {
match self.superstate() {
Some(mut superstate) => superstate.depth() + 1,
None => 1,
}
}
fn common_ancestor_depth(
mut source: M::Superstate<'_>,
mut target: M::Superstate<'_>,
) -> usize {
match source.depth().cmp(&target.depth()) {
Ordering::Equal => match Self::same_state(&source, &target) {
true => source.depth(),
false => match (source.superstate(), target.superstate()) {
(Some(source), Some(target)) => Self::common_ancestor_depth(source, target),
_ => 0,
},
},
Ordering::Greater => match source.superstate() {
Some(superstate) => Self::common_ancestor_depth(superstate, target),
None => 0,
},
Ordering::Less => match target.superstate() {
Some(superstate) => Self::common_ancestor_depth(source, superstate),
None => 0,
},
}
}
}
impl<M> Superstate<M> for ()
where
M: IntoStateMachine,
{
fn call_handler(
&mut self,
_: &mut M,
_: &M::Event<'_>,
_: &mut M::Context<'_>,
) -> impl Future<Output = Outcome<M::State>> {
core::future::ready(Outcome::Handled)
}
fn call_entry_action(&mut self, _: &mut M, _: &mut M::Context<'_>) -> impl Future<Output = ()> {
core::future::ready(())
}
fn call_exit_action(&mut self, _: &mut M, _: &mut M::Context<'_>) -> impl Future<Output = ()> {
core::future::ready(())
}
fn superstate(&mut self) -> Option<Self>
where
Self: Sized,
{
None
}
}
impl<T, M> SuperstateExt<M> for T
where
Self: Superstate<M>,
M: IntoStateMachine,
for<'sub> M::Superstate<'sub>: Superstate<M>,
{
}