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
//! Conditionally take a value out of an option. //! //! This crate adds a `take_if` extension method to [`Option`] which conditionally //! takes the value out of an option, leaving `None` in its place if the value was //! taken. The predicate function is only called if the option is `Some`, and //! receives a reference to the option's contents. //! //! If you don't need to take the value conditionally, i.e. you always need to take //! the value, use [`Option::take`] instead. //! //! # Examples //! //! ``` //! use take_if::TakeIf; //! //! let mut maybe_greeting = Some("Hello, World!"); //! //! if let Some(greeting) = maybe_greeting.take_if(|greeting| greeting.starts_with("Hello")) { //! println!(r#"Greeting {:?} starts with "Hello""#, greeting); //! } else { //! println!(r#"There was no greeting, or it didn't start with "Hello""#); //! } //! ``` //! //! [`Option`]: https://doc.rust-lang.org/std/option/enum.Option.html //! [`Option::take`]: https://doc.rust-lang.org/std/option/enum.Option.html#method.take /// Extension trait for `Option<T>` that adds the `take_if` method. /// /// See the [crate-level documentation](./index.html) for more information. pub trait TakeIf { /// The type contained in the `Option`. type Inner; /// Takes value out of the `Option` if `predicate` returns `true`. /// /// See the [crate-level documentation](./index.html) for more information. fn take_if<F: FnOnce(&Self::Inner) -> bool>(&mut self, predicate: F) -> Option<Self::Inner>; } impl<T> TakeIf for Option<T> { type Inner = T; fn take_if<F: FnOnce(&Self::Inner) -> bool>(&mut self, predicate: F) -> Option<Self::Inner> { if self.as_ref().map(predicate).unwrap_or(false) { self.take() } else { None } } } #[cfg(test)] mod tests { use crate::TakeIf; #[test] fn conditional_take() { let mut option = Some(5); assert_eq!(None, option.take_if(|_| false)); assert_eq!(Some(5), option.take_if(|_| true)); assert_eq!(None, option.take_if(|_| true)); } }