use core::fmt::Debug;
use crate::awaitable::{Inner, IntoStateMachine, State, Superstate};
pub trait IntoStateMachineExt: IntoStateMachine
where
for<'sub> Self::Superstate<'sub>: Superstate<Self>,
Self::State: State<Self>,
{
fn state_machine(self) -> StateMachine<Self>
where
Self: Sized,
{
let inner = Inner {
shared_storage: self,
state: Self::initial(),
};
StateMachine {
inner,
initialized: false,
}
}
fn uninitialized_state_machine(self) -> UninitializedStateMachine<Self> {
let inner = Inner {
shared_storage: self,
state: Self::initial(),
};
UninitializedStateMachine { inner }
}
}
impl<T> IntoStateMachineExt for T
where
Self: IntoStateMachine,
for<'sub> Self::Superstate<'sub>: Superstate<Self>,
Self::State: State<Self>,
{
}
pub struct StateMachine<M>
where
M: IntoStateMachine,
{
inner: Inner<M>,
initialized: bool,
}
impl<M> StateMachine<M>
where
M: IntoStateMachine,
M::State: State<M> + 'static,
for<'sub> M::Superstate<'sub>: Superstate<M>,
{
pub async fn init(&mut self)
where
for<'ctx> M: IntoStateMachine<Context<'ctx> = ()>,
{
self.init_with_context(&mut ()).await;
}
pub async fn init_with_context(&mut self, context: &mut M::Context<'_>) {
if !self.initialized {
self.inner.init_with_context(context).await;
self.initialized = true;
}
}
pub async fn handle(&mut self, event: &M::Event<'_>)
where
for<'ctx> M: IntoStateMachine<Context<'ctx> = ()>,
{
self.handle_with_context(event, &mut ()).await;
}
pub async fn handle_with_context(
&mut self,
event: &M::Event<'_>,
context: &mut M::Context<'_>,
) {
if !self.initialized {
self.inner.init_with_context(context).await;
self.initialized = true;
}
self.inner.handle_with_context(event, context).await;
}
pub async fn step(&mut self)
where
for<'evt, 'ctx> M: IntoStateMachine<Event<'evt> = (), Context<'ctx> = ()>,
{
self.handle_with_context(&(), &mut ()).await;
}
pub async fn step_with_context(&mut self, context: &mut M::Context<'_>)
where
for<'evt> M: IntoStateMachine<Event<'evt> = ()>,
{
self.handle_with_context(&(), context).await;
}
pub fn state(&self) -> &M::State {
&self.inner.state
}
pub fn inner(&self) -> &M {
&self.inner.shared_storage
}
pub unsafe fn inner_mut(&mut self) -> &mut M {
&mut self.inner.shared_storage
}
pub unsafe fn state_mut(&mut self) -> &mut M::State {
&mut self.inner.state
}
}
impl<M> Clone for StateMachine<M>
where
M: IntoStateMachine + Clone,
M::State: Clone,
{
fn clone(&self) -> Self {
let inner = self.inner.clone();
let initialized = self.initialized;
Self { inner, initialized }
}
}
impl<M> PartialEq for StateMachine<M>
where
M: IntoStateMachine + PartialEq,
M::State: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner && self.initialized == other.initialized
}
}
impl<M> Eq for StateMachine<M>
where
M: IntoStateMachine + PartialEq,
M::State: PartialEq,
{
}
impl<M> Default for StateMachine<M>
where
M: IntoStateMachine + Default,
{
fn default() -> Self {
let inner = Inner {
shared_storage: M::default(),
state: M::initial(),
};
Self {
inner,
initialized: false,
}
}
}
impl<M> core::ops::Deref for StateMachine<M>
where
M: IntoStateMachine,
{
type Target = M;
fn deref(&self) -> &Self::Target {
&self.inner.shared_storage
}
}
impl<M> From<UninitializedStateMachine<M>> for StateMachine<M>
where
M: IntoStateMachine,
{
fn from(value: UninitializedStateMachine<M>) -> Self {
Self {
inner: value.inner,
initialized: false,
}
}
}
impl<M> From<InitializedStateMachine<M>> for StateMachine<M>
where
M: IntoStateMachine,
{
fn from(value: InitializedStateMachine<M>) -> Self {
Self {
inner: value.inner,
initialized: true,
}
}
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<M> serde::Serialize for StateMachine<M>
where
M: IntoStateMachine + serde::Serialize,
M::State: serde::Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.inner.serialize(serializer)
}
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de, M> serde::Deserialize<'de> for StateMachine<M>
where
M: IntoStateMachine + serde::Deserialize<'de>,
M::State: serde::Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let inner: Inner<M> = Inner::deserialize(deserializer)?;
Ok(StateMachine {
inner,
initialized: false,
})
}
}
#[cfg(feature = "bevy")]
#[cfg_attr(docsrs, doc(cfg(feature = "bevy")))]
impl<M> bevy_ecs::component::Component for StateMachine<M>
where
Self: 'static + Send + Sync,
M: IntoStateMachine,
{
type Storage = bevy_ecs::component::TableStorage;
}
pub struct InitializedStateMachine<M>
where
M: IntoStateMachine,
{
inner: Inner<M>,
}
impl<M> InitializedStateMachine<M>
where
M: IntoStateMachine,
M::State: State<M> + 'static,
for<'sub> M::Superstate<'sub>: Superstate<M>,
{
pub async fn handle(&mut self, event: &M::Event<'_>)
where
for<'ctx> M: IntoStateMachine<Context<'ctx> = ()>,
{
self.handle_with_context(event, &mut ()).await;
}
pub async fn handle_with_context(&mut self, event: &M::Event<'_>, context: &mut M::Context<'_>)
where
M: IntoStateMachine,
{
self.inner.handle_with_context(event, context).await;
}
pub async fn step(&mut self)
where
for<'evt, 'ctx> M: IntoStateMachine<Event<'evt> = (), Context<'ctx> = ()>,
{
self.handle(&()).await;
}
pub async fn step_with_context(&mut self, context: &mut M::Context<'_>)
where
for<'evt> M: IntoStateMachine<Event<'evt> = ()>,
{
self.handle_with_context(&(), context).await;
}
pub fn state(&self) -> &M::State {
&self.inner.state
}
pub fn inner(&self) -> &M {
&self.inner.shared_storage
}
pub unsafe fn inner_mut(&mut self) -> &mut M {
&mut self.inner.shared_storage
}
pub unsafe fn state_mut(&mut self) -> &mut M::State {
&mut self.inner.state
}
}
impl<M> Clone for InitializedStateMachine<M>
where
M: IntoStateMachine + Clone,
M::State: Clone,
{
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<M> Debug for InitializedStateMachine<M>
where
M: IntoStateMachine + Debug,
M::State: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("InitializedStateMachine")
.field("shared_storage", &self.inner.shared_storage as &dyn Debug)
.field("state", &self.inner.state as &dyn Debug)
.finish()
}
}
impl<M> PartialEq for InitializedStateMachine<M>
where
M: IntoStateMachine + PartialEq,
M::State: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
}
}
impl<M> Eq for InitializedStateMachine<M>
where
M: IntoStateMachine + PartialEq + Eq,
M::State: PartialEq + Eq,
{
}
impl<M> core::ops::Deref for InitializedStateMachine<M>
where
M: IntoStateMachine,
{
type Target = M;
fn deref(&self) -> &Self::Target {
&self.inner.shared_storage
}
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<M> serde::Serialize for InitializedStateMachine<M>
where
M: IntoStateMachine + serde::Serialize,
M::State: serde::Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
use serde::ser::SerializeStruct;
let mut serializer = serializer.serialize_struct("StateMachine", 2)?;
serializer.serialize_field("shared_storage", &self.inner.shared_storage)?;
serializer.serialize_field("state", &self.inner.state)?;
serializer.end()
}
}
#[cfg(feature = "bevy")]
#[cfg_attr(docsrs, doc(cfg(feature = "bevy")))]
impl<M> bevy_ecs::component::Component for InitializedStateMachine<M>
where
Self: 'static + Send + Sync,
M: IntoStateMachine,
{
type Storage = bevy_ecs::component::TableStorage;
}
pub struct UninitializedStateMachine<M>
where
M: IntoStateMachine,
{
inner: Inner<M>,
}
impl<M> UninitializedStateMachine<M>
where
M: IntoStateMachine,
M::State: State<M> + 'static,
for<'sub> M::Superstate<'sub>: Superstate<M>,
{
pub async fn init(self) -> InitializedStateMachine<M>
where
for<'ctx> M: IntoStateMachine<Context<'ctx> = ()>,
{
let mut state_machine = InitializedStateMachine { inner: self.inner };
state_machine.inner.init_with_context(&mut ()).await;
state_machine
}
pub async fn init_with_context(
self,
context: &mut M::Context<'_>,
) -> InitializedStateMachine<M> {
let mut state_machine = InitializedStateMachine { inner: self.inner };
state_machine.inner.init_with_context(context).await;
state_machine
}
pub fn inner(&self) -> &M {
&self.inner.shared_storage
}
pub fn inner_mut(&mut self) -> &mut M {
&mut self.inner.shared_storage
}
pub fn state_mut(&mut self) -> &mut M::State {
&mut self.inner.state
}
}
impl<M> Clone for UninitializedStateMachine<M>
where
M: IntoStateMachine + Clone,
M::State: Clone,
{
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<M> Debug for UninitializedStateMachine<M>
where
M: IntoStateMachine + Debug,
M::State: Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("UnInitializedStateMachine")
.field("shared_storage", &self.inner.shared_storage as &dyn Debug)
.field("state", &self.inner.state as &dyn Debug)
.finish()
}
}
impl<M> PartialEq for UninitializedStateMachine<M>
where
M: IntoStateMachine + PartialEq,
M::State: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
}
}
impl<M> Eq for UninitializedStateMachine<M>
where
M: IntoStateMachine + PartialEq + Eq,
M::State: PartialEq + Eq,
{
}
impl<M> core::ops::Deref for UninitializedStateMachine<M>
where
M: IntoStateMachine,
{
type Target = M;
fn deref(&self) -> &Self::Target {
&self.inner.shared_storage
}
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<M> serde::Serialize for UninitializedStateMachine<M>
where
M: IntoStateMachine + serde::Serialize,
M::State: serde::Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
self.inner.serialize(serializer)
}
}
#[cfg(feature = "serde")]
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
impl<'de, M> serde::Deserialize<'de> for UninitializedStateMachine<M>
where
M: IntoStateMachine + serde::Deserialize<'de>,
M::State: serde::Deserialize<'de>,
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let inner: Inner<M> = Inner::deserialize(deserializer)?;
Ok(UninitializedStateMachine { inner })
}
}