melodium-common 0.10.1

Common Mélodium elements and traits
Documentation
#[derive(Debug, Clone)]
pub enum Status<S, F, E> {
    Success { success: S, errors: Vec<E> },
    Failure { failure: F, errors: Vec<E> },
}

impl<S, F, E> Status<S, F, E> {
    pub fn new_success(success: S) -> Self {
        Self::Success {
            success,
            errors: Vec::new(),
        }
    }

    pub fn new_failure(failure: F) -> Self {
        Self::Failure {
            failure,
            errors: Vec::new(),
        }
    }

    pub const fn success(&self) -> Option<&S> {
        match self {
            Status::Success { success, errors: _ } => Some(success),
            Status::Failure {
                failure: _,
                errors: _,
            } => None,
        }
    }

    pub fn success_mut(&mut self) -> Option<&mut S> {
        match self {
            Status::Success { success, errors: _ } => Some(success),
            Status::Failure {
                failure: _,
                errors: _,
            } => None,
        }
    }

    pub fn to_success(self) -> Option<S> {
        match self {
            Status::Success { success, errors: _ } => Some(success),
            Status::Failure {
                failure: _,
                errors: _,
            } => None,
        }
    }

    pub fn is_success(&self) -> bool {
        match self {
            Status::Success {
                success: _,
                errors: _,
            } => true,
            Status::Failure {
                failure: _,
                errors: _,
            } => false,
        }
    }

    pub const fn failure(&self) -> Option<&F> {
        match self {
            Status::Success {
                success: _,
                errors: _,
            } => None,
            Status::Failure { failure, errors: _ } => Some(failure),
        }
    }

    pub fn failure_mut(&mut self) -> Option<&mut F> {
        match self {
            Status::Success {
                success: _,
                errors: _,
            } => None,
            Status::Failure { failure, errors: _ } => Some(failure),
        }
    }

    pub fn to_failure(self) -> Option<F> {
        match self {
            Status::Success {
                success: _,
                errors: _,
            } => None,
            Status::Failure { failure, errors: _ } => Some(failure),
        }
    }

    pub fn is_failure(&self) -> bool {
        match self {
            Status::Success {
                success: _,
                errors: _,
            } => false,
            Status::Failure {
                failure: _,
                errors: _,
            } => true,
        }
    }

    pub const fn errors(&self) -> &Vec<E> {
        match self {
            Status::Success { success: _, errors } => errors,
            Status::Failure { failure: _, errors } => errors,
        }
    }

    pub fn errors_mut(&mut self) -> &mut Vec<E> {
        match self {
            Status::Success { success: _, errors } => errors,
            Status::Failure { failure: _, errors } => errors,
        }
    }

    pub fn has_errors(&self) -> bool {
        !self.errors().is_empty()
    }

    pub const fn as_result(&self) -> Result<&S, &F> {
        match self {
            Status::Success { success, errors: _ } => Ok(&success),
            Status::Failure { failure, errors: _ } => Err(&failure),
        }
    }

    pub fn into_result(self) -> Result<S, F> {
        match self {
            Status::Success { success, errors: _ } => Ok(success),
            Status::Failure { failure, errors: _ } => Err(failure),
        }
    }

    pub fn merge<T>(&mut self, status: Status<T, F, E>) -> Option<T> {
        match status {
            Status::Success {
                success,
                mut errors,
            } => {
                self.errors_mut().append(&mut errors);
                Some(success)
            }
            Status::Failure {
                failure,
                mut errors,
            } => {
                self.errors_mut().append(&mut errors);
                let mut errors = Vec::new();
                errors.append(self.errors_mut());
                *self = Self::Failure { failure, errors };
                None
            }
        }
    }

    pub fn and<T>(self, mut status: Status<T, F, E>) -> Status<T, F, E> {
        match self {
            Status::Success {
                success: _,
                errors: mut errors_self,
            } => match status {
                Status::Success {
                    success,
                    mut errors,
                } => {
                    errors_self.append(&mut errors);
                    Status::Success {
                        success,
                        errors: errors_self,
                    }
                }
                Status::Failure {
                    failure,
                    mut errors,
                } => {
                    errors_self.append(&mut errors);
                    Status::Failure {
                        failure,
                        errors: errors_self,
                    }
                }
            },
            Status::Failure {
                failure: failure_self,
                errors: mut errors_self,
            } => {
                errors_self.append(status.errors_mut());
                match status {
                    Status::Success {
                        success: _,
                        errors: _,
                    } => Status::Failure {
                        failure: failure_self,
                        errors: errors_self,
                    },
                    Status::Failure { failure, errors: _ } => Status::Failure {
                        failure,
                        errors: errors_self,
                    },
                }
            }
        }
    }

