| //! Definitions of integer that is known not to equal zero. | |
| use crate::fmt; | |
| use crate::ops::{BitOr, BitOrAssign}; | |
| use crate::str::FromStr; | |
| use super::from_str_radix; | |
| use super::{IntErrorKind, ParseIntError}; | |
| macro_rules! doc_comment { | |
| ($x:expr, $($tt:tt)*) => { | |
| #[doc = $x] | |
| $($tt)* | |
| }; | |
| } | |
| macro_rules! impl_nonzero_fmt { | |
| ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { | |
| $( | |
| #[$stability] | |
| impl fmt::$Trait for $Ty { | |
| #[inline] | |
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| self.get().fmt(f) | |
| } | |
| } | |
| )+ | |
| } | |
| } | |
| macro_rules! nonzero_integers { | |
| ( $( #[$stability: meta] $Ty: ident($Int: ty); )+ ) => { | |
| $( | |
| doc_comment! { | |
| concat!("An integer that is known not to equal zero. | |
| This enables some memory layout optimization. | |
| For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`: | |
| ```rust | |
| use std::mem::size_of; | |
| assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", stringify!($Int), | |
| ">()); | |
| ```"), | |
| #[$stability] | |
| #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] | |
| #[repr(transparent)] | |
| #[rustc_layout_scalar_valid_range_start(1)] | |
| #[rustc_nonnull_optimization_guaranteed] | |
| pub struct $Ty($Int); | |
| } | |
| impl $Ty { | |
| /// Creates a non-zero without checking the value. | |
| /// | |
| /// # Safety | |
| /// | |
| /// The value must not be zero. | |
| #[$stability] | |
| #[rustc_const_stable(feature = "nonzero", since = "1.34.0")] | |
| #[inline] | |
| pub const unsafe fn new_unchecked(n: $Int) -> Self { | |
| // SAFETY: this is guaranteed to be safe by the caller. | |
| unsafe { Self(n) } | |
| } | |
| /// Creates a non-zero if the given value is not zero. | |
| #[$stability] | |
| #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")] | |
| #[inline] | |
| pub const fn new(n: $Int) -> Option<Self> { | |
| if n != 0 { | |
| // SAFETY: we just checked that there's no `0` | |
| Some(unsafe { Self(n) }) | |
| } else { | |
| None | |
| } | |
| } | |
| /// Returns the value as a primitive type. | |
| #[$stability] | |
| #[inline] | |
| #[rustc_const_stable(feature = "nonzero", since = "1.34.0")] | |
| pub const fn get(self) -> $Int { | |
| self.0 | |
| } | |
| } | |
| #[stable(feature = "from_nonzero", since = "1.31.0")] | |
| impl From<$Ty> for $Int { | |
| doc_comment! { | |
| concat!( | |
| "Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`"), | |
| #[inline] | |
| fn from(nonzero: $Ty) -> Self { | |
| nonzero.0 | |
| } | |
| } | |
| } | |
| #[stable(feature = "nonzero_bitor", since = "1.45.0")] | |
| impl BitOr for $Ty { | |
| type Output = Self; | |
| #[inline] | |
| fn bitor(self, rhs: Self) -> Self::Output { | |
| // SAFETY: since `self` and `rhs` are both nonzero, the | |
| // result of the bitwise-or will be nonzero. | |
| unsafe { $Ty::new_unchecked(self.get() | rhs.get()) } | |
| } | |
| } | |
| #[stable(feature = "nonzero_bitor", since = "1.45.0")] | |
| impl BitOr<$Int> for $Ty { | |
| type Output = Self; | |
| #[inline] | |
| fn bitor(self, rhs: $Int) -> Self::Output { | |
| // SAFETY: since `self` is nonzero, the result of the | |
| // bitwise-or will be nonzero regardless of the value of | |
| // `rhs`. | |
| unsafe { $Ty::new_unchecked(self.get() | rhs) } | |
| } | |
| } | |
| #[stable(feature = "nonzero_bitor", since = "1.45.0")] | |
| impl BitOr<$Ty> for $Int { | |
| type Output = $Ty; | |
| #[inline] | |
| fn bitor(self, rhs: $Ty) -> Self::Output { | |
| // SAFETY: since `rhs` is nonzero, the result of the | |
| // bitwise-or will be nonzero regardless of the value of | |
| // `self`. | |
| unsafe { $Ty::new_unchecked(self | rhs.get()) } | |
| } | |
| } | |
| #[stable(feature = "nonzero_bitor", since = "1.45.0")] | |
| impl BitOrAssign for $Ty { | |
| #[inline] | |
| fn bitor_assign(&mut self, rhs: Self) { | |
| *self = *self | rhs; | |
| } | |
| } | |
| #[stable(feature = "nonzero_bitor", since = "1.45.0")] | |
| impl BitOrAssign<$Int> for $Ty { | |
| #[inline] | |
| fn bitor_assign(&mut self, rhs: $Int) { | |
| *self = *self | rhs; | |
| } | |
| } | |
| impl_nonzero_fmt! { | |
| #[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty | |
| } | |
| )+ | |
| } | |
| } | |
| nonzero_integers! { | |
| #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8); | |
| #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16); | |
| #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32); | |
| #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64); | |
| #[stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128); | |
| #[stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize); | |
| #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8); | |
| #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16); | |
| #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32); | |
| #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64); | |
| #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128); | |
| #[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize); | |
| } | |
| macro_rules! from_str_radix_nzint_impl { | |
| ($($t:ty)*) => {$( | |
| #[stable(feature = "nonzero_parse", since = "1.35.0")] | |
| impl FromStr for $t { | |
| type Err = ParseIntError; | |
| fn from_str(src: &str) -> Result<Self, Self::Err> { | |
| Self::new(from_str_radix(src, 10)?) | |
| .ok_or(ParseIntError { | |
| kind: IntErrorKind::Zero | |
| }) | |
| } | |
| } | |
| )*} | |
| } | |
| from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize | |
| NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize } |