//! 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::>(), 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 { 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::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 }