1use std::fmt::Display;
4
5pub trait OptionExt<T> {
7 fn context(self, msg: impl Display) -> anyhow::Result<T>;
9
10 fn with_context<F, M>(self, f: F) -> anyhow::Result<T>
12 where
13 F: FnOnce() -> M,
14 M: Display;
15}
16
17impl<T> OptionExt<T> for Option<T> {
18 fn context(self, msg: impl Display) -> anyhow::Result<T> {
19 self.ok_or_else(|| anyhow::anyhow!("{}", msg))
20 }
21
22 fn with_context<F, M>(self, f: F) -> anyhow::Result<T>
23 where
24 F: FnOnce() -> M,
25 M: Display,
26 {
27 self.ok_or_else(|| anyhow::anyhow!("{}", f()))
28 }
29}
30
31#[cfg(test)]
34mod tests {
35 use super::*;
36
37 #[test]
38 fn none_becomes_error() {
39 let r: anyhow::Result<i32> = None::<i32>.context("missing value");
40 assert!(r.is_err());
41 assert_eq!(r.unwrap_err().to_string(), "missing value");
42 }
43
44 #[test]
45 fn some_passes_through() {
46 let r: anyhow::Result<i32> = Some(42).context("unreachable");
47 assert_eq!(r.unwrap(), 42);
48 }
49}