use std::convert::Infallible;
pub trait MisconfigurationStrategy {
type Error<E>;
fn fallback<T, E>(
&self,
result: Result<T, E>,
fallback_fn: impl FnOnce(E) -> T,
) -> Result<T, Self::Error<E>>;
fn fallback_opt<T, E>(
&self,
result: Result<T, E>,
fallback_fn: impl FnOnce(E),
) -> Result<Option<T>, Self::Error<E>>;
fn to_anyhow<T, E>(
&self,
result: Result<T, Self::Error<E>>,
) -> Result<T, Self::Error<anyhow::Error>>
where
anyhow::Error: From<E>;
fn map_err<T, E1, E2>(
&self,
result: Result<T, Self::Error<E1>>,
map_err: impl FnOnce(E1) -> E2,
) -> Result<T, Self::Error<E2>>;
}
#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
pub struct UseDefaultStrategy;
impl MisconfigurationStrategy for UseDefaultStrategy {
type Error<E> = Infallible;
fn fallback<T, E>(
&self,
result: Result<T, E>,
fallback_fn: impl FnOnce(E) -> T,
) -> Result<T, Self::Error<E>> {
Ok(result.unwrap_or_else(fallback_fn))
}
fn fallback_opt<T, E>(
&self,
result: Result<T, E>,
fallback_fn: impl FnOnce(E),
) -> Result<Option<T>, Self::Error<E>> {
match result {
Ok(val) => Ok(Some(val)),
Err(e) => {
fallback_fn(e);
Ok(None)
}
}
}
fn to_anyhow<T, E>(
&self,
result: Result<T, Self::Error<E>>,
) -> Result<T, Self::Error<anyhow::Error>>
where
anyhow::Error: From<E>,
{
let Ok(val) = result;
Ok(val)
}
fn map_err<T, E1, E2>(
&self,
result: Result<T, Self::Error<E1>>,
_map_err: impl FnOnce(E1) -> E2,
) -> Result<T, Self::Error<E2>> {
let Ok(val) = result;
Ok(val)
}
}
#[derive(Default, Copy, Clone, Debug, PartialEq, Eq)]
pub struct FallibleStrategy;
impl MisconfigurationStrategy for FallibleStrategy {
type Error<E> = E;
fn fallback<T, E>(
&self,
result: Result<T, E>,
_fallback_fn: impl FnOnce(E) -> T,
) -> Result<T, Self::Error<E>> {
result
}
fn fallback_opt<T, E>(
&self,
result: Result<T, E>,
_fallback_fn: impl FnOnce(E),
) -> Result<Option<T>, Self::Error<E>> {
result.map(Some)
}
fn to_anyhow<T, E>(
&self,
result: Result<T, Self::Error<E>>,
) -> Result<T, Self::Error<anyhow::Error>>
where
anyhow::Error: From<E>,
{
Ok(result?)
}
fn map_err<T, E1, E2>(
&self,
result: Result<T, Self::Error<E1>>,
map_err: impl FnOnce(E1) -> E2,
) -> Result<T, Self::Error<E2>> {
result.map_err(map_err)
}
}