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 | |