1use crate::ffi::NotZeroable;
2use crate::ffi::option::OptZero;
3
4use core::num::NonZero;
5
6pub trait ZeroableThing: Sized {
10 const ZERO: Self;
11 fn is_zero(&self) -> bool;
12}
13
14macro_rules! impl_zeroable_int {
15 ($ty: ty) => {
16 impl ZeroableThing for $ty {
17 const ZERO: Self = 0;
18 fn is_zero(&self) -> bool {
19 *self == Self::ZERO
20 }
21 }
22
23 impl From<NonZero<$ty>> for ShouldNotBeZero<$ty> {
24 fn from(value: NonZero<$ty>) -> Self {
25 ShouldNotBeZero(value.into())
26 }
27 }
28
29 impl From<OptZero<ShouldNotBeZero<$ty>>> for Option<NonZero<$ty>> {
30 fn from(value: OptZero<ShouldNotBeZero<$ty>>) -> Self {
31 match value.into_option() {
32 Option::Some(value) => Some(unsafe { NonZero::new_unchecked(value.value()) }),
33 Option::None => None,
34 }
35 }
36 }
37 };
38}
39
40impl_zeroable_int!(u8);
41impl_zeroable_int!(u16);
42impl_zeroable_int!(u32);
43impl_zeroable_int!(u64);
44impl_zeroable_int!(u128);
45impl_zeroable_int!(usize);
46impl_zeroable_int!(i8);
47impl_zeroable_int!(i16);
48impl_zeroable_int!(i32);
49impl_zeroable_int!(i64);
50impl_zeroable_int!(i128);
51impl_zeroable_int!(isize);
52
53#[repr(transparent)]
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
58pub struct ShouldNotBeZero<T: ZeroableThing>(T);
59
60impl<T: ZeroableThing> ShouldNotBeZero<T> {
61 pub fn new(value: T) -> Option<Self> {
62 if value.is_zero() {
63 None
64 } else {
65 Some(ShouldNotBeZero(value))
66 }
67 }
68
69 pub const unsafe fn new_unchecked(value: T) -> Self {
70 ShouldNotBeZero(value)
71 }
72
73 pub const fn value_ref(&self) -> &T {
74 &self.0
75 }
76}
77
78impl<T: ZeroableThing + Copy> ShouldNotBeZero<T> {
79 pub const fn value(&self) -> T {
80 self.0
81 }
82}
83
84impl<T: ZeroableThing> NotZeroable for ShouldNotBeZero<T> {
85 fn is_zero(&self) -> bool {
86 self.0.is_zero()
87 }
88}