semisafe 1.1.0

Semi-safe utilities for performance-critical Rust
Documentation
//! Provides semi-safe helpers for `NonZero` integer types.

use core::num::{
    NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize, NonZeroU8,
    NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize,
};

// This implementation is awful and I hate it, but it's necessary
// because `ZeroablePrimitive` will never be stabilized.

/// Returns a `NonZeroU8` without zero checks in release builds.
///
/// Use this only when surrounding code guarantees that `val` is not zero.
/// In debug builds this delegates to [`NonZeroU8::new`] and panics on zero.
/// In release builds, passing zero causes undefined behavior.
///
/// # Panics
///
/// Panics in debug builds if `val` is zero.
///
/// # Examples
///
/// ```
/// let value = semisafe::nonzero::new_u8(5);
/// assert_eq!(value.get(), 5);
/// ```
pub fn new_u8(val: u8) -> NonZeroU8 {
    #[cfg(debug_assertions)]
    {
        NonZeroU8::new(val).expect("value for NonZero type must not be zero")
    }

    #[cfg(not(debug_assertions))]
    {
        unsafe { core::num::NonZero::new_unchecked(val) }
    }
}

/// Returns a `NonZeroU16` without zero checks in release builds.
///
/// Use this only when surrounding code guarantees that `val` is not zero.
/// In debug builds this delegates to [`NonZeroU16::new`] and panics on zero.
/// In release builds, passing zero causes undefined behavior.
///
/// # Panics
///
/// Panics in debug builds if `val` is zero.
///
/// # Examples
///
/// ```
/// let value = semisafe::nonzero::new_u16(5);
/// assert_eq!(value.get(), 5);
/// ```
pub fn new_u16(val: u16) -> NonZeroU16 {
    #[cfg(debug_assertions)]
    {
        NonZeroU16::new(val).expect("value for NonZero type must not be zero")
    }

    #[cfg(not(debug_assertions))]
    {
        unsafe { core::num::NonZero::new_unchecked(val) }
    }
}

/// Returns a `NonZeroU32` without zero checks in release builds.
///
/// Use this only when surrounding code guarantees that `val` is not zero.
/// In debug builds this delegates to [`NonZeroU32::new`] and panics on zero.
/// In release builds, passing zero causes undefined behavior.
///
/// # Panics
///
/// Panics in debug builds if `val` is zero.
///
/// # Examples
///
/// ```
/// let value = semisafe::nonzero::new_u32(5);
/// assert_eq!(value.get(), 5);
/// ```
pub fn new_u32(val: u32) -> NonZeroU32 {
    #[cfg(debug_assertions)]
    {
        NonZeroU32::new(val).expect("value for NonZero type must not be zero")
    }

    #[cfg(not(debug_assertions))]
    {
        unsafe { core::num::NonZero::new_unchecked(val) }
    }
}

/// Returns a `NonZeroU64` without zero checks in release builds.
///
/// Use this only when surrounding code guarantees that `val` is not zero.
/// In debug builds this delegates to [`NonZeroU64::new`] and panics on zero.
/// In release builds, passing zero causes undefined behavior.
///
/// # Panics
///
/// Panics in debug builds if `val` is zero.
///
/// # Examples
///
/// ```
/// let value = semisafe::nonzero::new_u64(5);
/// assert_eq!(value.get(), 5);
/// ```
pub fn new_u64(val: u64) -> NonZeroU64 {
    #[cfg(debug_assertions)]
    {
        NonZeroU64::new(val).expect("value for NonZero type must not be zero")
    }

    #[cfg(not(debug_assertions))]
    {
        unsafe { core::num::NonZero::new_unchecked(val) }
    }
}

/// Returns a `NonZeroU128` without zero checks in release builds.
///
/// Use this only when surrounding code guarantees that `val` is not zero.
/// In debug builds this delegates to [`NonZeroU128::new`] and panics on zero.
/// In release builds, passing zero causes undefined behavior.
///
/// # Panics
///
/// Panics in debug builds if `val` is zero.
///
/// # Examples
///
/// ```
/// let value = semisafe::nonzero::new_u128(5);
/// assert_eq!(value.get(), 5);
/// ```
pub fn new_u128(val: u128) -> NonZeroU128 {
    #[cfg(debug_assertions)]
    {
        NonZeroU128::new(val).expect("value for NonZero type must not be zero")
    }

    #[cfg(not(debug_assertions))]
    {
        unsafe { core::num::NonZero::new_unchecked(val) }
    }
}

/// Returns a `NonZeroUsize` without zero checks in release builds.
///
/// Use this only when surrounding code guarantees that `val` is not zero.
/// In debug builds this delegates to [`NonZeroUsize::new`] and panics on zero.
/// In release builds, passing zero causes undefined behavior.
///
/// # Panics
///
/// Panics in debug builds if `val` is zero.
///
/// # Examples
///
/// ```
/// let value = semisafe::nonzero::new_usize(5);
/// assert_eq!(value.get(), 5);
/// ```
pub fn new_usize(val: usize) -> NonZeroUsize {
    #[cfg(debug_assertions)]
    {
        NonZeroUsize::new(val).expect("value for NonZero type must not be zero")
    }

    #[cfg(not(debug_assertions))]
    {
        unsafe { core::num::NonZero::new_unchecked(val) }
    }
}

