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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
//! `option-operations` provides traits and auto-implementations to
//! improve arithmetic operations usability when dealing with `Option`s.
//!
//! # Example
//!
//! Dealing with two `Option`s, can lead to verbose expressions:
//!
//! ```
//! let lhs = Some(1u64);
//! let rhs = Some(u64::MAX);
//!
//! assert_eq!(
//!     lhs.zip(rhs).map(|(lhs, rhs)| lhs.saturating_add(rhs)),
//!     Some(u64::MAX),
//! );
//! ```
//!
//! Thanks to the trait [`OptionSaturatingAdd`] we can write:
//!
//! ```
//! # use option_operations::{Error, OptionSaturatingAdd};
//! # let lhs = Some(1u64);
//! # let rhs = Some(u64::MAX);
//! assert_eq!(
//!     lhs.opt_saturating_add(rhs),
//!     Some(u64::MAX),
//! );
//! ```
//!
//! The trait can also be used with the inner type:
//!
//! ```
//! # use option_operations::{Error, OptionSaturatingAdd};
//! # let lhs = Some(1u64);
//! # let rhs = Some(u64::MAX);
//! assert_eq!(
//!     lhs.opt_saturating_add(u64::MAX),
//!     Some(u64::MAX),
//! );
//!
//! assert_eq!(
//!     1.opt_saturating_add(rhs),
//!     Some(u64::MAX),
//! );
//! ```
//!
//! # Alternative to `PartialOrd` for `Option<T>`
//!
//! Another purpose is to workaround the `PartiaOrd` implementation
//! for `Option<T>`, which uses the declaration order of the variants
//! for `Option`. `None` appearing before `Some(_)`, it results in
//! the following behavior:
//!
//! ```
//! # use core::cmp::Ordering;
//! let some_0 = Some(0);
//! let none: Option<u64> = None;
//!
//! assert_eq!(none.partial_cmp(&some_0), Some(Ordering::Less));
//! assert_eq!(some_0.partial_cmp(&none), Some(Ordering::Greater));
//! ```
//!
//! In some cases, we might consider that `None` reflects a value which
//! is not defined and thus can not be compared with `Some(_)`.
//!
//! ```
//! # use option_operations::{OptionOperations, OptionOrd};
//! # let some_0 = Some(0);
//! # let none: Option<u64> = None;
//! assert_eq!(none.opt_cmp(&some_0), None);
//! assert_eq!(some_0.opt_cmp(&none), None);
//! ```
//!
//! Of course, this is consistent with other usual comparisons:
//!
//! ``` rust
//! # use option_operations::{OptionOperations, OptionOrd, OptionMinMax};
//! # let some_0 = Some(0);
//! # let none: Option<u64> = None;
//! assert_eq!(none.opt_lt(&some_0), None);
//! assert_eq!(none.opt_min(some_0), None);
//! ```

#![forbid(unsafe_code)]
#![cfg_attr(not(feature = "std"), no_std)]

/// Trait for inner types participating in `option-operations`.
///
/// The purpose of this trait is twofold:
///
/// - Auto-implement various `Option*` traits such as `OptionOrd`.
/// - Prevent some conflicting auto-implementation of traits on
///   `Option<T>`.
pub trait OptionOperations {}

impl<T: OptionOperations> OptionOperations for &T {}
impl<T: OptionOperations> OptionOperations for &mut T {}

#[macro_use]
mod macros;

impl_for_all!(OptionOperations);

pub mod add;
pub use add::{
    OptionAdd, OptionAddAssign, OptionCheckedAdd, OptionOverflowingAdd, OptionSaturatingAdd,
    OptionWrappingAdd,
};

pub mod error;
pub use error::Error;

pub mod div;
pub use div::{
    OptionCheckedDiv, OptionDiv, OptionDivAssign, OptionOverflowingDiv, OptionWrappingDiv,
};

pub mod eq;
pub use eq::OptionEq;

pub mod min_max;
pub use min_max::OptionMinMax;

pub mod mul;
pub use mul::{
    OptionCheckedMul, OptionMul, OptionMulAssign, OptionOverflowingMul, OptionSaturatingMul,
    OptionWrappingMul,
};

pub mod ord;
pub use ord::OptionOrd;

pub mod rem;
pub use rem::{
    OptionCheckedRem, OptionOverflowingRem, OptionRem, OptionRemAssign, OptionWrappingRem,
};

pub mod sub;
pub use sub::{
    OptionCheckedSub, OptionOverflowingSub, OptionSaturatingSub, OptionSub, OptionSubAssign,
    OptionWrappingSub,
};

pub mod prelude {
    pub use crate::add::{
        OptionAdd, OptionAddAssign, OptionCheckedAdd, OptionOverflowingAdd, OptionSaturatingAdd,
        OptionWrappingAdd,
    };
    pub use crate::div::{
        OptionCheckedDiv, OptionDiv, OptionDivAssign, OptionOverflowingDiv, OptionWrappingDiv,
    };
    pub use crate::eq::OptionEq;
    pub use crate::min_max::OptionMinMax;
    pub use crate::mul::{
        OptionCheckedMul, OptionMul, OptionMulAssign, OptionOverflowingMul, OptionSaturatingMul,
        OptionWrappingMul,
    };
    pub use crate::ord::OptionOrd;
    pub use crate::rem::{
        OptionCheckedRem, OptionOverflowingRem, OptionRem, OptionRemAssign, OptionWrappingRem,
    };
    pub use crate::sub::{
        OptionCheckedSub, OptionOverflowingSub, OptionSaturatingSub, OptionSub, OptionSubAssign,
        OptionWrappingSub,
    };
    pub use crate::OptionOperations;
}