#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Warned<T, W> {
pub value: T,
pub warnings: Vec<W>,
}
impl<T, W> Warned<T, W> {
pub fn new(value: T, warnings: impl IntoIterator<Item = W>) -> Self {
Self {
value,
warnings: Vec::from_iter(warnings),
}
}
pub fn unwrap<V>(self, warnings: &mut Vec<V>) -> T
where
W: Into<V>,
{
warnings.extend(self.warnings.into_iter().map(Into::into));
self.value
}
pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Warned<U, W> {
Warned {
value: f(self.value),
warnings: self.warnings,
}
}
pub fn map_warnings<V>(self, f: impl Fn(W) -> V) -> Warned<T, V> {
Warned {
value: self.value,
warnings: self.warnings.into_iter().map(f).collect(),
}
}
pub fn and_then<U>(mut self, f: impl Fn(T) -> Warned<U, W>) -> Warned<U, W> {
Warned::new(f(self.value).unwrap(&mut self.warnings), self.warnings)
}
pub fn into_result(self) -> Result<T, Vec<W>> {
if self.warnings.is_empty() {
Ok(self.value)
} else {
Err(self.warnings)
}
}
pub fn from_result_or_else(src: Result<T, W>, f: impl FnOnce() -> T) -> Self {
match src {
Ok(x) => x.into(),
Err(e) => Self::new(f(), vec![e]),
}
}
pub fn from_result_or(src: Result<T, W>, default: T) -> Self {
Self::from_result_or_else(src, || default)
}
pub fn from_result_or_default(src: Result<T, W>) -> Self
where
T: Default,
{
Self::from_result_or_else(src, T::default)
}
}
impl<T, W> Warned<Option<T>, W> {
pub fn from_result(src: Result<T, W>) -> Self {
match src {
Ok(x) => Self::new(Some(x), vec![]),
Err(e) => Self::new(None, vec![e]),
}
}
}
impl<T, W> std::ops::Deref for Warned<T, W> {
type Target = T;
fn deref(&self) -> &T {
&self.value
}
}
impl<T: Default, W> Default for Warned<T, W> {
fn default() -> Self {
Self::new(T::default(), vec![])
}
}
impl<T, W> From<T> for Warned<T, W> {
fn from(value: T) -> Self {
Self::new(value, vec![])
}
}
impl<T, E> From<Result<T, E>> for Warned<Option<T>, E> {
fn from(result: Result<T, E>) -> Self {
Self::from_result(result)
}
}
impl<T: Default, E> From<Result<T, E>> for Warned<T, E> {
fn from(result: Result<T, E>) -> Self {
match result {
Ok(x) => x.into(),
Err(e) => Self::new(T::default(), vec![e]),
}
}
}
impl<T, W> From<Warned<T, W>> for Result<T, Vec<W>> {
fn from(src: Warned<T, W>) -> Self {
src.into_result()
}
}
impl<T1, T2, W> From<(Warned<T1, W>, Warned<T2, W>)> for Warned<(T1, T2), W> {
fn from((a, b): (Warned<T1, W>, Warned<T2, W>)) -> Self {
Self::new((a.value, b.value), a.warnings.into_iter().chain(b.warnings))
}
}
impl<T, Ts: std::iter::FromIterator<T>, W> std::iter::FromIterator<Warned<T, W>> for Warned<Ts, W> {
fn from_iter<I: IntoIterator<Item = Warned<T, W>>>(iter: I) -> Self {
let mut warnings = vec![];
let value = iter.into_iter().map(|x| x.unwrap(&mut warnings)).collect();
Self { value, warnings }
}
}
impl<T, Ts: std::iter::FromIterator<T>, W> std::iter::FromIterator<Result<T, W>> for Warned<Ts, W> {
fn from_iter<I: IntoIterator<Item = Result<T, W>>>(iter: I) -> Self {
let mut warnings = vec![];
Self {
value: iter
.into_iter()
.filter_map(|item| Warned::from_result(item).unwrap(&mut warnings))
.collect(),
warnings,
}
}
}
pub trait ForceFrom<T>: Sized {
type Warning;
fn force_from(src: T) -> Warned<Self, Self::Warning>;
}
pub trait ForceInto<T> {
type Warning;
fn force_into(self) -> Warned<T, Self::Warning>;
}
impl<T, U: ForceFrom<T>> ForceInto<U> for T {
type Warning = U::Warning;
fn force_into(self) -> Warned<U, Self::Warning> {
U::force_from(self)
}
}
impl<T: Into<U>, U> ForceFrom<T> for U {
type Warning = std::convert::Infallible;
fn force_from(src: T) -> Warned<Self, Self::Warning> {
src.into().into()
}
}