try_guard/
lib.rs

1//! The [`guard!`] macro.
2//!
3//! The [`guard!`] macro implements a control-flow sugar that occurs very often in common Rust code:
4//!
5//! ```rust
6//! fn foo(cond: bool) -> Option<i32> {
7//!   if !cond {
8//!     return None;
9//!   }
10//!
11//!   // do something useful
12//!
13//!   Some(42)
14//! }
15//! ```
16//!
17//! This pattern of testing arguments and early-returning with an error is very typical.
18//! Unfortunately, the [`?`] operator doesn’t help us here because we want to early-return on a
19//! boolean value, not an error value.
20//!
21//! A not very idiomatic and weird way to rewrite that:
22//!
23//! ```rust
24//! fn foo(cond: bool) -> Option<i32> {
25//!   if cond { Some(()) } else { None }?;
26//!   Some(42)
27//! }
28//! ```
29//!
30//! This crate provides the [`guard!`] macro — analoguous to the [`guard`] Haskell `Alternative`
31//! function — that helps early-return from a function if a predicate is `false`:
32//!
33//! ```rust
34//! # #![cfg_attr(feature = "test-nightly", feature(try_trait))]
35//! # #[cfg(feature = "test-nightly")] mod lol {
36//! use try_guard::guard;
37//!
38//! fn foo(cond: bool) -> Option<i32> {
39//!   guard!(cond);
40//!   Some(42)
41//! }
42//! # }
43//! ```
44//!
45//! ## Custom guard types
46//!
47//! This crate also allows you to _guard_ to anything that implements [`Try<Error = NoneError>`] or
48//! `From<NoneError>` (nightly only).
49//!
50//! For instance, the following works:
51//!
52//! ```rust
53//! # #![cfg_attr(feature = "test-nightly", feature(try_trait))]
54//! # #[cfg(feature = "test-nightly")] mod lol {
55//! use std::ops::Try;
56//! use std::option::NoneError;
57//! use try_guard::guard;
58//!
59//! #[derive(Clone, Debug, Eq, PartialEq)]
60//! enum MyGuard<T> {
61//!   Just(T),
62//!   Nothing
63//! }
64//!
65//! impl<T> MyGuard<T> {
66//!   fn new(x: T) -> Self {
67//!     MyGuard::Just(x)
68//!   }
69//!
70//!   fn none() -> Self {
71//!     MyGuard::Nothing
72//!   }
73//! }
74//!
75//! impl<T> Try for MyGuard<T> {
76//!   type Ok = T;
77//!
78//!   type Error = NoneError;
79//!
80//!   fn from_error(_: Self::Error) -> Self {
81//!     MyGuard::none()
82//!   }
83//!
84//!   fn from_ok(x: Self::Ok) -> Self {
85//!     MyGuard::new(x)
86//!   }
87//!
88//!   fn into_result(self) -> Result<Self::Ok, Self::Error> {
89//!     match self {
90//!       MyGuard::Just(x) => Ok(x),
91//!       MyGuard::Nothing => Err(NoneError)
92//!     }
93//!   }
94//! }
95//!
96//! fn foo(cond: bool) -> MyGuard<i32> {
97//!   guard!(cond);
98//!   MyGuard::new(42)
99//! }
100//!
101//! fn main() {
102//!   assert_eq!(foo(false), MyGuard::Nothing);
103//! }
104//! # }
105//! ```
106//!
107//! ## More control on the error type
108//!
109//! If you’d rather manipulate the error type when the predicate is false, you might be interested
110//! in the [`verify!`] macro instead. That macro is akin to [`guard!`] but instead doesn’t exit the
111//! current scope: it maps the predicate’s truth to either `Some(())` or `None`, allowing you to
112//! call `Option::ok_or` or whatever error combinator you want to.
113//!
114//! ```rust
115//! use try_guard::verify;
116//!
117//! fn foo(cond: bool) -> Result<u32, String> {
118//!   verify!(cond).ok_or("bad condition".to_owned())?;
119//!   Ok(123)
120//! }
121//! ```
122//!
123//! ## Feature flags
124//!
125//!   - The `test-nightly` feature flag can be used to test nightly-related features that come
126//!     freely and don’t require a nightly build of rustc to compile this crate but require one at
127//!     use site.
128//!
129//! [`guard!`]: guard
130//! [`verify!`]: verify
131//! [`guard`]: http://hackage.haskell.org/package/base-4.12.0.0/docs/Control-Monad.html#v:guard
132//! [`?`]: https://doc.rust-lang.org/std/ops/trait.Try.html
133//! [`Try<Error = NoneError>`]: https://doc.rust-lang.org/std/ops/trait.Try.html
134
135/// The [`guard!`] macro.
136///
137/// [`guard!`]: guard
138#[macro_export]
139macro_rules! guard {
140  ($e:expr) => {
141    if !$e {
142      None?
143    }
144  };
145}
146
147/// A version of [`guard!`] that doesn’t shortcut.
148///
149/// The advantage of this macro over [`guard!`] is to allow you to manipulate the resulting
150/// [`Option`].
151///
152/// [`guard!`]: guard
153#[macro_export]
154macro_rules! verify {
155  ($e:expr) => {
156    if !$e {
157      None
158    } else {
159      Some(())
160    }
161  }
162}