1pub type PartialResult<T, F, E> = Result<PartialSuccess<T, F>, E>;
44
45pub trait PartialResultExt<T, F, E> {
47 fn partial_success(value: T, failure: F) -> Self;
49}
50
51impl<T, F, E> PartialResultExt<T, F, E> for PartialResult<T, F, E> {
52 fn partial_success(value: T, failure: F) -> Self {
53 Ok(PartialSuccess::partial(value, failure))
54 }
55}
56
57#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
59pub struct PartialSuccess<T, F> {
60 pub value: T,
62 pub failure: Option<F>,
64}
65
66impl<T, F> PartialSuccess<T, F> {
67 pub fn new(value: T, failure: Option<F>) -> Self {
69 Self {
70 value,
71 failure,
72 }
73 }
74
75 pub fn success(value: T) -> Self {
77 Self::new(value, None)
78 }
79
80 pub fn partial(value: T, failure: F) -> Self {
82 Self::new(value, Some(failure))
83 }
84
85 pub fn has_failure(&self) -> bool {
87 self.failure.is_some()
88 }
89
90 pub fn to_result(self) -> Result<T, F> {
92 match self.failure {
93 Some(f) => Err(f),
94 None => Ok(self.value),
95 }
96 }
97
98 pub fn to_ok<E>(self) -> Result<T, E> {
100 Ok(self.value)
101 }
102}
103
104impl<T, F> From<PartialSuccess<T, F>> for Result<T, F> {
105 fn from(partial: PartialSuccess<T, F>) -> Self {
106 partial.to_result()
107 }
108}
109
110#[cfg(test)]
111mod tests {
112 use super::*;
113
114 #[test]
115 fn partial_success_with_failure_has_failure() {
116 let partial = PartialSuccess::partial(42, "Something went wrong");
117
118 assert!(partial.has_failure());
119 }
120
121 #[test]
122 fn partial_success_without_failure_has_no_failure() {
123 let partial = PartialSuccess::<_, ()>::success(42);
124
125 assert!(!partial.has_failure());
126 }
127
128 #[test]
129 fn partial_success_with_failure_to_result_is_err() {
130 let partial = PartialSuccess::partial(42, "Something went wrong");
131
132 assert!(partial.to_result().is_err());
133 }
134
135 #[test]
136 fn partial_success_without_failure_to_result_is_ok() {
137 let partial = PartialSuccess::<_, ()>::success(42);
138
139 assert!(partial.to_result().is_ok());
140 }
141
142 #[test]
143 fn partial_success_with_failure_to_ok_is_ok() {
144 let partial = PartialSuccess::partial(42, "Something went wrong");
145
146 assert!(partial.to_ok::<&str>().is_ok());
147 }
148
149 #[test]
150 fn partial_result_ext_partial_success_creates_partial_success_with_failure() {
151 let partial = PartialResult::<_, _, ()>::partial_success(42, "Something went wrong");
152
153 assert!(partial.is_ok());
154 assert!(partial.unwrap().has_failure());
155 }
156}