    pub fn and_then<T, G>(self, op: G) -> Status<T, F, E>
    where
        G: FnOnce(S) -> Status<T, F, E>,
    {
        match self {
            Status::Success {
                success,
                errors: mut errors_self,
            } => {
                let other = op(success);
                match other {
                    Status::Success {
                        success,
                        mut errors,
                    } => {
                        errors_self.append(&mut errors);
                        Status::Success {
                            success,
                            errors: errors_self,
                        }
                    }
                    Status::Failure {
                        failure,
                        mut errors,
                    } => {
                        errors_self.append(&mut errors);
                        Status::Failure {
                            failure,
                            errors: errors_self,
                        }
                    }
                }
            }
            Status::Failure { failure, errors } => Status::Failure { failure, errors },
        }
    }

    pub fn from<T, G, H>(value: Status<T, G, H>) -> Self
    where
        S: From<T>,
        F: From<G>,
        E: From<H>,
    {
        match value {
            Status::Success { success, errors } => Status::Success {
                success: S::from(success),
                errors: errors.into_iter().map(|e| E::from(e)).collect(),
            },
            Status::Failure { failure, errors } => Status::Failure {
                failure: F::from(failure),
                errors: errors.into_iter().map(|e| E::from(e)).collect(),
            },
        }
    }
}

impl<S, E> Status<S, E, E> {
    pub fn convert_failure_errors<F, G>(self, op: G) -> Status<S, F, F>
    where
        G: Fn(E) -> F,
    {
        match self {
            Status::Success { success, errors } => Status::Success {
                success,
                errors: errors.into_iter().map(op).collect(),
            },
            Status::Failure { failure, errors } => Status::Failure {
                failure: op(failure),
                errors: errors.into_iter().map(op).collect(),
            },
        }
    }

    pub fn and_degrade_failure<T>(self, mut status: Status<T, E, E>) -> Status<T, E, E> {
        match self {
            Status::Success {
                success: _,
                errors: mut errors_self,
            } => match status {
                Status::Success {
                    success,
                    mut errors,
                } => {
                    errors_self.append(&mut errors);
                    Status::Success {
                        success,
                        errors: errors_self,
                    }
                }
                Status::Failure {
                    failure,
                    mut errors,
                } => {
                    errors_self.append(&mut errors);
                    Status::Failure {
                        failure,
                        errors: errors_self,
                    }
                }
            },
            Status::Failure {
                failure: failure_self,
                errors: mut errors_self,
            } => {
                errors_self.append(status.errors_mut());
                match status {
                    Status::Success {
                        success: _,
                        errors: _,
                    } => Status::Failure {
                        failure: failure_self,
                        errors: errors_self,
                    },
                    Status::Failure { failure, errors: _ } => {
                        errors_self.push(failure_self);
                        Status::Failure {
                            failure,
                            errors: errors_self,
                        }
                    }
                }
            }
        }
    }

    pub fn merge_degrade_failure<T>(&mut self, status: Status<T, E, E>) -> Option<T>
    where
        E: Clone,
    {
        match status {
            Status::Success {
                success,
                mut errors,
            } => {
                self.errors_mut().append(&mut errors);
                Some(success)
            }
            Status::Failure {
                failure,
                mut errors,
            } => {
                match self {
                    Status::Success {
                        success: _,
                        errors: former_errors,
                    } => {
                        former_errors.append(&mut errors);
                        let mut self_errors = Vec::new();
                        self_errors.append(former_errors);
                        *self = Self::Failure {
                            failure,
                            errors: self_errors,
                        };
                    }
                    Status::Failure {
                        failure: former_failure,
                        errors: former_errors,
                    } => {
                        former_errors.push(former_failure.clone());
                        former_errors.append(&mut errors);
                        let mut self_errors = Vec::new();
                        self_errors.append(former_errors);
                        *self = Self::Failure {
                            failure,
                            errors: self_errors,
                        };
                    }
                }

                None
            }
        }
    }
}

impl<S, F, E> From<Result<S, F>> for Status<S, F, E> {
    fn from(value: Result<S, F>) -> Self {
        match value {
            Ok(success) => Self::new_success(success),
            Err(failure) => Self::new_failure(failure),
        }
    }
}