use std::{convert::identity, fmt::Debug};
pub type ResultS<T> = Result<T, String>;
pub trait ResultBoost<T, E> {
fn transform<T2, Error2>(
self,
transformer_ok: impl FnMut(T) -> T2,
transformer_err: impl FnMut(E) -> Error2,
) -> Result<T2, Error2>;
#[inline(always)]
fn transform_err<Error2>(self, transformer: impl FnMut(E) -> Error2) -> Result<T, Error2>
where
Self: Sized,
{
self.transform(identity, transformer)
}
#[inline(always)]
fn transform_err_debug(self) -> Result<T, String>
where
Self: Sized,
E: Debug,
{
self.transform_err(|e| format!("{e:?}"))
}
#[inline(always)]
fn transform_err_string(self) -> Result<T, String>
where
Self: Sized,
E: ToString,
{
self.transform_err(|e| e.to_string())
}
fn flip(self) -> Result<E, T>;
fn ok_or_run(self, f: impl FnOnce(E)) -> Option<T>;
}
pub trait ResultBoostSingular<TorE> {
fn collapse(self) -> TorE;
}
impl<T, E> ResultBoost<T, E> for Result<T, E> {
#[inline]
fn transform<T2, Error2>(
self,
mut transformer_ok: impl FnMut(T) -> T2,
mut transformer_err: impl FnMut(E) -> Error2,
) -> Result<T2, Error2> {
match self {
Ok(ok) => Ok(transformer_ok(ok)),
Err(err) => Err(transformer_err(err)),
}
}
#[inline]
fn flip(self) -> Result<E, T> {
match self {
Ok(v) => Err(v),
Err(v) => Ok(v),
}
}
#[inline]
#[must_use]
fn ok_or_run(self, f: impl FnOnce(E)) -> Option<T> {
match self {
Ok(v) => Some(v),
Err(e) => {
f(e);
None
}
}
}
}
impl<T> ResultBoostSingular<T> for Result<T, T> {
#[inline]
fn collapse(self) -> T {
match self {
Ok(v) | Err(v) => v,
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::asserts;
#[test]
fn transform_err() {
asserts! {
Result::<i32, &str>::Ok(1)
.transform_err(|_| 1) => Ok(1)
Result::<i32, &str>::Err("这是个错误")
.transform_err(|err| err.chars().count()) => Err(5)
Result::<i32, &str>::Err("这是个错误") .transform_err_debug() => Err(format!("{:?}", "这是个错误"))
Result::<usize, usize>::Ok(0)
.transform_err(|err| err + 1) => Ok(0)
Result::<usize, usize>::Err(0)
.transform_err(|err| err + 1) => Err(1)
Result::<usize, usize>::Err(0) .transform_err_string() => Err("0".into())
}
type MyResult = Result<bool, String>;
fn is_even_of_text(text: &str) -> MyResult {
let parsed = text.parse::<i32>().transform_err(|err| format!("{err}"))?;
Ok(parsed & 1 == 0)
}
asserts! {
is_even_of_text("1") => Ok(false),
is_even_of_text("0") => Ok(true),
is_even_of_text("err") => Err("invalid digit found in string".into()),
is_even_of_text("这一定会发生错误!") => @ Err(..),
}
}
#[test]
fn flip() {
asserts! {
Result::<usize, usize>::Ok(1)
.flip() => Err(1),
Result::<usize, &str>::Err("value")
.flip() => Ok("value"),
}
}
#[test]
fn collapse() {
asserts! {
Result::<usize, usize>::Ok(1)
.collapse() => 1,
Result::<&str, &str>::Ok("str")
.collapse() => "str",
}
}
}