use crate::awaitable::{IntoStateMachine, State, StateExt, Superstate};
use crate::Outcome;
pub(crate) struct Inner<M>
where
M: IntoStateMachine,
{
pub shared_storage: M,
pub state: M::State,
}
impl<M> Inner<M>
where
M: IntoStateMachine,
M::State: State<M> + 'static,
for<'sub> M::Superstate<'sub>: Superstate<M>,
{
pub(crate) async fn init_with_context(&mut self, context: &mut M::Context<'_>) {
let enter_levels = self.state.depth();
self.state
.enter(&mut self.shared_storage, context, enter_levels)
.await;
}
pub(crate) async fn handle_with_context(
&mut self,
event: &M::Event<'_>,
context: &mut M::Context<'_>,
) {
let outcome = self
.state
.handle(&mut self.shared_storage, event, context)
.await;
match outcome {
Outcome::Super => {}
Outcome::Handled => {}
Outcome::Transition(state) => self.transition(state, context).await,
}
}
pub(crate) async fn transition(&mut self, mut target: M::State, context: &mut M::Context<'_>) {
M::before_transition(&mut self.shared_storage, &self.state, &target, context).await;
let (exit_levels, enter_levels) = self.state.transition_path(&mut target);
self.state
.exit(&mut self.shared_storage, context, exit_levels)
.await;
core::mem::swap(&mut self.state, &mut target);
self.state
.enter(&mut self.shared_storage, context, enter_levels)
.await;
M::after_transition(&mut self.shared_storage, &target, &self.state, context).await;
}
}
impl<M> Clone for Inner<M>
where
M: IntoStateMachine + Clone,
M::State: Clone,
{
fn clone(&self) -> Self {
Self {
shared_storage: self.shared_storage.clone(),
state: self.state.clone(),
}
}
}
impl<M> PartialEq for Inner<M>
where
M: IntoStateMachine + PartialEq,
M::State: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.shared_storage == other.shared_storage && self.state == other.state
}
}
impl<M> Eq for Inner<M>
where
M: IntoStateMachine + Eq,
M::State: Eq,
{
}
#[cfg(feature = "serde")]
impl<M> serde::Serialize for Inner<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.shared_storage)?;
serializer.serialize_field("state", &self.state)?;
serializer.end()
}
}
#[cfg(feature = "serde")]
impl<'de, M> serde::Deserialize<'de> for Inner<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>,
{
use core::marker::PhantomData;
enum Field {
SharedStorage,
State,
}
impl<'de> serde::Deserialize<'de> for Field {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
struct FieldVisitor;
impl<'de> serde::de::Visitor<'de> for FieldVisitor {
type Value = Field;
fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
formatter.write_str("`shared_storage` or `state`")
}
fn visit_str<E>(self, value: &str) -> Result<Field, E>
where
E: serde::de::Error,
{
match value {
"shared_storage" => Ok(Field::SharedStorage),
"state" => Ok(Field::State),
_ => Err(serde::de::Error::unknown_field(value, FIELDS)),
}
}
}
deserializer.deserialize_identifier(FieldVisitor)
}
}
struct InnerVisitor<M>(PhantomData<M>);
impl<'de, M> serde::de::Visitor<'de> for InnerVisitor<M>
where
M: IntoStateMachine + serde::Deserialize<'de>,
M::State: serde::Deserialize<'de>,
{
type Value = Inner<M>;
fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result {
formatter.write_str("StateMachine")
}
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
let shared_storage = seq
.next_element()?
.ok_or_else(|| serde::de::Error::invalid_length(0, &self))?;
let state = seq
.next_element()?
.ok_or_else(|| serde::de::Error::invalid_length(1, &self))?;
let inner = Inner {
shared_storage,
state,
};
Ok(inner)
}
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
where
V: serde::de::MapAccess<'de>,
{
let mut shared_storage = None;
let mut state = None;
while let Some(key) = map.next_key()? {
match key {
Field::SharedStorage => {
if shared_storage.is_some() {
return Err(serde::de::Error::duplicate_field("shared_storage"));
}
shared_storage = Some(map.next_value()?);
}
Field::State => {
if state.is_some() {
return Err(serde::de::Error::duplicate_field("state"));
}
state = Some(map.next_value()?);
}
}
}
let shared_storage = shared_storage
.ok_or_else(|| serde::de::Error::missing_field("shared_storage"))?;
let state = state.ok_or_else(|| serde::de::Error::missing_field("state"))?;
let inner = Inner {
shared_storage,
state,
};
Ok(inner)
}
}
const FIELDS: &[&str] = &["shared_storage", "state"];
deserializer.deserialize_struct(
"StateMachine",
FIELDS,
InnerVisitor(PhantomData::default()),
)
}
}