Last active
July 5, 2022 14:37
-
-
Save cgwalters/6a3941e83731265957270cbe83dd33e2 to your computer and use it in GitHub Desktop.
try_or_else
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![feature(try_trait_v2)] | |
use anyhow::Result; // 1.0.57 | |
use core::ops::Try; | |
trait TryOrElse<T> { | |
fn try_or_else<R: Try<Output = T>, F: FnOnce() -> R>(self, f: F) -> R; | |
} | |
// Proposed new API for Option https://github.com/rust-lang/libs-team/issues/59 | |
// This would actually use `self` there of course. | |
impl<T> TryOrElse<T> for Option<T> { | |
fn try_or_else<R: Try<Output = T>, F: FnOnce() -> R>(self, f: F) -> R { | |
if let Some(v) = self { | |
Try::from_output(v) | |
} else { | |
f() | |
} | |
} | |
} | |
impl<T, E> TryOrElse<T> for Result<T, E> { | |
fn try_or_else<R: Try<Output = T>, F: FnOnce() -> R>(self, f: F) -> R { | |
match self { | |
Ok(t) => R::from_output(t), | |
Err(_) => f(), | |
} | |
} | |
} | |
#[test] | |
fn test_option() -> Result<()> { | |
let o = Some("foo".to_string()); | |
let n: Option<String> = None; | |
// Tests with Result; https://github.com/rust-lang/libs-team/issues/59 | |
assert_eq!( | |
o.clone().try_or_else(|| std::fs::read_to_string("/"))?, | |
"foo" | |
); | |
assert_eq!( | |
n.clone() | |
.try_or_else(|| -> anyhow::Result<_> { Ok("fallback".to_string()) })?, | |
"fallback" | |
); | |
assert!(n.clone().try_or_else(|| anyhow::bail!("oops")).is_err()); | |
// Tests that replicate or_else https://doc.rust-lang.org/std/option/enum.Option.html#method.or_else | |
assert_eq!( | |
o.clone().try_or_else(|| Some("fallback".to_string())), | |
Some("foo".to_string()) | |
); | |
// Fallback must be lazy | |
assert_eq!( | |
o.clone() | |
.try_or_else(|| -> Option<String> { unreachable!() }), | |
Some("foo".to_string()) | |
); | |
assert_eq!( | |
n.clone().try_or_else(|| Some("fallback".to_string())), | |
Some("fallback".to_string()) | |
); | |
assert_eq!(n.clone().try_or_else(|| None), None); | |
Ok(()) | |
} | |
#[test] | |
fn test_result() -> Result<()> { | |
let s = Ok::<_, std::io::Error>("foo".to_string()); | |
let e = Err(anyhow::anyhow!("Oops")); | |
// Tests with Result; https://github.com/rust-lang/libs-team/issues/59 | |
assert_eq!(s.try_or_else(|| None), Some("foo".to_string())); | |
assert_eq!(e.try_or_else(|| Some("foo")), Some("foo")); | |
Ok(()) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment