1use num_traits::Zero;
4use std::{
5 fmt::Display,
6 num::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize},
7 ops::Not,
8};
9
10#[derive(Debug, Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
12pub struct NonZero<T> {
13 value: T,
14}
15
16impl<T> Display for NonZero<T>
17where
18 T: Display,
19{
20 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21 write!(f, "{}", self.value)
22 }
23}
24
25impl<T> NonZero<T>
26where
27 T: Zero,
28{
29 pub fn new(value: T) -> Option<Self> {
31 value.is_zero().not().then_some(Self { value })
32 }
33
34 pub const unsafe fn new_unchecked(value: T) -> Self {
38 Self { value }
39 }
40
41 pub fn replace(&mut self, new_value: T) -> Option<T> {
45 let mut other = Self::new(new_value)?;
46 self.swap(&mut other);
47 Some(other.value)
48 }
49
50 pub fn set(&mut self, value: T) -> bool {
54 let nonzero = value.is_zero().not();
55 if nonzero {
56 unsafe { self.set_unchecked(value) }
57 }
58 nonzero
59 }
60
61 pub unsafe fn set_unchecked(&mut self, value: T) {
66 self.value = value;
67 }
68
69 pub fn map(self, f: impl Fn(T) -> T) -> Option<Self> {
71 Self::new(f(self.value))
72 }
73
74 #[must_use]
78 pub unsafe fn map_unchecked(self, f: impl Fn(T) -> T) -> Self {
79 Self::new_unchecked(f(self.value))
80 }
81
82 pub const fn get(&self) -> &T {
84 &self.value
85 }
86
87 #[deprecated(since = "0.3.14", note = "use `swap` instead")]
91 pub const unsafe fn get_mut(&mut self) -> &mut T {
92 &mut self.value
93 }
94
95 pub fn swap(&mut self, other: &mut Self) {
97 std::mem::swap(self, other);
98 }
99
100 pub fn into_inner(self) -> T {
105 self.value
106 }
107}
108
109macro_rules! impl_from_primitive {
110 ($new_name: ty, $primitive: ty) => {
111 impl From<$primitive> for $new_name {
112 fn from(value: $primitive) -> Self {
113 Self { value: value.get() }
114 }
115 }
116 };
117}
118
119impl_from_primitive!(NonZero<u8>, NonZeroU8);
120impl_from_primitive!(NonZero<u16>, NonZeroU16);
121impl_from_primitive!(NonZero<u32>, NonZeroU32);
122impl_from_primitive!(NonZero<u64>, NonZeroU64);
123impl_from_primitive!(NonZero<u128>, NonZeroU128);
124impl_from_primitive!(NonZero<usize>, NonZeroUsize);