use crate::error::NoError;
pub trait StateSubspace {
type ProjectedState;
}
pub trait ProjectState<State>: StateSubspace {
type ProjectionError;
fn project(&self, state: &State)
-> Result<Option<Self::ProjectedState>, Self::ProjectionError>;
}
pub trait LiftState<State>: StateSubspace {
type LiftError;
fn lift(
&self,
original: &State,
projection: Self::ProjectedState,
) -> Result<Option<State>, Self::LiftError>;
}
pub trait StateMap<State>: ProjectState<State> + LiftState<State> {}
impl<State, T: ProjectState<State> + LiftState<State>> StateMap<State> for T {}
pub struct NoStateSubspace<State> {
_ignore: std::marker::PhantomData<State>,
}
impl<State> NoStateSubspace<State> {
pub fn new() -> Self {
Self {
_ignore: Default::default(),
}
}
}
impl<State> StateSubspace for NoStateSubspace<State> {
type ProjectedState = State;
}
impl<State: Clone> ProjectState<State> for NoStateSubspace<State> {
type ProjectionError = NoError;
fn project(&self, state: &State) -> Result<Option<State>, NoError> {
Ok(Some(state.clone()))
}
}
impl<State> LiftState<State> for NoStateSubspace<State> {
type LiftError = NoError;
fn lift(&self, _: &State, projection: State) -> Result<Option<State>, NoError> {
Ok(Some(projection))
}
}
#[derive(Debug)]
pub struct StateInto<ProjectedState> {
_ignore: std::marker::PhantomData<ProjectedState>,
}
impl<ProjectedState> StateInto<ProjectedState> {
pub fn new() -> Self {
Self {
_ignore: Default::default(),
}
}
}
impl<ProjectedState> StateSubspace for StateInto<ProjectedState> {
type ProjectedState = ProjectedState;
}
impl<State: Clone + Into<ProjectedState>, ProjectedState> ProjectState<State>
for StateInto<ProjectedState>
{
type ProjectionError = NoError;
fn project(&self, state: &State) -> Result<Option<ProjectedState>, NoError> {
Ok(Some(state.clone().into()))
}
}
impl<State, ProjectedState: Into<State>> LiftState<State> for StateInto<ProjectedState> {
type LiftError = NoError;
fn lift(&self, _: &State, projection: Self::ProjectedState) -> Result<Option<State>, NoError> {
Ok(Some(projection.into()))
}
}
impl<ProjectedState> Clone for StateInto<ProjectedState> {
fn clone(&self) -> Self {
Self::new()
}
}
#[derive(Debug)]
pub struct StateMaybeInto<ProjectedState> {
_ignore: std::marker::PhantomData<ProjectedState>,
}
impl<ProjectedState> StateMaybeInto<ProjectedState> {
pub fn new() -> Self {
Self {
_ignore: Default::default(),
}
}
}
impl<ProjectedState> StateSubspace for StateMaybeInto<ProjectedState> {
type ProjectedState = ProjectedState;
}
impl<State, ProjectedState> ProjectState<State> for StateMaybeInto<ProjectedState>
where
State: Clone + Into<Option<ProjectedState>>,
{
type ProjectionError = NoError;
fn project(&self, state: &State) -> Result<Option<ProjectedState>, NoError> {
Ok(state.clone().into())
}
}
impl<State, ProjectedState> LiftState<State> for StateMaybeInto<ProjectedState>
where
ProjectedState: Into<Option<State>>,
{
type LiftError = NoError;
fn lift(&self, _: &State, projection: Self::ProjectedState) -> Result<Option<State>, NoError> {
Ok(projection.into())
}
}
impl<ProjectedState> Clone for StateMaybeInto<ProjectedState> {
fn clone(&self) -> Self {
Self::new()
}
}