1#![cfg_attr(not(test), no_std)]
2#![forbid(unsafe_code)]
3#![warn(missing_docs)]
4
5use core::cmp::{self, Eq, Ord, PartialEq, PartialOrd};
75use core::fmt::{self, Display, Formatter};
76use core::ops;
77
78#[allow(non_upper_case_globals)] pub const Zero: Zero = Zero::Zero;
81
82#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
84pub enum Zero {
85 Zero = 0,
88}
89
90impl<T> ops::Add<T> for Zero {
91 type Output = T;
92 fn add(self, other: T) -> T { other }
93}
94
95impl<T> ops::Mul<T> for Zero {
96 type Output = Zero;
97 fn mul(self, _: T) -> Zero { Zero }
98}
99
100impl<T> ops::BitOr<T> for Zero {
101 type Output = T;
102 fn bitor(self, other: T) -> T { other }
103}
104
105impl<T> ops::BitAnd<T> for Zero {
106 type Output = Zero;
107 fn bitand(self, _: T) -> Zero { Zero }
108}
109
110impl Display for Zero {
111 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
112 <u8 as Display>::fmt(&0, f)
113 }
114}
115
116#[allow(non_upper_case_globals)] pub const One: One = One::One;
119
120#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
122pub enum One {
123 One = 1,
126}
127
128impl<T: ops::Add<One>> ops::Add<T> for One {
129 type Output = T::Output;
130 fn add(self, other: T) -> Self::Output {
131 other + self
132 }
133}
134
135impl<T> ops::Mul<T> for One {
136 type Output = T;
137 fn mul(self, other: T) -> T { other }
138}
139
140impl Display for One {
141 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
142 <u8 as Display>::fmt(&1, f)
143 }
144}
145
146macro_rules! impl_math_identities {
147 ($($trait:ident/$method:ident: $lhs:ident $rhs:ident -> $out:ident,)+) => {$(
148 impl ops::$trait<$rhs> for $lhs {
149 type Output = $out;
150 fn $method(self, _: $rhs) -> $out { $out }
151 }
152 )+};
153}
154
155impl_math_identities!{
156 Sub/sub: Zero Zero -> Zero,
159 Sub/sub: One Zero -> One,
160 Sub/sub: One One -> Zero,
161 Div/div: Zero One -> Zero,
164 Div/div: One One -> One,
165 Rem/rem: Zero One -> Zero,
166 Rem/rem: One One -> Zero,
167
168 BitAnd/bitand: One Zero -> Zero,
170 BitAnd/bitand: One One -> One,
171 BitOr/bitor: One Zero -> One,
173 BitOr/bitor: One One -> One,
174 BitXor/bitxor: Zero Zero -> Zero,
175 BitXor/bitxor: Zero One -> One,
176 BitXor/bitxor: One Zero -> One,
177 BitXor/bitxor: One One -> Zero,
178 Shl/shl: Zero Zero -> Zero,
179 Shl/shl: Zero One -> Zero,
180 Shl/shl: One Zero -> One,
181 Shr/shr: Zero Zero -> Zero,
182 Shr/shr: One Zero -> One,
183 Shr/shr: Zero One -> Zero,
184 Shr/shr: One One -> Zero,
185}
186
187macro_rules! impl_for_integer {
188 ($($t:ty,)+) => {$(
189 impl From<Zero> for $t {
190 fn from(_: Zero) -> $t { 0 }
191 }
192 impl From<One> for $t {
193 fn from(_: One) -> $t { 1 }
194 }
195
196 impl TryFrom<$t> for Zero {
197 type Error = core::num::TryFromIntError;
198 fn try_from(other: $t) -> Result<Zero, Self::Error> {
199 if other == 0 {
200 Ok(Zero)
201 } else {
202 u8::try_from(-1).map(|_| unreachable!())
203 }
204 }
205 }
206 impl TryFrom<$t> for One {
207 type Error = core::num::TryFromIntError;
208 fn try_from(other: $t) -> Result<One, Self::Error> {
209 if other == 1 {
210 Ok(One)
211 } else {
212 u8::try_from(-1).map(|_| unreachable!())
213 }
214 }
215 }
216
217 impl PartialEq<$t> for Zero {
218 fn eq(&self, other: &$t) -> bool {
219 *other == 0
220 }
221 }
222 impl PartialEq<$t> for One {
223 fn eq(&self, other: &$t) -> bool {
224 *other == 1
225 }
226 }
227
228 impl PartialEq<Zero> for $t {
229 fn eq(&self, other: &Zero) -> bool {
230 *other == *self
231 }
232 }
233 impl PartialEq<One> for $t {
234 fn eq(&self, other: &One) -> bool {
235 *other == *self
236 }
237 }
238
239 impl PartialOrd<$t> for Zero {
240 fn partial_cmp(&self, other: &$t) -> Option<cmp::Ordering> {
241 <$t as PartialOrd>::partial_cmp(&0, other)
242 }
243 }
244 impl PartialOrd<$t> for One {
245 fn partial_cmp(&self, other: &$t) -> Option<cmp::Ordering> {
246 <$t as PartialOrd>::partial_cmp(&1, other)
247 }
248 }
249
250 impl PartialOrd<Zero> for $t {
251 fn partial_cmp(&self, _other: &Zero) -> Option<cmp::Ordering> {
252 <$t as PartialOrd>::partial_cmp(self, &0)
253 }
254 }
255 impl PartialOrd<One> for $t {
256 fn partial_cmp(&self, _other: &One) -> Option<cmp::Ordering> {
257 <$t as PartialOrd>::partial_cmp(self, &1)
258 }
259 }
260
261 impl ops::Add<Zero> for $t {
262 type Output = $t;
263 fn add(self, _: Zero) -> $t {
264 self + 0
265 }
266 }
267 impl ops::Add<One> for $t {
268 type Output = $t;
269 fn add(self, _: One) -> $t {
270 self + 1
271 }
272 }
273 )+};
274}
275
276impl_for_integer!{
277 i8, i16, i32, i64, i128, isize,
278 u8, u16, u32, u64, u128, usize,
279}
280
281macro_rules! impl_for_nonzero_integer {
282 ($($t:ty,)+) => {$(
283 #[allow(unused_imports)]
284 use core::num::*;
285
286 impl From<One> for $t {
287 fn from(_: One) -> $t { <$t>::new(1).unwrap() }
288 }
289
290 impl TryFrom<$t> for One {
291 type Error = TryFromIntError;
292 fn try_from(other: $t) -> Result<One, Self::Error> {
293 if other.get() == 1 {
294 Ok(One)
295 } else {
296 u8::try_from(-1).map(|_| unreachable!())
297 }
298 }
299 }
300 )+};
301}
302
303impl_for_nonzero_integer!{
304 NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize,
305 NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
306}
307
308impl ops::Neg for Zero {
309 type Output = Zero;
310 fn neg(self) -> Zero { Zero }
311}
312
313#[cfg(test)]
314mod tests {
315 use super::*;
316
317 #[test]
318 fn some_basics() {
319 assert_eq!(std::mem::size_of::<Zero>(), 0);
320 assert_eq!(std::mem::size_of::<One>(), 0);
321
322 assert_eq!(Zero as i8, 0);
323 assert_eq!(Zero as u128, 0);
324 assert_eq!(One as u8, 1);
325 assert_eq!(One as i128, 1);
326
327 assert_eq!(Zero + Zero, Zero);
328 assert_eq!(One * One, One);
329 }
330}