heveanly 0.1.0

C is the heavenly option
Documentation
// The code in this file is derived from rust-linux-errno by John Millikin. The
// original copyright notice has been retained below.

// Copyright (c) 2022 John Millikin <john@john-millikin.com>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
//
// SPDX-License-Identifier: 0BSD

/*
//! This library defines an [Error] struct that represents error numbers
//! returned from Linux system calls.
//!
//! On Linux, error numbers are architecture-specific. The [arch] modules
//! provide access to error numbers for all supported architectures, and the
//! top-level module re-exports error numbers for the current target platform.
*/
#![allow(unexpected_cfgs)]

use core::{fmt, num};

/*
/// Type for error numbers returned from Linux system calls.
///
/// The `Error` type implements `PartialEq` for many integer types, and
/// (optionally) with the POSIX error numbers defined in the [`posix-errno`]
/// library.
///
/// [`posix-errno`]: https://crates.io/crates/posix-errno
*/
#[cfg(feature = "nightly")]
#[repr(transparent)]
#[rustc_layout_scalar_valid_range_start(0x0000_0001)]
#[rustc_layout_scalar_valid_range_end(0x7fff_ffff)]
#[rustc_nonnull_optimization_guaranteed]
#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Errno(i32);

#[cfg(not(feature = "nightly"))]
#[repr(transparent)]
#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Errno(num::NonZeroI32);

impl Errno {
	/*
	/// Create a new error from a raw error number. If outside the permitted
	/// range `[1, 4096)` for Linux error numbers, returns `None`.
	*/
	#[inline]
	pub const fn new(errno: i32) -> Option<Self> {
		if errno <= 0 || 0xFFF < errno {
			return errno_out_of_range();
		}
		#[cfg(feature = "nightly")]
		return Some(unsafe { Self(errno) });
		#[cfg(not(feature = "nightly"))]
		Some(Self(unsafe { num::NonZeroI32::new_unchecked(errno) }))
	}

	/*
	/// Unsafely create a new error from a raw error number, without checking
	/// whether it's within the permitted range for Linux error numbers.
	///
	/// # Safety
	///
	/// The caller must ensure that `0 < errno <= 0xFFF`. In particular, it is
	/// undefined behavior if `errno` is zero.
	*/
	#[inline(always)]
	pub const unsafe fn new_unchecked(errno: i32) -> Self {
		#[cfg(feature = "nightly")]
		return Self(errno);
		#[cfg(not(feature = "nightly"))]
		Self(num::NonZeroI32::new_unchecked(errno))
	}

	/*
	/// Returns the error number as a primitive `u16`.
	*/
	#[inline(always)]
	pub const fn get(self) -> i32 {
		#[cfg(feature = "nightly")]
		return self.0;
		#[cfg(not(feature = "nightly"))]
		self.0.get()
	}

	/*
	/// Returns the error number as a [`NonZeroU16`](num::NonZeroU16).
	*/
	#[inline(always)]
	pub const fn get_nonzero(self) -> num::NonZeroI32 {
		#[cfg(feature = "nightly")]
		return unsafe { num::NonZeroI32::new_unchecked(self.0) };
		#[cfg(not(feature = "nightly"))]
		self.0
	}
}

#[cold]
#[inline]
const fn errno_out_of_range() -> Option<Errno> {
	None
}

macro_rules! errno_constants {
	(
		$( $(#[$meta:meta])* $name:ident = $value:literal ),+,
		{ $( $(#[$meta1:meta])* $name1:ident = $value1:ident, )+ },
	) => {
		$(
			$(#[$meta])*
			pub const $name: super::Errno = unsafe {
				super::Errno::new_unchecked($value)
			};
		)+
		$(
			$(#[$meta1])*
			pub const $name1: super::Errno = $value1;
		)*

		#[inline]
		pub(super) const fn err_name(err: super::Errno) -> Option<&'static str> {
			match err.get() {
			$(
				$value => Some(stringify!($name)),
			)+
				_ => None,
			}
		}
	}
}

#[cfg(any(
	target_arch = "arm",
	target_arch = "aarch64",
	target_arch = "m68k",
	target_arch = "powerpc",
	target_arch = "powerpc64",
	target_arch = "riscv32",
	target_arch = "riscv64",
	target_arch = "s390x",
	target_arch = "x86",
	target_arch = "x86_64",
))]
#[path = "errno/generic.rs"]
mod arch;

#[cfg(target_arch = "alpha")]
#[path = "errno/alpha.rs"]
mod arch;

#[cfg(any(target_arch = "mips", target_arch = "mips64"))]
#[path = "errno/mips.rs"]
mod arch;

#[cfg(target_arch = "parisc")]
#[path = "errno/parisc.rs"]
mod arch;

#[cfg(any(target_arch = "sparc", target_arch = "sparc64"))]
#[path = "errno/sparc.rs"]
mod arch;

pub use arch::*;

impl fmt::Debug for Errno {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		match arch::err_name(*self) {
			Some(name) => f.write_str(name),
			_ => f.debug_tuple("Error").field(&self.get()).finish(),
		}
	}
}