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
//! # NonZero signs of integers
use std::cmp::Ordering;
use std::num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8};
use std::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8};

use crate::non_zero::NonZeroSign;
use crate::non_zero::NonZeroSigned;

macro_rules! define_u {
    ($ty:ty) => {
        impl NonZeroSigned for $ty {
            #[must_use]
            #[inline]
            fn signum(&self) -> NonZeroSign {
                if *self > 0 {
                    NonZeroSign::Positive
                } else {
                    panic!("attempt to take a non zero sign of a zero value")
                }
            }
        }
    }
}

define_u!(u8);
define_u!(u16);
define_u!(u32);
define_u!(u64);
define_u!(u128);

macro_rules! define {
    ($ty:ty) => {
        impl NonZeroSigned for $ty {
            #[must_use]
            #[inline]
            fn signum(&self) -> NonZeroSign {
                match self.cmp(&0) {
                    Ordering::Less => NonZeroSign::Negative,
                    Ordering::Equal => panic!("attempt to take a non zero sign of a zero value"),
                    Ordering::Greater => NonZeroSign::Positive,
                }
            }
        }
    }
}

define!(i8);
define!(i16);
define!(i32);
define!(i64);
define!(i128);

macro_rules! define_non_zero_u {
    ($ty:ty) => {
        impl NonZeroSigned for $ty {
            #[must_use]
            #[inline]
            fn signum(&self) -> NonZeroSign {
                NonZeroSign::Positive
            }
        }
    }
}

define_non_zero_u!(NonZeroU8);
define_non_zero_u!(NonZeroU16);
define_non_zero_u!(NonZeroU32);
define_non_zero_u!(NonZeroU64);
define_non_zero_u!(NonZeroU128);

macro_rules! define_non_zero {
    ($ty:ty) => {
        impl NonZeroSigned for $ty {
            #[must_use]
            #[inline]
            fn signum(&self) -> NonZeroSign {
                if self.get() > 0 {
                    NonZeroSign::Positive
                } else {
                    NonZeroSign::Negative
                }
            }
        }
    }
}

define_non_zero!(NonZeroI8);
define_non_zero!(NonZeroI16);
define_non_zero!(NonZeroI32);
define_non_zero!(NonZeroI64);
define_non_zero!(NonZeroI128);

#[cfg(test)]
mod test {
    use std::num::{NonZeroI8, NonZeroU8};

    use crate::{NonZeroSign, NonZeroSigned};

    #[test]
    fn test_zero_sign() {
        assert_eq!(NonZeroSigned::signum(&1_u32), NonZeroSign::Positive);
        assert_eq!(NonZeroSigned::signum(&-1_i32), NonZeroSign::Negative);

        assert_eq!(NonZeroSigned::signum(&NonZeroU8::new(1).unwrap()), NonZeroSign::Positive);
        assert_eq!(NonZeroSigned::signum(&NonZeroI8::new(1).unwrap()), NonZeroSign::Positive);
        assert_eq!(NonZeroSigned::signum(&NonZeroI8::new(-1).unwrap()), NonZeroSign::Negative);
    }

    #[test]
    #[should_panic]
    fn test_non_zero_on_zero() {
        NonZeroSigned::signum(&0_u32);
    }

    #[test]
    #[should_panic]
    fn test_non_zero_on_zero_signed() {
        NonZeroSigned::signum(&0_i8);
    }
}