| 1 | |
| 2 |
|
| 3 | use core::num::{Saturating, Wrapping};
|
| 4 |
|
| 5 | use crate::boxed::Box;
|
| 6 |
|
| 7 | #[rustc_specialization_trait]
|
| 8 | pub(super) unsafe trait IsZero {
|
| 9 | |
| 10 | |
| 11 | fn is_zero(&self) -> bool;
|
| 12 | }
|
| 13 |
|
| 14 | macro_rules! impl_is_zero {
|
| 15 | ($t:ty, $is_zero:expr) => {
|
| 16 | unsafe impl IsZero for $t {
|
| 17 | #[inline]
|
| 18 | fn is_zero(&self) -> bool {
|
| 19 | $is_zero(*self)
|
| 20 | }
|
| 21 | }
|
| 22 | };
|
| 23 | }
|
| 24 |
|
| 25 | impl_is_zero!(i8, |x| x == 0); |
| 26 | impl_is_zero!(i16, |x| x == 0);
|
| 27 | impl_is_zero!(i32, |x| x == 0);
|
| 28 | impl_is_zero!(i64, |x| x == 0);
|
| 29 | impl_is_zero!(i128, |x| x == 0);
|
| 30 | impl_is_zero!(isize, |x| x == 0);
|
| 31 |
|
| 32 | impl_is_zero!(u8, |x| x == 0); |
| 33 | impl_is_zero!(u16, |x| x == 0);
|
| 34 | impl_is_zero!(u32, |x| x == 0);
|
| 35 | impl_is_zero!(u64, |x| x == 0);
|
| 36 | impl_is_zero!(u128, |x| x == 0);
|
| 37 | impl_is_zero!(usize, |x| x == 0);
|
| 38 |
|
| 39 | impl_is_zero!(bool, |x| x == false);
|
| 40 | impl_is_zero!(char, |x| x == '\0');
|
| 41 |
|
| 42 | impl_is_zero!(f32, |x: f32| x.to_bits() == 0);
|
| 43 | impl_is_zero!(f64, |x: f64| x.to_bits() == 0);
|
| 44 |
|
| 45 | unsafe impl<T> IsZero for *const T {
|
| 46 | #[inline]
|
| 47 | fn is_zero(&self) -> bool {
|
| 48 | (*self).is_null()
|
| 49 | }
|
| 50 | }
|
| 51 |
|
| 52 | unsafe impl<T> IsZero for *mut T {
|
| 53 | #[inline]
|
| 54 | fn is_zero(&self) -> bool {
|
| 55 | (*self).is_null()
|
| 56 | }
|
| 57 | }
|
| 58 |
|
| 59 | unsafe impl<T: IsZero, const N: usize> IsZero for [T; N] {
|
| 60 | #[inline]
|
| 61 | fn is_zero(&self) -> bool {
|
| 62 | |
| 63 | |
| 64 | |
| 65 | |
| 66 | |
| 67 | |
| 68 |
|
| 69 | N <= 16 && self.iter().all(IsZero::is_zero)
|
| 70 | }
|
| 71 | }
|
| 72 |
|
| 73 | |
| 74 | macro_rules! impl_for_tuples {
|
| 75 | |
| 76 | () => {
|
| 77 | |
| 78 | };
|
| 79 | ($first_arg:ident $(,$rest:ident)*) => {
|
| 80 | unsafe impl <$first_arg: IsZero, $($rest: IsZero,)*> IsZero for ($first_arg, $($rest,)*){
|
| 81 | #[inline]
|
| 82 | fn is_zero(&self) -> bool{
|
| 83 | |
| 84 | |
| 85 | #[allow(non_snake_case)]
|
| 86 | let ($first_arg, $($rest,)*) = self;
|
| 87 |
|
| 88 | $first_arg.is_zero()
|
| 89 | $( && $rest.is_zero() )*
|
| 90 | }
|
| 91 | }
|
| 92 |
|
| 93 | impl_for_tuples!($($rest),*);
|
| 94 | }
|
| 95 | }
|
| 96 |
|
| 97 | impl_for_tuples!(A, B, C, D, E, F, G, H);
|
| 98 |
|
| 99 | |
| 100 | |
| 101 | |
| 102 | |
| 103 | |
| 104 | |
| 105 |
|
| 106 | unsafe impl<T: ?Sized> IsZero for Option<&T> {
|
| 107 | #[inline]
|
| 108 | fn is_zero(&self) -> bool {
|
| 109 | self.is_none()
|
| 110 | }
|
| 111 | }
|
| 112 |
|
| 113 | unsafe impl<T: ?Sized> IsZero for Option<Box<T>> {
|
| 114 | #[inline]
|
| 115 | fn is_zero(&self) -> bool {
|
| 116 | self.is_none()
|
| 117 | }
|
| 118 | }
|
| 119 |
|
| 120 | |
| 121 | |
| 122 | |
| 123 | |
| 124 | |
| 125 | |
| 126 |
|
| 127 | macro_rules! impl_is_zero_option_of_nonzero {
|
| 128 | ($($t:ident,)+) => {$(
|
| 129 | unsafe impl IsZero for Option<core::num::$t> {
|
| 130 | #[inline]
|
| 131 | fn is_zero(&self) -> bool {
|
| 132 | self.is_none()
|
| 133 | }
|
| 134 | }
|
| 135 | )+};
|
| 136 | }
|
| 137 |
|
| 138 | impl_is_zero_option_of_nonzero!(
|
| 139 | NonZeroU8,
|
| 140 | NonZeroU16,
|
| 141 | NonZeroU32,
|
| 142 | NonZeroU64,
|
| 143 | NonZeroU128,
|
| 144 | NonZeroI8,
|
| 145 | NonZeroI16,
|
| 146 | NonZeroI32,
|
| 147 | NonZeroI64,
|
| 148 | NonZeroI128,
|
| 149 | NonZeroUsize,
|
| 150 | NonZeroIsize,
|
| 151 | );
|
| 152 |
|
| 153 | macro_rules! impl_is_zero_option_of_num {
|
| 154 | ($($t:ty,)+) => {$(
|
| 155 | unsafe impl IsZero for Option<$t> {
|
| 156 | #[inline]
|
| 157 | fn is_zero(&self) -> bool {
|
| 158 | const {
|
| 159 | let none: Self = unsafe { core::mem::MaybeUninit::zeroed().assume_init() };
|
| 160 | assert!(none.is_none());
|
| 161 | }
|
| 162 | self.is_none()
|
| 163 | }
|
| 164 | }
|
| 165 | )+};
|
| 166 | }
|
| 167 |
|
| 168 | impl_is_zero_option_of_num!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize,);
|
| 169 |
|
| 170 | unsafe impl<T: IsZero> IsZero for Wrapping<T> {
|
| 171 | #[inline]
|
| 172 | fn is_zero(&self) -> bool {
|
| 173 | self.0.is_zero()
|
| 174 | }
|
| 175 | }
|
| 176 |
|
| 177 | unsafe impl<T: IsZero> IsZero for Saturating<T> {
|
| 178 | #[inline]
|
| 179 | fn is_zero(&self) -> bool {
|
| 180 | self.0.is_zero()
|
| 181 | }
|
| 182 | }
|
| 183 |
|
| 184 | macro_rules! impl_for_optional_bool {
|
| 185 | ($($t:ty,)+) => {$(
|
| 186 | unsafe impl IsZero for $t {
|
| 187 | #[inline]
|
| 188 | fn is_zero(&self) -> bool {
|
| 189 | |
| 190 | |
| 191 | |
| 192 | |
| 193 | let raw: u8 = unsafe { core::mem::transmute(*self) };
|
| 194 | raw == 0
|
| 195 | }
|
| 196 | }
|
| 197 | )+};
|
| 198 | }
|
| 199 | impl_for_optional_bool! {
|
| 200 | Option<bool>,
|
| 201 | Option<Option<bool>>,
|
| 202 | Option<Option<Option<bool>>>,
|
| 203 | |
| 204 | }
|