/// Returns a `NonZeroI8` without zero checks in release builds.
///
/// Use this only when surrounding code guarantees that `val` is not zero.
/// In debug builds this delegates to [`NonZeroI8::new`] and panics on zero.
/// In release builds, passing zero causes undefined behavior.
///
/// # Panics
///
/// Panics in debug builds if `val` is zero.
///
/// # Examples
///
/// ```
/// let value = semisafe::nonzero::new_i8(5);
/// assert_eq!(value.get(), 5);
/// ```
pub fn new_i8(val: i8) -> NonZeroI8 {
    #[cfg(debug_assertions)]
    {
        NonZeroI8::new(val).expect("value for NonZero type must not be zero")
    }

    #[cfg(not(debug_assertions))]
    {
        unsafe { core::num::NonZero::new_unchecked(val) }
    }
}

/// Returns a `NonZeroI16` without zero checks in release builds.
///
/// Use this only when surrounding code guarantees that `val` is not zero.
/// In debug builds this delegates to [`NonZeroI16::new`] and panics on zero.
/// In release builds, passing zero causes undefined behavior.
///
/// # Panics
///
/// Panics in debug builds if `val` is zero.
///
/// # Examples
///
/// ```
/// let value = semisafe::nonzero::new_i16(5);
/// assert_eq!(value.get(), 5);
/// ```
pub fn new_i16(val: i16) -> NonZeroI16 {
    #[cfg(debug_assertions)]
    {
        NonZeroI16::new(val).expect("value for NonZero type must not be zero")
    }

    #[cfg(not(debug_assertions))]
    {
        unsafe { core::num::NonZero::new_unchecked(val) }
    }
}

/// Returns a `NonZeroI32` without zero checks in release builds.
///
/// Use this only when surrounding code guarantees that `val` is not zero.
/// In debug builds this delegates to [`NonZeroI32::new`] and panics on zero.
/// In release builds, passing zero causes undefined behavior.
///
/// # Panics
///
/// Panics in debug builds if `val` is zero.
///
/// # Examples
///
/// ```
/// let value = semisafe::nonzero::new_i32(5);
/// assert_eq!(value.get(), 5);
/// ```
pub fn new_i32(val: i32) -> NonZeroI32 {
    #[cfg(debug_assertions)]
    {
        NonZeroI32::new(val).expect("value for NonZero type must not be zero")
    }

    #[cfg(not(debug_assertions))]
    {
        unsafe { core::num::NonZero::new_unchecked(val) }
    }
}

/// Returns a `NonZeroI64` without zero checks in release builds.
///
/// Use this only when surrounding code guarantees that `val` is not zero.
/// In debug builds this delegates to [`NonZeroI64::new`] and panics on zero.
/// In release builds, passing zero causes undefined behavior.
///
/// # Panics
///
/// Panics in debug builds if `val` is zero.
///
/// # Examples
///
/// ```
/// let value = semisafe::nonzero::new_i64(5);
/// assert_eq!(value.get(), 5);
/// ```
pub fn new_i64(val: i64) -> NonZeroI64 {
    #[cfg(debug_assertions)]
    {
        NonZeroI64::new(val).expect("value for NonZero type must not be zero")
    }

    #[cfg(not(debug_assertions))]
    {
        unsafe { core::num::NonZero::new_unchecked(val) }
    }
}

/// Returns a `NonZeroI128` without zero checks in release builds.
///
/// Use this only when surrounding code guarantees that `val` is not zero.
/// In debug builds this delegates to [`NonZeroI128::new`] and panics on zero.
/// In release builds, passing zero causes undefined behavior.
///
/// # Panics
///
/// Panics in debug builds if `val` is zero.
///
/// # Examples
///
/// ```
/// let value = semisafe::nonzero::new_i128(5);
/// assert_eq!(value.get(), 5);
/// ```
pub fn new_i128(val: i128) -> NonZeroI128 {
    #[cfg(debug_assertions)]
    {
        NonZeroI128::new(val).expect("value for NonZero type must not be zero")
    }

    #[cfg(not(debug_assertions))]
    {
        unsafe { core::num::NonZero::new_unchecked(val) }
    }
}

/// Returns a `NonZeroIsize` without zero checks in release builds.
///
/// Use this only when surrounding code guarantees that `val` is not zero.
/// In debug builds this delegates to [`NonZeroIsize::new`] and panics on zero.
/// In release builds, passing zero causes undefined behavior.
///
/// # Panics
///
/// Panics in debug builds if `val` is zero.
///
/// # Examples
///
/// ```
/// let value = semisafe::nonzero::new_isize(5);
/// assert_eq!(value.get(), 5);
/// ```
pub fn new_isize(val: isize) -> NonZeroIsize {
    #[cfg(debug_assertions)]
    {
        NonZeroIsize::new(val).expect("value for NonZero type must not be zero")
    }

    #[cfg(not(debug_assertions))]
    {
        unsafe { core::num::NonZero::new_unchecked(val) }
    }
}