use core::marker::PhantomData;
use crate::presence::{Absent, Optional, Presence, Present};
pub trait Split<To: Presence>: Presence {
fn split<T>(value: Self::Output<T>) -> SplitResult<To, Self, T>
where
Self: Sized;
}
pub type SplitResult<To, From, T> = (
<To as Presence>::Output<T>,
<<To as Presence>::RemainderFrom<From> as Presence>::Output<T>,
);
pub trait TrySplit<To: Presence>: Presence {
fn try_split<T>(value: Self::Output<T>) -> Result<SplitResult<To, Self, T>, Self::Output<T>>
where
Self: Sized;
}
impl<From: Presence, To: Presence> TrySplit<To> for From
where
From: Split<To>,
{
fn try_split<T>(value: From::Output<T>) -> Result<SplitResult<To, From, T>, Self::Output<T>> {
Ok(From::split(value))
}
}
impl Split<Absent> for Present {
fn split<T>(value: T) -> (PhantomData<T>, T) {
(PhantomData, value)
}
}
impl Split<Present> for Present {
fn split<T>(value: T) -> (T, PhantomData<T>) {
(value, PhantomData)
}
}
impl Split<Optional> for Present {
fn split<T>(value: T) -> (Option<T>, PhantomData<T>) {
(Some(value), PhantomData)
}
}
impl Split<Absent> for Optional {
fn split<T>(value: Option<T>) -> (PhantomData<T>, Option<T>) {
(PhantomData, value)
}
}
impl Split<Optional> for Optional {
fn split<T>(value: Option<T>) -> (Option<T>, PhantomData<T>) {
(value, PhantomData)
}
}
impl TrySplit<Present> for Optional {
fn try_split<T>(value: Option<T>) -> Result<(T, PhantomData<T>), Option<T>> {
match value {
Some(v) => Ok((v, PhantomData)),
None => Err(None),
}
}
}
impl Split<Absent> for Absent {
fn split<T>(_value: PhantomData<T>) -> (PhantomData<T>, PhantomData<T>) {
(PhantomData, PhantomData)
}
}
impl Split<Optional> for Absent {
fn split<T>(_value: PhantomData<T>) -> (Option<T>, PhantomData<T>) {
(None, PhantomData)
}
}