pub type PartialResult<T, F, E> = Result<PartialSuccess<T, F>, E>;
pub trait PartialResultExt<T, F, E> {
fn partial_success(value: T, failure: F) -> Self;
}
impl<T, F, E> PartialResultExt<T, F, E> for PartialResult<T, F, E> {
fn partial_success(value: T, failure: F) -> Self {
Ok(PartialSuccess::partial(value, failure))
}
}
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
pub struct PartialSuccess<T, F> {
pub value: T,
pub failure: Option<F>,
}
impl<T, F> PartialSuccess<T, F> {
pub fn new(value: T, failure: Option<F>) -> Self {
Self {
value,
failure,
}
}
pub fn success(value: T) -> Self {
Self::new(value, None)
}
pub fn partial(value: T, failure: F) -> Self {
Self::new(value, Some(failure))
}
pub fn has_failure(&self) -> bool {
self.failure.is_some()
}
pub fn to_result(self) -> Result<T, F> {
match self.failure {
Some(f) => Err(f),
None => Ok(self.value),
}
}
pub fn to_ok<E>(self) -> Result<T, E> {
Ok(self.value)
}
}
impl<T, F> From<PartialSuccess<T, F>> for Result<T, F> {
fn from(partial: PartialSuccess<T, F>) -> Self {
partial.to_result()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn partial_success_with_failure_has_failure() {
let partial = PartialSuccess::partial(42, "Something went wrong");
assert!(partial.has_failure());
}
#[test]
fn partial_success_without_failure_has_no_failure() {
let partial = PartialSuccess::<_, ()>::success(42);
assert!(!partial.has_failure());
}
#[test]
fn partial_success_with_failure_to_result_is_err() {
let partial = PartialSuccess::partial(42, "Something went wrong");
assert!(partial.to_result().is_err());
}
#[test]
fn partial_success_without_failure_to_result_is_ok() {
let partial = PartialSuccess::<_, ()>::success(42);
assert!(partial.to_result().is_ok());
}
#[test]
fn partial_success_with_failure_to_ok_is_ok() {
let partial = PartialSuccess::partial(42, "Something went wrong");
assert!(partial.to_ok::<&str>().is_ok());
}
#[test]
fn partial_result_ext_partial_success_creates_partial_success_with_failure() {
let partial = PartialResult::<_, _, ()>::partial_success(42, "Something went wrong");
assert!(partial.is_ok());
assert!(partial.unwrap().has_failure());
}
}