safa_abi/ffi/
num.rs

1use crate::ffi::NotZeroable;
2use crate::ffi::option::OptZero;
3
4use core::num::NonZero;
5
6/// Describes a trait for some types that are valid when passed as a zero
7///
8/// mainly for usage with [`ShouldNotBeZero`]
9pub 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/// Describes something that is valid when passed as a zero but SHOULDN'T BE a zero
55///
56/// mainly for usage with FFI and [`OptZero`] so that if it was passed as a zero it would be treated as a None value
57#[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}