mod guard;
mod storage;
#[cfg(feature = "alloc")]
mod weak;
use crate::{
Initial, RuntimeStateMarker, SOwned, State, StateMachineImpl, StateMarker,
StateRuntimeMarkerFor, StateTrait, state_trait,
};
#[cfg(feature = "alloc")]
use alloc::rc::Rc;
#[cfg(feature = "alloc")]
use alloc::sync::Arc;
use core::marker::PhantomData;
pub use guard::{
SharedBorrowState, StateMut, StateMutTransitionCall, StateRef, StorageStateMut,
StorageStateRef, transition_mut,
};
#[cfg(feature = "std")]
pub use storage::{MutexStorage, RwLockStorage};
pub use storage::{
RefCellStorage, SharedStateError, SharedStorage, SharedStorageView, SharedValue,
WrongStateError,
};
#[cfg(feature = "alloc")]
pub use weak::{WeakSArc, WeakSRc, WeakSRcRefCell};
#[cfg(feature = "std")]
pub use weak::{WeakSArcMutex, WeakSArcRwLock};
pub struct DynState<T> {
value: SharedValue<T>,
}
pub struct DynStorage;
impl SharedStorageView for DynStorage {
type Storage<T> = SharedValue<T>;
type ReadGuard<'a, T>
= &'a SharedValue<T>
where
T: 'a;
type WriteGuard<'a, T>
= &'a mut SharedValue<T>
where
T: 'a;
}
impl<T> DynState<T>
where
T: StateMachineImpl,
{
#[must_use]
pub fn new<State>(value: T) -> Self
where
T::Standin: Initial<State>,
State: crate::ConcreteStateTrait,
{
Self {
value: SharedValue {
state: state_trait::erased_state::<State>(),
value,
},
}
}
#[must_use]
pub fn from_state<StateMarker>(state: State<SOwned, T, StateMarker>) -> Self
where
StateMarker: crate::ConcreteStateTrait,
{
Self {
value: SharedValue {
state: state_trait::erased_state::<StateMarker>(),
value: state.inner.value,
},
}
}
pub fn borrow<RequestedState>(
&self,
) -> Result<
SRefView<'_, DynStorage, T, RuntimeStateMarker<RequestedState>>,
SharedStateError<core::convert::Infallible>,
>
where
RequestedState:
StateTrait + StateMarker + StateRuntimeMarkerFor<<RequestedState as StateMarker>::Kind>,
RuntimeStateMarker<RequestedState>: SharedBorrowState,
{
StateRef::from_guard(&self.value).map(State::from_inner)
}
pub fn borrow_mut<RequestedState>(
&mut self,
) -> Result<
SMutView<'_, DynStorage, T, RuntimeStateMarker<RequestedState>>,
SharedStateError<core::convert::Infallible>,
>
where
RequestedState:
StateTrait + StateMarker + StateRuntimeMarkerFor<<RequestedState as StateMarker>::Kind>,
RuntimeStateMarker<RequestedState>: SharedBorrowState,
{
StateMut::from_guard(&mut self.value).map(State::from_inner)
}
}
pub struct SharedState<P, S, T>
where
S: SharedStorage,
{
pub(super) storage: P,
pub(super) backend: PhantomData<fn() -> S>,
pub(super) value: PhantomData<fn() -> T>,
}
impl<P: Clone, S: SharedStorage, T> Clone for SharedState<P, S, T> {
fn clone(&self) -> Self {
Self {
storage: self.storage.clone(),
backend: PhantomData,
value: PhantomData,
}
}
}
impl<P, Backend, T> SharedState<P, Backend, T>
where
Backend: SharedStorage,
P: From<Backend::Storage<T>> + AsRef<Backend::Storage<T>>,
T: StateMachineImpl,
{
#[must_use]
pub fn new<State>(value: T) -> Self
where
T::Standin: Initial<State>,
State: crate::ConcreteStateTrait,
{
Self {
storage: P::from(Backend::new(SharedValue {
state: state_trait::erased_state::<State>(),
value,
})),
backend: PhantomData,
value: PhantomData,
}
}
#[must_use]
pub fn from_state<StateMarker>(state: State<SOwned, T, StateMarker>) -> Self
where
StateMarker: crate::ConcreteStateTrait,
{
Self {
storage: P::from(Backend::new(SharedValue {
state: state_trait::erased_state::<StateMarker>(),
value: state.inner.value,
})),
backend: PhantomData,
value: PhantomData,
}
}
pub fn borrow<RequestedState>(
&self,
) -> Result<
SRefView<'_, Backend, T, RuntimeStateMarker<RequestedState>>,
SharedStateError<Backend::ReadError<'_, T>>,
>
where
RequestedState:
StateTrait + StateMarker + StateRuntimeMarkerFor<<RequestedState as StateMarker>::Kind>,
RuntimeStateMarker<RequestedState>: SharedBorrowState,
{
let guard = Backend::read(self.storage.as_ref()).map_err(SharedStateError::Storage)?;
StateRef::from_guard(guard).map(State::from_inner)
}
pub fn borrow_mut<RequestedState>(
&self,
) -> Result<
SMutView<'_, Backend, T, RuntimeStateMarker<RequestedState>>,
SharedStateError<Backend::WriteError<'_, T>>,
>
where
RequestedState:
StateTrait + StateMarker + StateRuntimeMarkerFor<<RequestedState as StateMarker>::Kind>,
RuntimeStateMarker<RequestedState>: SharedBorrowState,
{
let guard = Backend::write(self.storage.as_ref()).map_err(SharedStateError::Storage)?;
StateMut::from_guard(guard).map(State::from_inner)
}
}
#[cfg(feature = "alloc")]
pub type SRc<Storage, T> = SharedState<Rc<<Storage as SharedStorageView>::Storage<T>>, Storage, T>;
#[cfg(feature = "alloc")]
pub type SArc<Storage, T> =
SharedState<Arc<<Storage as SharedStorageView>::Storage<T>>, Storage, T>;
#[cfg(feature = "alloc")]
pub type SRcRefCell<T> = SRc<RefCellStorage, T>;
#[cfg(feature = "std")]
pub type SArcMutex<T> = SArc<MutexStorage, T>;
#[cfg(feature = "std")]
pub type SArcRwLock<T> = SArc<RwLockStorage, T>;
pub type SRefCell<'a> = StorageStateMut<'a, RefCellStorage>;
#[cfg(feature = "std")]
pub type SMutex<'a> = StorageStateMut<'a, MutexStorage>;
#[cfg(feature = "std")]
pub type SRwLock<'a> = StorageStateMut<'a, RwLockStorage>;
pub type SMutView<'a, Backend, T, S> = State<StorageStateMut<'a, Backend>, T, S>;
pub type SRefView<'a, Backend, T, S> = State<StorageStateRef<'a, Backend>, T, S>;