nonzero_const_param/
lib.rs1#![expect(internal_features)]
4#![feature(
5 adt_const_params,
6 const_option_ops,
7 const_param_ty_unchecked,
8 const_trait_impl,
9 nonzero_internals
10)]
11
12use std::fmt;
13use std::marker::ConstParamTy;
14use std::num::ZeroablePrimitive;
15
16#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, ConstParamTy)]
17#[cfg_attr(feature = "serde", derive(serde::Serialize))]
18#[cfg_attr(
19 feature = "zerocopy",
20 derive(zerocopy::AsBytes, zerocopy::FromBytes, zerocopy::FromZeroes)
21)]
22#[repr(transparent)]
23pub struct NonZero<T: ZeroablePrimitive>(T);
24
25pub type NonZeroU8 = NonZero<u8>;
26pub type NonZeroU16 = NonZero<u16>;
27pub type NonZeroU32 = NonZero<u32>;
28pub type NonZeroU64 = NonZero<u64>;
29pub type NonZeroU128 = NonZero<u128>;
30pub type NonZeroUsize = NonZero<usize>;
31pub type NonZeroI8 = NonZero<i8>;
32pub type NonZeroI16 = NonZero<i16>;
33pub type NonZeroI32 = NonZero<i32>;
34pub type NonZeroI64 = NonZero<i64>;
35pub type NonZeroI128 = NonZero<i128>;
36pub type NonZeroIsize = NonZero<isize>;
37
38impl<T: ZeroablePrimitive> NonZero<T> {
39 #[doc = r" Creates a non-zero if the given value is not zero."]
40 #[must_use]
41 #[inline(always)]
42 pub const fn new(value: T) -> Option<Self> {
43 <std::num::NonZero<T>>::new(value).map(Self::from_std)
44 }
45
46 #[doc = r" Creates a non-zero without checking whether the value is non-zero."]
47 #[doc = r" This results in undefined behaviour if the value is zero."]
48 #[doc = r""]
49 #[doc = r" # Safety"]
50 #[doc = r""]
51 #[doc = r" The value must not be zero."]
52 #[must_use]
53 #[inline(always)]
54 pub const unsafe fn new_unchecked(value: T) -> Self {
55 Self::from_std(unsafe { std::num::NonZero::new_unchecked(value) })
56 }
57
58 #[must_use]
59 #[inline(always)]
60 pub const fn get(self) -> T {
61 self.into_std().get()
62 }
63
64 #[must_use]
65 #[inline(always)]
66 pub const fn into_std(self) -> std::num::NonZero<T> {
67 unsafe { <std::num::NonZero<T>>::new_unchecked(self.0) }
68 }
69
70 #[must_use]
71 #[inline(always)]
72 pub const fn from_std(value: std::num::NonZero<T>) -> Self {
73 Self(value.get())
74 }
75}
76
77impl<T: ZeroablePrimitive + fmt::Display> fmt::Display for NonZero<T> {
78 #[inline]
79 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
80 <T as fmt::Display>::fmt(&self.0, f)
81 }
82}
83
84#[cfg(feature = "serde")]
85impl<'de, T: ZeroablePrimitive + serde::Deserialize<'de>> serde::Deserialize<'de> for NonZero<T> {
86 #[inline]
87 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
88 where
89 D: serde::Deserializer<'de>,
90 {
91 let v = <T as serde::Deserialize<'de>>::deserialize(deserializer)?;
92 Self::new(v).ok_or_else(|| serde::de::Error::custom("expected nonzero integer"))
93 }
94}
95
96#[cfg(test)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn test() {
102 struct A<const NZ: NonZero<u8>>;
103
104 impl<const NZ: NonZero<u8>> A<NZ> {
105 fn get(self) -> u8 {
106 NZ.get()
107 }
108
109 fn get_static() -> u8 {
110 NZ.get()
111 }
112 }
113
114 assert_eq!(A::<{ NonZero::new(1).unwrap() }>.get(), 1);
115 assert_eq!(A::<{ NonZero::new(1).unwrap() }>::get_static(), 1);
116 }
117}