| 1 | //! `option-operations` provides traits and auto-implementations to |
| 2 | //! improve arithmetic operations usability when dealing with `Option`s. |
| 3 | //! |
| 4 | //! # Example |
| 5 | //! |
| 6 | //! Dealing with two `Option`s, can lead to verbose expressions: |
| 7 | //! |
| 8 | //! ``` |
| 9 | //! let lhs = Some(1u64); |
| 10 | //! let rhs = Some(u64::MAX); |
| 11 | //! |
| 12 | //! assert_eq!( |
| 13 | //! lhs.zip(rhs).map(|(lhs, rhs)| lhs.saturating_add(rhs)), |
| 14 | //! Some(u64::MAX), |
| 15 | //! ); |
| 16 | //! ``` |
| 17 | //! |
| 18 | //! Thanks to the trait [`OptionSaturatingAdd`] we can write: |
| 19 | //! |
| 20 | //! ``` |
| 21 | //! # use option_operations::{Error, OptionSaturatingAdd}; |
| 22 | //! # let lhs = Some(1u64); |
| 23 | //! # let rhs = Some(u64::MAX); |
| 24 | //! assert_eq!( |
| 25 | //! lhs.opt_saturating_add(rhs), |
| 26 | //! Some(u64::MAX), |
| 27 | //! ); |
| 28 | //! ``` |
| 29 | //! |
| 30 | //! The trait can also be used with the inner type: |
| 31 | //! |
| 32 | //! ``` |
| 33 | //! # use option_operations::{Error, OptionSaturatingAdd}; |
| 34 | //! # let lhs = Some(1u64); |
| 35 | //! # let rhs = Some(u64::MAX); |
| 36 | //! assert_eq!( |
| 37 | //! lhs.opt_saturating_add(u64::MAX), |
| 38 | //! Some(u64::MAX), |
| 39 | //! ); |
| 40 | //! |
| 41 | //! assert_eq!( |
| 42 | //! 1.opt_saturating_add(rhs), |
| 43 | //! Some(u64::MAX), |
| 44 | //! ); |
| 45 | //! ``` |
| 46 | //! |
| 47 | //! # Alternative to `PartialOrd` for `Option<T>` |
| 48 | //! |
| 49 | //! Another purpose is to workaround the `PartiaOrd` implementation |
| 50 | //! for `Option<T>`, which uses the declaration order of the variants |
| 51 | //! for `Option`. `None` appearing before `Some(_)`, it results in |
| 52 | //! the following behavior: |
| 53 | //! |
| 54 | //! ``` |
| 55 | //! # use core::cmp::Ordering; |
| 56 | //! let some_0 = Some(0); |
| 57 | //! let none: Option<u64> = None; |
| 58 | //! |
| 59 | //! assert_eq!(none.partial_cmp(&some_0), Some(Ordering::Less)); |
| 60 | //! assert_eq!(some_0.partial_cmp(&none), Some(Ordering::Greater)); |
| 61 | //! ``` |
| 62 | //! |
| 63 | //! In some cases, we might consider that `None` reflects a value which |
| 64 | //! is not defined and thus can not be compared with `Some(_)`. |
| 65 | //! |
| 66 | //! ``` |
| 67 | //! # use option_operations::{OptionOperations, OptionOrd}; |
| 68 | //! # let some_0 = Some(0); |
| 69 | //! # let none: Option<u64> = None; |
| 70 | //! assert_eq!(none.opt_cmp(&some_0), None); |
| 71 | //! assert_eq!(some_0.opt_cmp(&none), None); |
| 72 | //! ``` |
| 73 | //! |
| 74 | //! Of course, this is consistent with other usual comparisons: |
| 75 | //! |
| 76 | //! ``` rust |
| 77 | //! # use option_operations::{OptionOperations, OptionOrd, OptionMinMax}; |
| 78 | //! # let some_0 = Some(0); |
| 79 | //! # let none: Option<u64> = None; |
| 80 | //! assert_eq!(none.opt_lt(&some_0), None); |
| 81 | //! assert_eq!(none.opt_min(some_0), None); |
| 82 | //! ``` |
| 83 | |
| 84 | #![forbid (unsafe_code)] |
| 85 | #![cfg_attr (not(feature = "std" ), no_std)] |
| 86 | |
| 87 | /// Trait for inner types participating in `option-operations`. |
| 88 | /// |
| 89 | /// The purpose of this trait is twofold: |
| 90 | /// |
| 91 | /// - Auto-implement various `Option*` traits such as `OptionOrd`. |
| 92 | /// - Prevent some conflicting auto-implementation of traits on |
| 93 | /// `Option<T>`. |
| 94 | pub trait OptionOperations {} |
| 95 | |
| 96 | impl<T: OptionOperations> OptionOperations for &T {} |
| 97 | impl<T: OptionOperations> OptionOperations for &mut T {} |
| 98 | |
| 99 | #[macro_use ] |
| 100 | mod macros; |
| 101 | |
| 102 | impl_for_all!(OptionOperations); |
| 103 | |
| 104 | pub mod add; |
| 105 | pub use add::{ |
| 106 | OptionAdd, OptionAddAssign, OptionCheckedAdd, OptionOverflowingAdd, OptionSaturatingAdd, |
| 107 | OptionWrappingAdd, |
| 108 | }; |
| 109 | |
| 110 | pub mod error; |
| 111 | pub use error::Error; |
| 112 | |
| 113 | pub mod div; |
| 114 | pub use div::{ |
| 115 | OptionCheckedDiv, OptionDiv, OptionDivAssign, OptionOverflowingDiv, OptionWrappingDiv, |
| 116 | }; |
| 117 | |
| 118 | pub mod eq; |
| 119 | pub use eq::OptionEq; |
| 120 | |
| 121 | pub mod min_max; |
| 122 | pub use min_max::OptionMinMax; |
| 123 | |
| 124 | pub mod mul; |
| 125 | pub use mul::{ |
| 126 | OptionCheckedMul, OptionMul, OptionMulAssign, OptionOverflowingMul, OptionSaturatingMul, |
| 127 | OptionWrappingMul, |
| 128 | }; |
| 129 | |
| 130 | pub mod ord; |
| 131 | pub use ord::OptionOrd; |
| 132 | |
| 133 | pub mod rem; |
| 134 | pub use rem::{ |
| 135 | OptionCheckedRem, OptionOverflowingRem, OptionRem, OptionRemAssign, OptionWrappingRem, |
| 136 | }; |
| 137 | |
| 138 | pub mod sub; |
| 139 | pub use sub::{ |
| 140 | OptionCheckedSub, OptionOverflowingSub, OptionSaturatingSub, OptionSub, OptionSubAssign, |
| 141 | OptionWrappingSub, |
| 142 | }; |
| 143 | |
| 144 | pub mod prelude { |
| 145 | pub use crate::add::{ |
| 146 | OptionAdd, OptionAddAssign, OptionCheckedAdd, OptionOverflowingAdd, OptionSaturatingAdd, |
| 147 | OptionWrappingAdd, |
| 148 | }; |
| 149 | pub use crate::div::{ |
| 150 | OptionCheckedDiv, OptionDiv, OptionDivAssign, OptionOverflowingDiv, OptionWrappingDiv, |
| 151 | }; |
| 152 | pub use crate::eq::OptionEq; |
| 153 | pub use crate::min_max::OptionMinMax; |
| 154 | pub use crate::mul::{ |
| 155 | OptionCheckedMul, OptionMul, OptionMulAssign, OptionOverflowingMul, OptionSaturatingMul, |
| 156 | OptionWrappingMul, |
| 157 | }; |
| 158 | pub use crate::ord::OptionOrd; |
| 159 | pub use crate::rem::{ |
| 160 | OptionCheckedRem, OptionOverflowingRem, OptionRem, OptionRemAssign, OptionWrappingRem, |
| 161 | }; |
| 162 | pub use crate::sub::{ |
| 163 | OptionCheckedSub, OptionOverflowingSub, OptionSaturatingSub, OptionSub, OptionSubAssign, |
| 164 | OptionWrappingSub, |
| 165 | }; |
| 166 | pub use crate::OptionOperations; |
| 167 | } |
| 168 | |