optional_transpose/lib.rs
1//! # optional_transpose
2//! A small crate that adds `.transpose()` to `Option<Option<T>>`
3//! It allows you to reversibly swap the inner and outer options in the pair, so that you can use `?` on the inner option
4//!
5//! Example:
6//! ```rust
7//! use optional_transpose::OptionTranspose;
8//!
9//! fn example() -> Option<i32> {
10//! let x: Option<Option<i32>> = Some(None);
11//! let y: Option<i32> = x.transpose()?; // Returns None, as the inner option is None
12//! Some(1)
13//! }
14//!
15//! assert_eq!(example(), None);
16//! ```
17//!
18
19/// Transpose an `Option` of an `Option` into an `Option` of an `Option`.
20pub trait OptionTranspose<T> {
21 /// Reverses the inner and outer `Option`s.
22 /// ``````
23 fn transpose(self) -> Option<Option<T>>;
24}
25
26impl<T> OptionTranspose<T> for Option<Option<T>> {
27 fn transpose(self) -> Option<Option<T>> {
28 match self {
29 Some(Some(x)) => Some(Some(x)),
30 Some(None) => None,
31 _ => Some(None),
32 }
33 }
34}
35
36#[cfg(test)]
37mod tests {
38 use super::*;
39
40 #[test]
41 fn test_transpose() {
42 let x: Option<Option<i32>> = Some(Some(1));
43 assert_eq!(x.transpose(), Some(Some(1)));
44
45 let x: Option<Option<i32>> = Some(None);
46 assert_eq!(x.transpose(), None);
47
48 let x: Option<Option<i32>> = None;
49 assert_eq!(x.transpose(), Some(None));
50 }
51}