use super::*;
use anyhow::Error as AnyError;
pub struct DefineTrait<State, Error = AnyError> {
_ignore: std::marker::PhantomData<(State, Error)>,
}
impl<State, Error> DefineTrait<State, Error> {
pub fn new() -> Self {
DefineTrait {
_ignore: Default::default(),
}
}
}
impl<State, Error> Domain for DefineTrait<State, Error> {
type State = State;
type Error = Error;
}
impl<State, Error> Clone for DefineTrait<State, Error> {
fn clone(&self) -> Self {
Self::new()
}
}
impl<State, Error> Default for DefineTrait<State, Error> {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct Incorporated<Base, Prop> {
pub base: Base,
pub prop: Prop,
}
impl<Base: Domain, Prop> Domain for Incorporated<Base, Prop> {
type State = Base::State;
type Error = Base::Error;
}
pub trait Incorporate {
fn with<Prop>(self, prop: Prop) -> Incorporated<Self, Prop>
where
Self: Sized;
}
impl<D: Domain> Incorporate for D {
fn with<Prop>(self, prop: Prop) -> Incorporated<Self, Prop>
where
Self: Sized,
{
Incorporated { base: self, prop }
}
}
#[derive(Debug, Clone)]
pub struct Chained<Base, Prop> {
pub base: Base,
pub prop: Prop,
}
impl<Base: Domain, Prop> Domain for Chained<Base, Prop> {
type State = Base::State;
type Error = Base::Error;
}
pub trait Chain {
fn chain<Prop>(self, prop: Prop) -> Chained<Self, Prop>
where
Self: Sized;
}
impl<D: Domain> Chain for D {
fn chain<Prop>(self, prop: Prop) -> Chained<Self, Prop>
where
Self: Sized,
{
Chained { base: self, prop }
}
}
#[derive(Debug, Clone)]
pub struct Mapped<Base, Prop> {
pub base: Base,
pub prop: Prop,
}
impl<Base: Domain, Prop> Domain for Mapped<Base, Prop> {
type State = Base::State;
type Error = Base::Error;
}
pub trait Map {
fn map<Prop>(self, prop: Prop) -> Mapped<Self, Prop>
where
Self: Sized;
}
impl<D: Domain> Map for D {
fn map<Prop>(self, prop: Prop) -> Mapped<Self, Prop>
where
Self: Sized,
{
Mapped { base: self, prop }
}
}
#[derive(Debug, Clone)]
pub struct Lifted<Base, Lifter, Prop> {
pub base: Base,
pub lifter: Lifter,
pub prop: Prop,
}
impl<Base: Domain, Lifter, Prop> Domain for Lifted<Base, Lifter, Prop> {
type State = Base::State;
type Error = Base::Error;
}
pub trait Lift {
fn lift<Lifter, Prop>(self, lifter: Lifter, prop: Prop) -> Lifted<Self, Lifter, Prop>
where
Self: Sized;
fn chain_lift<Lifter, Prop>(
self,
lifter: Lifter,
prop: Prop,
) -> ChainedLift<Self, Lifter, Prop>
where
Self: Sized + Domain;
}
type ChainedLift<Base, Lifter, Prop> = Chained<
Base,
Lifted<DefineTrait<<Base as Domain>::State, <Base as Domain>::Error>, Lifter, Prop>,
>;
impl<D: Domain> Lift for D {
fn lift<Lifter, Prop>(self, lifter: Lifter, prop: Prop) -> Lifted<Self, Lifter, Prop>
where
Self: Sized,
{
Lifted {
base: self,
lifter,
prop,
}
}
fn chain_lift<Lifter, Prop>(self, lifter: Lifter, prop: Prop) -> ChainedLift<Self, Lifter, Prop>
where
Self: Sized,
{
self.chain(DefineTrait::<D::State, D::Error>::new().lift(lifter, prop))
}
}