1use crate::{
4 Bounded, Choice, ConstOne, Constants, CtAssign, CtEq, CtOption, CtSelect, Encoding, Int, Limb,
5 Mul, Odd, One, ToUnsigned, Uint, UintRef, Zero,
6};
7use core::{
8 fmt,
9 num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128},
10 ops::Deref,
11};
12use ctutils::{CtAssignSlice, CtEqSlice};
13
14#[cfg(feature = "alloc")]
15use crate::BoxedUint;
16
17#[cfg(feature = "hybrid-array")]
18use crate::{ArrayEncoding, ByteArray};
19
20#[cfg(feature = "rand_core")]
21use {crate::Random, rand_core::TryRng};
22
23#[cfg(feature = "serde")]
24use serdect::serde::{
25 Deserialize, Deserializer, Serialize, Serializer,
26 de::{Error, Unexpected},
27};
28
29pub type NonZeroLimb = NonZero<Limb>;
31
32pub type NonZeroUint<const LIMBS: usize> = NonZero<Uint<LIMBS>>;
34
35pub type NonZeroUintRef = NonZero<UintRef>;
37
38pub type NonZeroInt<const LIMBS: usize> = NonZero<Int<LIMBS>>;
40
41#[cfg(feature = "alloc")]
43pub type NonZeroBoxedUint = NonZero<BoxedUint>;
44
45#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
47#[repr(transparent)]
48pub struct NonZero<T: ?Sized>(pub(crate) T);
49
50impl<T> NonZero<T> {
51 #[inline]
53 pub fn new(mut n: T) -> CtOption<Self>
54 where
55 T: Zero + One + CtAssign,
56 {
57 let is_zero = n.is_zero();
58
59 n.ct_assign(&T::one_like(&n), is_zero);
63 CtOption::new(Self(n), !is_zero)
64 }
65
66 #[inline]
68 pub fn get(self) -> T {
69 self.0
70 }
71
72 #[inline]
77 pub const fn get_copy(self) -> T
78 where
79 T: Copy,
80 {
81 self.0
82 }
83}
84
85impl<T: ?Sized> NonZero<T> {
86 pub const fn as_ref(&self) -> &T {
88 &self.0
89 }
90}
91
92impl<T> NonZero<T>
93where
94 T: Bounded + ?Sized,
95{
96 pub const BITS: u32 = T::BITS;
98
99 pub const BYTES: usize = T::BYTES;
101}
102
103impl<T> NonZero<T>
104where
105 T: Constants,
106{
107 pub const ONE: Self = Self(T::ONE);
109
110 pub const MAX: Self = Self(T::MAX);
112}
113
114impl<T> NonZero<T>
115where
116 T: Zero + One + CtAssign + Encoding,
117{
118 pub fn from_be_bytes(bytes: T::Repr) -> CtOption<Self> {
120 Self::new(T::from_be_bytes(bytes))
121 }
122
123 pub fn from_le_bytes(bytes: T::Repr) -> CtOption<Self> {
125 Self::new(T::from_le_bytes(bytes))
126 }
127}
128
129impl<T> ConstOne for NonZero<T>
130where
131 T: ConstOne + One,
132{
133 const ONE: Self = Self(T::ONE);
134}
135
136impl<T> One for NonZero<T>
137where
138 T: One,
139 Self: CtEq,
140{
141 #[inline]
142 fn one() -> Self {
143 Self(T::one())
144 }
145}
146
147impl<T> num_traits::One for NonZero<T>
148where
149 T: One + Mul<T, Output = T>,
150{
151 #[inline]
152 fn one() -> Self {
153 Self(T::one())
154 }
155
156 fn is_one(&self) -> bool {
157 self.0.is_one().into()
158 }
159}
160
161impl<T> Mul<Self> for NonZero<T>
163where
164 T: Mul<T, Output = T>,
165{
166 type Output = Self;
167
168 fn mul(self, rhs: Self) -> Self {
169 Self(self.0 * rhs.0)
170 }
171}
172
173impl NonZero<Limb> {
174 #[inline]
184 #[must_use]
185 #[track_caller]
186 pub const fn new_unwrap(n: Limb) -> Self {
187 assert!(n.is_nonzero().to_bool_vartime(), "invalid value: zero");
188 Self(n)
189 }
190
191 #[must_use]
194 pub const fn from_u8(n: NonZeroU8) -> Self {
195 Self(Limb::from_u8(n.get()))
196 }
197
198 #[must_use]
201 pub const fn from_u16(n: NonZeroU16) -> Self {
202 Self(Limb::from_u16(n.get()))
203 }
204
205 #[must_use]
208 pub const fn from_u32(n: NonZeroU32) -> Self {
209 Self(Limb::from_u32(n.get()))
210 }
211
212 cpubits::cpubits! {
213 64 => {
214 #[must_use]
217 pub const fn from_u64(n: NonZeroU64) -> Self {
218 Self(Limb::from_u64(n.get()))
219 }
220 }
221 }
222}
223
224impl<const LIMBS: usize> NonZeroUint<LIMBS> {
225 #[inline]
234 #[track_caller]
235 #[must_use]
236 pub const fn new_unwrap(n: Uint<LIMBS>) -> Self {
237 assert!(n.is_nonzero().to_bool_vartime(), "invalid value: zero");
238 Self(n)
239 }
240
241 #[track_caller]
246 #[must_use]
247 pub const fn from_be_hex(hex: &str) -> Self {
248 Self::new_unwrap(Uint::from_be_hex(hex))
249 }
250
251 #[track_caller]
256 #[must_use]
257 pub const fn from_le_hex(hex: &str) -> Self {
258 Self::new_unwrap(Uint::from_le_hex(hex))
259 }
260
261 #[must_use]
264 pub const fn from_u8(n: NonZeroU8) -> Self {
265 Self(Uint::from_u8(n.get()))
266 }
267
268 #[must_use]
271 pub const fn from_u16(n: NonZeroU16) -> Self {
272 Self(Uint::from_u16(n.get()))
273 }
274
275 #[must_use]
278 pub const fn from_u32(n: NonZeroU32) -> Self {
279 Self(Uint::from_u32(n.get()))
280 }
281
282 #[must_use]
285 pub const fn from_u64(n: NonZeroU64) -> Self {
286 Self(Uint::from_u64(n.get()))
287 }
288
289 #[must_use]
292 pub const fn from_u128(n: NonZeroU128) -> Self {
293 Self(Uint::from_u128(n.get()))
294 }
295
296 #[inline]
298 #[must_use]
299 pub const fn as_uint_ref(&self) -> &NonZeroUintRef {
300 self.0.as_uint_ref().as_nz_unchecked()
301 }
302}
303
304impl<const LIMBS: usize> AsRef<NonZeroUintRef> for NonZeroUint<LIMBS> {
305 fn as_ref(&self) -> &NonZeroUintRef {
306 self.as_uint_ref()
307 }
308}
309
310impl<const LIMBS: usize> NonZeroInt<LIMBS> {
311 #[inline]
321 #[must_use]
322 #[track_caller]
323 pub const fn new_unwrap(n: Int<LIMBS>) -> Self {
324 assert!(n.is_nonzero().to_bool_vartime(), "invalid value: zero");
325 Self(n)
326 }
327
328 #[must_use]
330 pub const fn abs_sign(&self) -> (NonZero<Uint<LIMBS>>, Choice) {
331 let (abs, sign) = self.0.abs_sign();
332 (NonZero(abs), sign)
334 }
335
336 #[must_use]
338 pub const fn abs(&self) -> NonZero<Uint<LIMBS>> {
339 self.abs_sign().0
340 }
341}
342
343#[cfg(feature = "alloc")]
344impl NonZeroBoxedUint {
345 #[inline]
347 #[must_use]
348 pub fn as_uint_ref(&self) -> &NonZeroUintRef {
349 self.0.as_uint_ref().as_nz_unchecked()
350 }
351}
352
353#[cfg(feature = "alloc")]
354impl AsRef<NonZeroUintRef> for NonZeroBoxedUint {
355 fn as_ref(&self) -> &NonZeroUintRef {
356 self.as_uint_ref()
357 }
358}
359
360#[cfg(feature = "alloc")]
361impl<T: AsRef<UintRef> + ?Sized> NonZero<T> {
362 pub(crate) fn lower_limb(&self) -> NonZeroLimb {
364 NonZero(self.0.as_ref().limbs[0])
365 }
366
367 pub(crate) fn to_boxed(&self) -> NonZeroBoxedUint {
369 NonZero(BoxedUint::from(self.0.as_ref()))
370 }
371}
372
373impl<T: ToUnsigned + ?Sized> NonZero<T> {
374 pub fn to_unsigned(&self) -> NonZero<T::Unsigned> {
376 NonZero(self.0.to_unsigned())
377 }
378}
379
380#[cfg(feature = "hybrid-array")]
381impl<T> NonZero<T>
382where
383 T: ArrayEncoding + Zero + One + CtAssign,
384{
385 pub fn from_be_byte_array(bytes: ByteArray<T>) -> CtOption<Self> {
387 Self::new(T::from_be_byte_array(bytes))
388 }
389
390 pub fn from_le_byte_array(bytes: ByteArray<T>) -> CtOption<Self> {
392 Self::new(T::from_le_byte_array(bytes))
393 }
394}
395
396impl<T: ?Sized> AsRef<T> for NonZero<T> {
397 fn as_ref(&self) -> &T {
398 &self.0
399 }
400}
401
402impl<T> CtAssign for NonZero<T>
403where
404 T: CtAssign,
405{
406 #[inline]
407 fn ct_assign(&mut self, other: &Self, choice: Choice) {
408 self.0.ct_assign(&other.0, choice);
409 }
410}
411impl<T> CtAssignSlice for NonZero<T> where T: CtAssign {}
412
413impl<T> CtEq for NonZero<T>
414where
415 T: CtEq + ?Sized,
416{
417 #[inline]
418 fn ct_eq(&self, other: &Self) -> Choice {
419 CtEq::ct_eq(&self.0, &other.0)
420 }
421}
422impl<T> CtEqSlice for NonZero<T> where T: CtEq {}
423
424impl<T> CtSelect for NonZero<T>
425where
426 T: CtSelect,
427{
428 #[inline]
429 fn ct_select(&self, other: &Self, choice: Choice) -> Self {
430 Self(self.0.ct_select(&other.0, choice))
431 }
432}
433
434impl<T> Default for NonZero<T>
435where
436 T: One,
437{
438 #[inline]
439 fn default() -> Self {
440 Self(T::one())
441 }
442}
443
444impl<T: ?Sized> Deref for NonZero<T> {
445 type Target = T;
446
447 fn deref(&self) -> &T {
448 &self.0
449 }
450}
451
452#[cfg(feature = "rand_core")]
453impl<T> Random for NonZero<T>
454where
455 T: Random + Zero + One + CtAssign,
456{
457 fn try_random_from_rng<R: TryRng + ?Sized>(rng: &mut R) -> Result<Self, R::Error> {
463 loop {
464 if let Some(result) = Self::new(T::try_random_from_rng(rng)?).into() {
465 break Ok(result);
466 }
467 }
468 }
469}
470
471impl From<NonZeroU8> for NonZero<Limb> {
472 fn from(integer: NonZeroU8) -> Self {
473 Self::from_u8(integer)
474 }
475}
476
477impl From<NonZeroU16> for NonZero<Limb> {
478 fn from(integer: NonZeroU16) -> Self {
479 Self::from_u16(integer)
480 }
481}
482
483impl From<NonZeroU32> for NonZero<Limb> {
484 fn from(integer: NonZeroU32) -> Self {
485 Self::from_u32(integer)
486 }
487}
488
489cpubits::cpubits! {
490 64 => {
491 impl From<NonZeroU64> for NonZero<Limb> {
492 fn from(integer: NonZeroU64) -> Self {
493 Self::from_u64(integer)
494 }
495 }
496 }
497}
498
499impl<const LIMBS: usize> From<NonZeroU8> for NonZero<Uint<LIMBS>> {
500 fn from(integer: NonZeroU8) -> Self {
501 Self::from_u8(integer)
502 }
503}
504
505impl<const LIMBS: usize> From<NonZeroU16> for NonZero<Uint<LIMBS>> {
506 fn from(integer: NonZeroU16) -> Self {
507 Self::from_u16(integer)
508 }
509}
510
511impl<const LIMBS: usize> From<NonZeroU32> for NonZero<Uint<LIMBS>> {
512 fn from(integer: NonZeroU32) -> Self {
513 Self::from_u32(integer)
514 }
515}
516
517impl<const LIMBS: usize> From<NonZeroU64> for NonZero<Uint<LIMBS>> {
518 fn from(integer: NonZeroU64) -> Self {
519 Self::from_u64(integer)
520 }
521}
522
523impl<const LIMBS: usize> From<NonZeroU128> for NonZero<Uint<LIMBS>> {
524 fn from(integer: NonZeroU128) -> Self {
525 Self::from_u128(integer)
526 }
527}
528
529impl<T> From<Odd<T>> for NonZero<T> {
530 fn from(odd: Odd<T>) -> NonZero<T> {
531 NonZero(odd.get())
532 }
533}
534
535impl<T> fmt::Display for NonZero<T>
536where
537 T: fmt::Display + ?Sized,
538{
539 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
540 fmt::Display::fmt(&self.0, f)
541 }
542}
543
544impl<T> fmt::Binary for NonZero<T>
545where
546 T: fmt::Binary + ?Sized,
547{
548 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
549 fmt::Binary::fmt(&self.0, f)
550 }
551}
552
553impl<T> fmt::Octal for NonZero<T>
554where
555 T: fmt::Octal + ?Sized,
556{
557 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
558 fmt::Octal::fmt(&self.0, f)
559 }
560}
561
562impl<T> fmt::LowerHex for NonZero<T>
563where
564 T: fmt::LowerHex + ?Sized,
565{
566 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
567 fmt::LowerHex::fmt(&self.0, f)
568 }
569}
570
571impl<T> fmt::UpperHex for NonZero<T>
572where
573 T: fmt::UpperHex + ?Sized,
574{
575 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
576 fmt::UpperHex::fmt(&self.0, f)
577 }
578}
579
580#[cfg(feature = "serde")]
581impl<'de, T: Deserialize<'de> + Zero> Deserialize<'de> for NonZero<T> {
582 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
583 where
584 D: Deserializer<'de>,
585 {
586 let value: T = T::deserialize(deserializer)?;
587
588 if bool::from(value.is_zero()) {
589 Err(D::Error::invalid_value(
590 Unexpected::Other("zero"),
591 &"a non-zero value",
592 ))
593 } else {
594 Ok(Self(value))
595 }
596 }
597}
598
599#[cfg(feature = "serde")]
600impl<T: Serialize + Zero> Serialize for NonZero<T> {
601 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
602 where
603 S: Serializer,
604 {
605 self.0.serialize(serializer)
606 }
607}
608
609#[cfg(feature = "subtle")]
610impl<T> subtle::ConditionallySelectable for NonZero<T>
611where
612 T: Copy,
613 Self: CtSelect,
614{
615 fn conditional_select(a: &Self, b: &Self, choice: subtle::Choice) -> Self {
616 CtSelect::ct_select(a, b, choice.into())
617 }
618}
619
620#[cfg(feature = "subtle")]
621impl<T> subtle::ConstantTimeEq for NonZero<T>
622where
623 T: ?Sized,
624 Self: CtEq,
625{
626 #[inline]
627 fn ct_eq(&self, other: &Self) -> subtle::Choice {
628 CtEq::ct_eq(self, other).into()
629 }
630}
631
632#[cfg(feature = "zeroize")]
633impl<T: zeroize::Zeroize + Zero> zeroize::Zeroize for NonZero<T> {
634 fn zeroize(&mut self) {
635 self.0.zeroize();
636 }
637}
638
639#[cfg(test)]
640mod tests {
641 use super::NonZero;
642 use crate::{I128, One, U128};
643 use hex_literal::hex;
644
645 #[test]
646 fn default() {
647 assert!(!NonZero::<U128>::default().is_zero().to_bool());
648 }
649
650 #[test]
651 fn from_be_bytes() {
652 assert_eq!(
653 NonZero::<U128>::from_be_bytes(hex!("00000000000000000000000000000001").into())
654 .unwrap(),
655 NonZero::<U128>::ONE
656 );
657
658 assert_eq!(
659 NonZero::<U128>::from_be_bytes(hex!("00000000000000000000000000000000").into())
660 .into_option(),
661 None
662 );
663 }
664
665 #[test]
666 fn from_le_bytes() {
667 assert_eq!(
668 NonZero::<U128>::from_le_bytes(hex!("01000000000000000000000000000000").into())
669 .unwrap(),
670 NonZero::<U128>::ONE
671 );
672
673 assert_eq!(
674 NonZero::<U128>::from_le_bytes(hex!("00000000000000000000000000000000").into())
675 .into_option(),
676 None
677 );
678 }
679
680 #[test]
681 fn from_be_hex_when_nonzero() {
682 assert_eq!(
683 NonZero::<U128>::from_be_hex("00000000000000000000000000000001"),
684 NonZero::<U128>::ONE
685 );
686 }
687
688 #[test]
689 #[should_panic]
690 fn from_be_hex_when_zero() {
691 let _ = NonZero::<U128>::from_be_hex("00000000000000000000000000000000");
692 }
693
694 #[test]
695 fn from_le_hex_when_nonzero() {
696 assert_eq!(
697 NonZero::<U128>::from_le_hex("01000000000000000000000000000000"),
698 NonZero::<U128>::ONE
699 );
700 }
701
702 #[test]
703 #[should_panic]
704 fn from_le_hex_when_zero() {
705 let _ = NonZero::<U128>::from_le_hex("00000000000000000000000000000000");
706 }
707
708 #[test]
709 fn int_abs_sign() {
710 let x = I128::from(-55).to_nz().unwrap();
711 let (abs, sgn) = x.abs_sign();
712 assert_eq!(abs, U128::from(55u32).to_nz().unwrap());
713 assert!(sgn.to_bool());
714 }
715
716 #[test]
717 fn one() {
718 assert_eq!(
719 NonZero::<U128>::from_le_bytes(hex!("01000000000000000000000000000000").into())
720 .unwrap(),
721 NonZero::<U128>::one()
722 );
723 }
724
725 #[cfg(feature = "hybrid-array")]
726 #[test]
727 fn from_le_byte_array() {
728 assert_eq!(
729 NonZero::<U128>::from_le_byte_array(hex!("01000000000000000000000000000000").into())
730 .unwrap(),
731 NonZero::<U128>::ONE
732 );
733 }
734}