1use core::num::{NonZero, Saturating, Wrapping};
2
3use crate::boxed::Box;
4
5#[rustc_specialization_trait]
6pub(super) unsafe trait IsZero {
7 fn is_zero(&self) -> bool;
10}
11
12macro_rules! impl_is_zero {
13 ($t:ty, $is_zero:expr) => {
14 unsafe impl IsZero for $t {
15 #[inline]
16 fn is_zero(&self) -> bool {
17 $is_zero(*self)
18 }
19 }
20 };
21}
22
23impl_is_zero!(i8, |x| x == 0); impl_is_zero!(i16, |x| x == 0);
25impl_is_zero!(i32, |x| x == 0);
26impl_is_zero!(i64, |x| x == 0);
27impl_is_zero!(i128, |x| x == 0);
28impl_is_zero!(isize, |x| x == 0);
29
30impl_is_zero!(u8, |x| x == 0); impl_is_zero!(u16, |x| x == 0);
32impl_is_zero!(u32, |x| x == 0);
33impl_is_zero!(u64, |x| x == 0);
34impl_is_zero!(u128, |x| x == 0);
35impl_is_zero!(usize, |x| x == 0);
36
37impl_is_zero!(bool, |x| x == false);
38impl_is_zero!(char, |x| x == '\0');
39
40impl_is_zero!(f32, |x: f32| x.to_bits() == 0);
41impl_is_zero!(f64, |x: f64| x.to_bits() == 0);
42
43unsafe impl<T: IsZero, const N: usize> IsZero for [T; N] {
47 #[inline]
48 fn is_zero(&self) -> bool {
49 N <= 16 && self.iter().all(IsZero::is_zero)
57 }
58}
59
60macro_rules! impl_is_zero_tuples {
62 () => {
64 };
66 ($first_arg:ident $(,$rest:ident)*) => {
67 unsafe impl <$first_arg: IsZero, $($rest: IsZero,)*> IsZero for ($first_arg, $($rest,)*){
68 #[inline]
69 fn is_zero(&self) -> bool{
70 #[allow(non_snake_case)]
73 let ($first_arg, $($rest,)*) = self;
74
75 $first_arg.is_zero()
76 $( && $rest.is_zero() )*
77 }
78 }
79
80 impl_is_zero_tuples!($($rest),*);
81 }
82}
83
84impl_is_zero_tuples!(A, B, C, D, E, F, G, H);
85
86unsafe impl<T: ?Sized> IsZero for Option<&T> {
94 #[inline]
95 fn is_zero(&self) -> bool {
96 self.is_none()
97 }
98}
99
100unsafe impl<T: ?Sized> IsZero for Option<Box<T>> {
101 #[inline]
102 fn is_zero(&self) -> bool {
103 self.is_none()
104 }
105}
106
107macro_rules! impl_is_zero_option_of_nonzero_int {
114 ($($t:ty),+ $(,)?) => {$(
115 unsafe impl IsZero for Option<NonZero<$t>> {
116 #[inline]
117 fn is_zero(&self) -> bool {
118 self.is_none()
119 }
120 }
121 )+};
122}
123
124impl_is_zero_option_of_nonzero_int!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);
125
126macro_rules! impl_is_zero_option_of_int {
127 ($($t:ty),+ $(,)?) => {$(
128 unsafe impl IsZero for Option<$t> {
129 #[inline]
130 fn is_zero(&self) -> bool {
131 const {
132 let none: Self = unsafe { core::mem::MaybeUninit::zeroed().assume_init() };
133 assert!(none.is_none());
134 }
135 self.is_none()
136 }
137 }
138 )+};
139}
140
141impl_is_zero_option_of_int!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, usize, isize);
142
143unsafe impl<T: IsZero> IsZero for Wrapping<T> {
144 #[inline]
145 fn is_zero(&self) -> bool {
146 self.0.is_zero()
147 }
148}
149
150unsafe impl<T: IsZero> IsZero for Saturating<T> {
151 #[inline]
152 fn is_zero(&self) -> bool {
153 self.0.is_zero()
154 }
155}
156
157macro_rules! impl_is_zero_option_of_bool {
158 ($($t:ty),+ $(,)?) => {$(
159 unsafe impl IsZero for $t {
160 #[inline]
161 fn is_zero(&self) -> bool {
162 let raw: u8 = unsafe { core::mem::transmute(*self) };
167 raw == 0
168 }
169 }
170 )+};
171}
172
173impl_is_zero_option_of_bool! {
174 Option<bool>,
175 Option<Option<bool>>,
176 Option<Option<Option<bool>>>,
177 }