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, 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
25impl<T: ZeroablePrimitive> NonZero<T> {
26 #[doc = r" Creates a non-zero if the given value is not zero."]
27 #[must_use]
28 #[inline(always)]
29 pub const fn new(value: T) -> Option<Self> {
30 <std::num::NonZero<T>>::new(value).map(Self::from_std)
31 }
32
33 #[doc = r" Creates a non-zero without checking whether the value is non-zero."]
34 #[doc = r" This results in undefined behaviour if the value is zero."]
35 #[doc = r""]
36 #[doc = r" # Safety"]
37 #[doc = r""]
38 #[doc = r" The value must not be zero."]
39 #[must_use]
40 #[inline(always)]
41 pub const unsafe fn new_unchecked(value: T) -> Self {
42 Self::from_std(unsafe { std::num::NonZero::new_unchecked(value) })
43 }
44
45 #[must_use]
46 #[inline(always)]
47 pub const fn get(self) -> T {
48 self.into_std().get()
49 }
50
51 #[must_use]
52 #[inline(always)]
53 pub const fn into_std(self) -> std::num::NonZero<T> {
54 unsafe { <std::num::NonZero<T>>::new_unchecked(self.0) }
55 }
56
57 #[must_use]
58 #[inline(always)]
59 pub const fn from_std(value: std::num::NonZero<T>) -> Self {
60 Self(value.get())
61 }
62}
63
64impl<T: ZeroablePrimitive + fmt::Display> fmt::Display for NonZero<T> {
65 #[inline]
66 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
67 <T as fmt::Display>::fmt(&self.0, f)
68 }
69}
70
71#[cfg(feature = "serde")]
72impl<'de, T: ZeroablePrimitive + serde::Deserialize<'de>> serde::Deserialize<'de> for NonZero<T> {
73 #[inline]
74 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
75 where
76 D: serde::Deserializer<'de>,
77 {
78 let v = <T as serde::Deserialize<'de>>::deserialize(deserializer)?;
79 Self::new(v).ok_or_else(|| serde::de::Error::custom("expected nonzero integer"))
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::*;
86
87 #[test]
88 fn test() {
89 struct A<const NZ: NonZero<u8>>;
90
91 impl<const NZ: NonZero<u8>> A<NZ> {
92 fn get(self) -> u8 {
93 NZ.get()
94 }
95
96 fn get_static() -> u8 {
97 NZ.get()
98 }
99 }
100
101 assert_eq!(A::<{ NonZero::new(1).unwrap() }>.get(), 1);
102 assert_eq!(A::<{ NonZero::new(1).unwrap() }>::get_static(), 1);
103 }
104}