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
use std::cmp::Ordering;
use std::fmt;
use std::num::*;

macro_rules! impl_nonzero_fmt {
    ( ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
        $(
            impl fmt::$Trait for $Ty {
                #[inline]
                fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                    self.get().fmt(f)
                }
            }
        )+
    }
}

macro_rules! def_signed {
    ( $($name:ident($inner:ident, $zeroable_signed:ident, $zeroable:ident),)+) => {
        $(
            /// An integer that is known not to equal zero.
            ///
            /// This enables some memory layout optimization.
            /// For example, `Option<NonZeroI32>` is the same size as `i32`:
            ///
            /// ```rust
            /// use std::mem::size_of;
            /// use nonzero_signed::NonZeroI32;
            /// assert_eq!(size_of::<Option<NonZeroI32>>(), size_of::<i32>());
            /// ```
            #[cfg_attr(new_rustc, deprecated(since = "1.0.3", note = "These became part of std::num in Rust 1.34, please use the std types instead of this crate."))]
            #[derive(Copy, Clone, Eq, PartialEq, Hash)]
            #[repr(transparent)]
            pub struct $name($inner);

            impl $name {
                /// Create a non-zero without checking the value.
                ///
                /// # Safety
                ///
                /// The value must not be zero.
                #[inline]
                pub unsafe fn new_unchecked(n: $zeroable_signed) -> Self {
                    $name($inner::new_unchecked(n as $zeroable))
                }

                /// Create a non-zero if the given value is not zero.
                #[inline]
                pub fn new(n: $zeroable_signed) -> Option<Self> {
                    if n != 0 {
                        Some(unsafe {$name::new_unchecked(n)})
                    } else {
                        None
                    }
                }

                /// Returns the value as a primitive type.
                #[inline]
                pub fn get(self) -> $zeroable_signed {
                    self.0.get() as $zeroable_signed
                }
            }

            impl Ord for $name {
                fn cmp(&self, other: &Self) -> Ordering {
                    self.get().cmp(&other.get())
                }
            }

            impl PartialOrd for $name {
                fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
                    Some(self.cmp(other))
                }
            }

            impl_nonzero_fmt! {
                (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $name
            }
        )+
    }
}

def_signed!(
    NonZeroI8(NonZeroU8, i8, u8),
    NonZeroI16(NonZeroU16, i16, u16),
    NonZeroI32(NonZeroU32, i32, u32),
    NonZeroI64(NonZeroU64, i64, u64),
    NonZeroI128(NonZeroU128, i128, u128),
    NonZeroIsize(NonZeroUsize, isize, usize),
);

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn wrapping_test() {
        assert!(NonZeroI8::new(0).is_none());
        assert!(NonZeroI8::new(-5).unwrap().get() == -5);
    }

    #[test]
    fn format_test() {
        assert_eq!(format!("{}", NonZeroI8::new(-5).unwrap()), "-5")
    }
}