use std::ops::{Try, FromResidual, ControlFlow, Residual, Yeet};
use std::convert::Infallible;
use crate::NondetResidual;
#[must_use]
pub struct NdResult<T, E>(pub(crate) Result<T, E>);
impl<T, E> NdResult<T, E> {
#[doc(hidden)]
pub fn from_internal(r: Result<T, E>) -> Self { Self(r) }
#[doc(hidden)]
pub fn get_internal(self) -> Result<T, E> {
self.0
}
pub fn and_then<U>(self, f: impl FnOnce(T) -> NdResult<U, E>) -> NdResult<U, E> {
NdResult(self.0.and_then(|x| f(x).0))
}
}
impl<T, E> Try for NdResult<T, E> {
type Output = T;
type Residual = NdResult<Infallible, E>;
fn from_output(output: Self::Output) -> Self {
NdResult(Ok(output))
}
fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
match self.0 {
Ok(x) => ControlFlow::Continue(x),
Err(e) => ControlFlow::Break(NdResult(Err(e))),
}
}
}
impl<T, E> FromResidual<NdResult<Infallible, E>> for NdResult<T, E> {
fn from_residual(residual: NdResult<Infallible, E>) -> Self {
match residual.0 {
Ok(x) => match x {},
Err(e) => NdResult(Err(e))
}
}
}
impl<T, E> FromResidual<Result<Infallible, E>> for NdResult<T, E> {
fn from_residual(residual: Result<Infallible, E>) -> Self {
match residual {
Ok(x) => match x {},
Err(e) => NdResult(Err(e))
}
}
}
impl<T, E> FromResidual<NondetResidual> for NdResult<T, E> {
fn from_residual(residual: NondetResidual) -> Self {
match residual {}
}
}
impl<T, E> Residual<T> for NdResult<Infallible, E> {
type TryType = NdResult<T, E>;
}
impl<T, E> FromResidual<Yeet<E>> for NdResult<T, E> {
fn from_residual(residual: Yeet<E>) -> Self {
NdResult(Err(residual.0))
}
}