use crate::{Tuple, TupleLike, Unit};
pub trait Unwrap {
type Output;
fn unwrap(self) -> Self::Output;
fn has_value(&self) -> bool;
}
pub trait UnwrapOrDefault {
type Output;
fn unwrap_or_default(self) -> Self::Output;
}
impl<T> Unwrap for Option<T> {
type Output = T;
fn unwrap(self) -> Self::Output {
self.unwrap()
}
fn has_value(&self) -> bool {
self.is_some()
}
}
impl<T, E: std::fmt::Debug> Unwrap for Result<T, E> {
type Output = T;
fn unwrap(self) -> Self::Output {
self.unwrap()
}
fn has_value(&self) -> bool {
self.is_ok()
}
}
impl<T: Default> UnwrapOrDefault for Option<T> {
type Output = T;
fn unwrap_or_default(self) -> Self::Output {
self.unwrap_or_default()
}
}
impl<T: Default, E> UnwrapOrDefault for Result<T, E> {
type Output = T;
fn unwrap_or_default(self) -> Self::Output {
self.unwrap_or_default()
}
}
impl Unwrap for Unit {
type Output = Unit;
fn unwrap(self) -> Self::Output {
Self
}
fn has_value(&self) -> bool {
true
}
}
impl<First, Other> Unwrap for Tuple<First, Other>
where
Other: TupleLike + Unwrap,
First: Unwrap,
{
type Output = Tuple<<First as Unwrap>::Output, <Other as Unwrap>::Output>;
fn unwrap(self) -> Self::Output {
Tuple(self.0.unwrap(), self.1.unwrap())
}
fn has_value(&self) -> bool {
self.0.has_value() && self.1.has_value()
}
}
impl UnwrapOrDefault for Unit {
type Output = Unit;
fn unwrap_or_default(self) -> Self::Output {
Self
}
}
impl<First, Other> Tuple<First, Other>
where
Other: TupleLike + Unwrap,
First: Unwrap,
{
pub fn try_unwrap(self) -> Option<<Self as Unwrap>::Output> {
if self.has_value() {
Some(self.unwrap())
} else {
None
}
}
}
impl<First, Other> UnwrapOrDefault for Tuple<First, Other>
where
Other: TupleLike + UnwrapOrDefault,
First: UnwrapOrDefault,
{
type Output = Tuple<<First as UnwrapOrDefault>::Output, <Other as UnwrapOrDefault>::Output>;
fn unwrap_or_default(self) -> Self::Output {
Tuple(self.0.unwrap_or_default(), self.1.unwrap_or_default())
}
}