1#![forbid(missing_docs)]
57#![cfg_attr(not(feature = "std"), no_std)]
58
59#[derive(Debug, Clone, Copy, PartialEq, Eq)]
61pub struct TryFromIntError(());
62
63#[cfg(feature = "std")]
64impl std::error::Error for TryFromIntError {}
65
66impl core::fmt::Display for TryFromIntError {
67 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
68 "out of range integral type conversion attempted".fmt(fmt)
69 }
70}
71
72impl From<core::num::TryFromIntError> for TryFromIntError {
73 fn from(_: core::num::TryFromIntError) -> Self {
74 Self(())
75 }
76}
77
78impl From<core::convert::Infallible> for TryFromIntError {
79 fn from(never: core::convert::Infallible) -> Self {
80 match never {}
81 }
82}
83
84#[derive(Clone, Debug, PartialEq, Eq)]
86pub struct ParseIntError(());
87
88#[cfg(feature = "std")]
89impl std::error::Error for ParseIntError {}
90
91impl core::fmt::Display for ParseIntError {
92 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
93 "unable to parse integer".fmt(fmt)
94 }
95}
96
97impl From<core::num::ParseIntError> for ParseIntError {
98 fn from(_: core::num::ParseIntError) -> Self {
99 Self(())
100 }
101}
102
103macro_rules! impl_nonmax_fmt {
109 ( ( $( $Trait: ident ),+ ) for $nonmax: ident ) => {
110 $(
111 impl core::fmt::$Trait for $nonmax {
112 #[inline]
113 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
114 core::fmt::$Trait::fmt(&self.get(), f)
115 }
116 }
117 )+
118 };
119}
120
121macro_rules! nonmax {
122 ( common, $nonmax: ident, $non_zero: ident, $primitive: ident ) => {
123 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
125 #[repr(transparent)]
126 pub struct $nonmax(core::num::$non_zero);
127
128 impl $nonmax {
129 #[inline]
132 pub const fn new(value: $primitive) -> Option<Self> {
133 match core::num::$non_zero::new(value ^ $primitive::MAX) {
134 None => None,
135 Some(value) => Some(Self(value)),
136 }
137 }
138
139 #[inline]
146 pub const unsafe fn new_unchecked(value: $primitive) -> Self {
147 let inner = core::num::$non_zero::new_unchecked(value ^ $primitive::MAX);
148 Self(inner)
149 }
150
151 #[inline]
153 pub const fn get(&self) -> $primitive {
154 self.0.get() ^ $primitive::MAX
155 }
156
157 pub const ZERO: $nonmax = unsafe { Self::new_unchecked(0) };
159
160 pub const ONE: $nonmax = unsafe { Self::new_unchecked(1) };
162
163 pub const MAX: $nonmax = unsafe { Self::new_unchecked($primitive::MAX - 1) };
165 }
166
167 impl Default for $nonmax {
168 fn default() -> Self {
169 unsafe { Self::new_unchecked(0) }
170 }
171 }
172
173 impl From<$nonmax> for $primitive {
174 fn from(value: $nonmax) -> Self {
175 value.get()
176 }
177 }
178
179 impl core::convert::TryFrom<$primitive> for $nonmax {
180 type Error = TryFromIntError;
181 fn try_from(value: $primitive) -> Result<Self, Self::Error> {
182 Self::new(value).ok_or(TryFromIntError(()))
183 }
184 }
185
186 impl core::str::FromStr for $nonmax {
187 type Err = ParseIntError;
188 fn from_str(value: &str) -> Result<Self, Self::Err> {
189 Self::new($primitive::from_str(value)?).ok_or(ParseIntError(()))
190 }
191 }
192
193 impl core::cmp::Ord for $nonmax {
194 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
195 self.get().cmp(&other.get())
196 }
197 }
198 impl core::cmp::PartialOrd for $nonmax {
199 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
200 Some(self.cmp(other))
201 }
202 }
203
204 impl core::ops::BitAnd<$nonmax> for $nonmax {
209 type Output = $nonmax;
210 fn bitand(self, rhs: $nonmax) -> Self::Output {
211 unsafe { $nonmax::new_unchecked(self.get() & rhs.get()) }
214 }
215 }
216
217 impl core::ops::BitAndAssign<$nonmax> for $nonmax {
218 fn bitand_assign(&mut self, rhs: $nonmax) {
219 *self = *self & rhs;
220 }
221 }
222
223 impl_nonmax_fmt! {
225 (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $nonmax
226 }
227
228 #[cfg(feature = "serde")]
229 impl serde::Serialize for $nonmax {
230 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
231 where
232 S: serde::Serializer,
233 {
234 self.get().serialize(serializer)
235 }
236 }
237
238 #[cfg(feature = "serde")]
239 impl<'de> serde::Deserialize<'de> for $nonmax {
240 fn deserialize<D>(deserializer: D) -> Result<$nonmax, D::Error>
241 where
242 D: serde::Deserializer<'de>,
243 {
244 let value = $primitive::deserialize(deserializer)?;
245 use core::convert::TryFrom;
246 Self::try_from(value).map_err(serde::de::Error::custom)
247 }
248 }
249
250 #[cfg(test)]
251 mod $primitive {
252 use super::*;
253
254 use core::mem::size_of;
255
256 #[test]
257 fn construct() {
258 let zero = $nonmax::new(0).unwrap();
259 assert_eq!(zero.get(), 0);
260
261 let some = $nonmax::new(19).unwrap();
262 assert_eq!(some.get(), 19);
263
264 let max = $nonmax::new($primitive::MAX);
265 assert_eq!(max, None);
266 }
267
268 #[test]
269 fn sizes_correct() {
270 assert_eq!(size_of::<$primitive>(), size_of::<$nonmax>());
271 assert_eq!(size_of::<$nonmax>(), size_of::<Option<$nonmax>>());
272 }
273
274 #[test]
275 fn convert() {
276 use core::convert::TryFrom;
277 let zero = $nonmax::try_from(0 as $primitive).unwrap();
278 let zero = $primitive::from(zero);
279 assert_eq!(zero, 0);
280
281 $nonmax::try_from($primitive::MAX).unwrap_err();
282 }
283
284 #[test]
285 fn cmp() {
286 let zero = $nonmax::new(0).unwrap();
287 let one = $nonmax::new(1).unwrap();
288 let two = $nonmax::new(2).unwrap();
289 assert!(zero < one);
290 assert!(one < two);
291 assert!(two > one);
292 assert!(one > zero);
293 }
294
295 #[test]
296 fn constants() {
297 let zero = $nonmax::ZERO;
298 let one = $nonmax::ONE;
299 let max = $nonmax::MAX;
300 assert_eq!(zero.get(), 0);
301 assert_eq!(one.get(), 1);
302 assert_eq!(max.get(), $primitive::MAX - 1);
303 }
304
305 #[test]
306 #[cfg(feature = "std")] fn parse() {
308 for value in [0, 19, $primitive::MAX - 1].iter().copied() {
309 let string = value.to_string();
310 let nonmax = string.parse::<$nonmax>().unwrap();
311 assert_eq!(nonmax.get(), value);
312 }
313 $primitive::MAX.to_string().parse::<$nonmax>().unwrap_err();
314 }
315
316 #[test]
317 #[cfg(feature = "std")] fn fmt() {
319 let zero = $nonmax::new(0).unwrap();
320 let some = $nonmax::new(19).unwrap();
321 let max1 = $nonmax::new($primitive::MAX - 1).unwrap();
322 for value in [zero, some, max1].iter().copied() {
323 assert_eq!(format!("{}", value.get()), format!("{}", value)); assert_eq!(format!("{:?}", value.get()), format!("{:?}", value)); assert_eq!(format!("{:b}", value.get()), format!("{:b}", value)); assert_eq!(format!("{:o}", value.get()), format!("{:o}", value)); assert_eq!(format!("{:x}", value.get()), format!("{:x}", value)); assert_eq!(format!("{:X}", value.get()), format!("{:X}", value)); }
330 }
331
332 #[test]
333 #[cfg(feature = "serde")]
334 fn serde() {
335 for &value in [0, 19, $primitive::MAX - 1].iter() {
336 let nonmax_value = $nonmax::new(value).unwrap();
337 let encoded: Vec<u8> = bincode::serialize(&nonmax_value).unwrap();
338 let decoded: $nonmax = bincode::deserialize(&encoded[..]).unwrap();
339 assert_eq!(nonmax_value, decoded);
340 }
341 }
342 }
343 };
344
345 ( signed, $nonmax: ident, $non_zero: ident, $primitive: ident ) => {
346 nonmax!(common, $nonmax, $non_zero, $primitive);
347 };
349
350 ( unsigned, $nonmax: ident, $non_zero: ident, $primitive: ident ) => {
351 nonmax!(common, $nonmax, $non_zero, $primitive);
352
353 impl core::ops::BitAnd<$nonmax> for $primitive {
354 type Output = $nonmax;
355 fn bitand(self, rhs: $nonmax) -> Self::Output {
356 unsafe { $nonmax::new_unchecked(self & rhs.get()) }
359 }
360 }
361
362 impl core::ops::BitAnd<$primitive> for $nonmax {
363 type Output = $nonmax;
364 fn bitand(self, rhs: $primitive) -> Self::Output {
365 unsafe { $nonmax::new_unchecked(self.get() & rhs) }
368 }
369 }
370
371 impl core::ops::BitAndAssign<$primitive> for $nonmax {
372 fn bitand_assign(&mut self, rhs: $primitive) {
373 *self = *self & rhs;
374 }
375 }
376
377 impl core::ops::BitAndAssign<$nonmax> for $primitive {
379 fn bitand_assign(&mut self, rhs: $nonmax) {
380 *self = *self & rhs.get();
381 }
382 }
383 };
384}
385
386nonmax!(signed, NonMaxI8, NonZeroI8, i8);
387nonmax!(signed, NonMaxI16, NonZeroI16, i16);
388nonmax!(signed, NonMaxI32, NonZeroI32, i32);
389nonmax!(signed, NonMaxI64, NonZeroI64, i64);
390nonmax!(signed, NonMaxI128, NonZeroI128, i128);
391nonmax!(signed, NonMaxIsize, NonZeroIsize, isize);
392
393nonmax!(unsigned, NonMaxU8, NonZeroU8, u8);
394nonmax!(unsigned, NonMaxU16, NonZeroU16, u16);
395nonmax!(unsigned, NonMaxU32, NonZeroU32, u32);
396nonmax!(unsigned, NonMaxU64, NonZeroU64, u64);
397nonmax!(unsigned, NonMaxU128, NonZeroU128, u128);
398nonmax!(unsigned, NonMaxUsize, NonZeroUsize, usize);
399
400macro_rules! impl_nonmax_from {
402 ( $small: ty, $large: ty ) => {
403 impl From<$small> for $large {
404 #[inline]
405 fn from(small: $small) -> Self {
406 unsafe { Self::new_unchecked(small.get().into()) }
408 }
409 }
410 };
411}
412
413impl_nonmax_from!(NonMaxU8, NonMaxU16);
415impl_nonmax_from!(NonMaxU8, NonMaxU32);
416impl_nonmax_from!(NonMaxU8, NonMaxU64);
417impl_nonmax_from!(NonMaxU8, NonMaxU128);
418impl_nonmax_from!(NonMaxU8, NonMaxUsize);
419impl_nonmax_from!(NonMaxU16, NonMaxU32);
420impl_nonmax_from!(NonMaxU16, NonMaxU64);
421impl_nonmax_from!(NonMaxU16, NonMaxU128);
422impl_nonmax_from!(NonMaxU16, NonMaxUsize);
423impl_nonmax_from!(NonMaxU32, NonMaxU64);
424impl_nonmax_from!(NonMaxU32, NonMaxU128);
425impl_nonmax_from!(NonMaxU64, NonMaxU128);
426
427impl_nonmax_from!(NonMaxI8, NonMaxI16);
429impl_nonmax_from!(NonMaxI8, NonMaxI32);
430impl_nonmax_from!(NonMaxI8, NonMaxI64);
431impl_nonmax_from!(NonMaxI8, NonMaxI128);
432impl_nonmax_from!(NonMaxI8, NonMaxIsize);
433impl_nonmax_from!(NonMaxI16, NonMaxI32);
434impl_nonmax_from!(NonMaxI16, NonMaxI64);
435impl_nonmax_from!(NonMaxI16, NonMaxI128);
436impl_nonmax_from!(NonMaxI16, NonMaxIsize);
437impl_nonmax_from!(NonMaxI32, NonMaxI64);
438impl_nonmax_from!(NonMaxI32, NonMaxI128);
439impl_nonmax_from!(NonMaxI64, NonMaxI128);
440
441impl_nonmax_from!(NonMaxU8, NonMaxI16);
443impl_nonmax_from!(NonMaxU8, NonMaxI32);
444impl_nonmax_from!(NonMaxU8, NonMaxI64);
445impl_nonmax_from!(NonMaxU8, NonMaxI128);
446impl_nonmax_from!(NonMaxU8, NonMaxIsize);
447impl_nonmax_from!(NonMaxU16, NonMaxI32);
448impl_nonmax_from!(NonMaxU16, NonMaxI64);
449impl_nonmax_from!(NonMaxU16, NonMaxI128);
450impl_nonmax_from!(NonMaxU32, NonMaxI64);
451impl_nonmax_from!(NonMaxU32, NonMaxI128);
452impl_nonmax_from!(NonMaxU64, NonMaxI128);
453
454macro_rules! impl_smaller_from {
456 ( $small: ty, $large: ty ) => {
457 impl From<$small> for $large {
458 #[inline]
459 fn from(small: $small) -> Self {
460 unsafe { Self::new_unchecked(small.into()) }
462 }
463 }
464 };
465}
466
467impl_smaller_from!(u8, NonMaxU16);
469impl_smaller_from!(u8, NonMaxU32);
470impl_smaller_from!(u8, NonMaxU64);
471impl_smaller_from!(u8, NonMaxU128);
472impl_smaller_from!(u8, NonMaxUsize);
473impl_smaller_from!(u16, NonMaxU32);
474impl_smaller_from!(u16, NonMaxU64);
475impl_smaller_from!(u16, NonMaxU128);
476impl_smaller_from!(u16, NonMaxUsize);
477impl_smaller_from!(u32, NonMaxU64);
478impl_smaller_from!(u32, NonMaxU128);
479impl_smaller_from!(u64, NonMaxU128);
480
481impl_smaller_from!(i8, NonMaxI16);
483impl_smaller_from!(i8, NonMaxI32);
484impl_smaller_from!(i8, NonMaxI64);
485impl_smaller_from!(i8, NonMaxI128);
486impl_smaller_from!(i8, NonMaxIsize);
487impl_smaller_from!(i16, NonMaxI32);
488impl_smaller_from!(i16, NonMaxI64);
489impl_smaller_from!(i16, NonMaxI128);
490impl_smaller_from!(i16, NonMaxIsize);
491impl_smaller_from!(i32, NonMaxI64);
492impl_smaller_from!(i32, NonMaxI128);
493impl_smaller_from!(i64, NonMaxI128);
494
495impl_smaller_from!(u8, NonMaxI16);
497impl_smaller_from!(u8, NonMaxI32);
498impl_smaller_from!(u8, NonMaxI64);
499impl_smaller_from!(u8, NonMaxI128);
500impl_smaller_from!(u8, NonMaxIsize);
501impl_smaller_from!(u16, NonMaxI32);
502impl_smaller_from!(u16, NonMaxI64);
503impl_smaller_from!(u16, NonMaxI128);
504impl_smaller_from!(u32, NonMaxI64);
505impl_smaller_from!(u32, NonMaxI128);
506impl_smaller_from!(u64, NonMaxI128);
507
508#[cfg(test)]
509mod ops {
510 use super::*;
511
512 #[test]
513 fn bitand_unsigned() {
514 for left in 0..=u8::MAX {
515 let nmleft = NonMaxU8::new(left);
516 for right in 0..=u8::MAX {
517 let nmright = NonMaxU8::new(right);
518 let vanilla = left & right;
519
520 if let (Some(nmleft), Some(nmright)) = (nmleft, nmright) {
521 assert_eq!(vanilla, (nmleft & nmright).get());
522 }
523 if let Some(nmleft) = nmleft {
524 assert_eq!(vanilla, (nmleft & right).get());
525 }
526 if let Some(nmright) = nmright {
527 assert_eq!(vanilla, (left & nmright).get());
528 }
529 }
530 }
531 }
532
533 #[test]
534 fn bitand_signed() {
535 for left in i8::MIN..=i8::MAX {
536 let nmleft = NonMaxI8::new(left);
537 for right in i8::MIN..=i8::MAX {
538 let nmright = NonMaxI8::new(right);
539 let vanilla = left & right;
540 if let (Some(nmleft), Some(nmright)) = (nmleft, nmright) {
541 assert_eq!(vanilla, (nmleft & nmright).get());
542 }
543 }
544 }
545 }
546}