1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use crate::error::{StError, Warning};
use core::convert::TryFrom;
#[derive(Debug, Default)]
#[cfg_attr(feature = "ufmt", derive(ufmt::derive::uDebug))]
#[must_use = "this `Outcome` may contain a warning, which should be handled"]
pub struct Outcome<T> {
value: T,
pub warning: Option<Warning>,
}
impl<T> Outcome<T> {
pub fn new(value: T, warning: Option<Warning>) -> Self {
Self { value, warning }
}
pub fn ok(value: T) -> Self {
Self::new(value, None)
}
pub fn warn(value: T, warning: Warning) -> Self {
Self::new(value, Some(warning))
}
pub fn map<F, U>(self, f: F) -> Outcome<U>
where
F: FnOnce(T) -> U,
{
let Outcome { value, warning } = self;
let value = f(value);
Outcome { value, warning }
}
pub fn ignore_warnings(self, to_ignore: &[Warning]) -> Result<T, Warning> {
match self.warning {
Some(warning) => match to_ignore.iter().any(|&w| warning == w) {
true => Ok(self.value),
false => Err(warning),
},
None => Ok(self.value),
}
}
pub fn ignore_all_warnings(self) -> T {
self.value
}
pub fn err_on_warning(self) -> Result<T, Warning> {
match self.warning {
Some(warning) => Err(warning),
None => Ok(self.value),
}
}
}
impl<T, E> From<Outcome<T>> for Result<Outcome<T>, E> {
fn from(outcome: Outcome<T>) -> Self {
Ok(outcome)
}
}
pub fn from_st(status: i8) -> Result<Outcome<()>, StError> {
if status == 0 {
return Outcome::ok(()).into();
}
let res = Warning::try_from(status).map(|w| Outcome::warn((), w));
if let Ok(outcome) = res {
return Ok(outcome);
}
match StError::try_from(status) {
Ok(err) => return Err(err),
_ => Err(StError::NOT_IMPLEMENTED),
}
}