diff --git a/.bumpversion.toml b/.bumpversion.toml index 1209c8a..051ac9d 100644 --- a/.bumpversion.toml +++ b/.bumpversion.toml @@ -4,7 +4,7 @@ # SPDX-License-Identifier: Apache-2.0 OR MIT [tool.bumpversion] -current_version = "0.7.14" +current_version = "0.8.0" [[tool.bumpversion.files]] filename = "CITATION.cff" diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1c3df4c..e792801 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,6 +4,11 @@ version: 2 updates: + - package-ecosystem: "cargo" + directory: "/" + schedule: + interval: "daily" + - package-ecosystem: "github-actions" directory: "/" schedule: diff --git a/.github/workflows/CI.yaml b/.github/workflows/CI.yaml index 8735a85..3e321d3 100644 --- a/.github/workflows/CI.yaml +++ b/.github/workflows/CI.yaml @@ -24,7 +24,7 @@ jobs: - aarch64-apple-darwin - x86_64-pc-windows-msvc toolchain: - - 1.61.0 # MSRV + - 1.65.0 # MSRV - stable - nightly include: diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index 723df91..88013b9 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -14,6 +14,16 @@ All notable changes to this project will be documented in this file. The format is based on https://keepachangelog.com/[Keep a Changelog], and this project adheres to https://semver.org/[Semantic Versioning]. +== {compare-url}/v0.7.14\...v0.8.0[0.8.0] - 2024-06-05 + +=== Added + +* Add conversion methods for integers to `ExitCode` ({pull-request-url}/92[#92]) + +=== Changed + +* Bump MSRV to 1.65.0 ({pull-request-url}/92[#92]) + == {compare-url}/v0.7.13\...v0.7.14[0.7.14] - 2024-05-19 === Changed diff --git a/CITATION.cff b/CITATION.cff index 8434517..80d5bc8 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -8,8 +8,8 @@ cff-version: 1.2.0 message: Please cite this software using these meta data. # Version information. -date-released: 2024-05-19 -version: 0.7.14 +date-released: 2024-06-05 +version: 0.8.0 # Project information. abstract: The system exit codes as defined by for Rust diff --git a/Cargo.lock b/Cargo.lock index c831f25..8efeed4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,388 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "bit-set" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +dependencies = [ + "bit-vec", +] + +[[package]] +name = "bit-vec" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "linux-raw-sys" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.85" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b476131c3c86cb68032fdc5cb6d5a1045e3e42d96b69fa599fd77701e1f5bf" +dependencies = [ + "bit-set", + "bit-vec", + "bitflags", + "lazy_static", + "num-traits", + "rand", + "rand_chacha", + "rand_xorshift", + "regex-syntax", + "rusty-fork", + "tempfile", + "unarray", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "rand_xorshift" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" +dependencies = [ + "rand_core", +] + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "rusty-fork" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +dependencies = [ + "fnv", + "quick-error", + "tempfile", + "wait-timeout", +] + +[[package]] +name = "structmeta" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ad9e09554f0456d67a69c1584c9798ba733a5b50349a6c0d0948710523922d" +dependencies = [ + "proc-macro2", + "quote", + "structmeta-derive", + "syn", +] + +[[package]] +name = "structmeta-derive" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a60bcaff7397072dca0017d1db428e30d5002e00b6847703e2e42005c95fbe00" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.66" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "sysexits" -version = "0.7.14" +version = "0.8.0" +dependencies = [ + "proptest", + "test-strategy", +] + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys", +] + +[[package]] +name = "test-strategy" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8361c808554228ad09bfed70f5c823caf8a3450b6881cc3a38eb57e8c08c1d9" +dependencies = [ + "proc-macro2", + "quote", + "structmeta", + "syn", +] + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" diff --git a/Cargo.toml b/Cargo.toml index 42949e5..2346926 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,10 +5,10 @@ [package] name = "sysexits" -version = "0.7.14" +version = "0.8.0" authors = ["Shun Sakai "] edition = "2021" -rust-version = "1.61.0" +rust-version = "1.65.0" description = "The system exit codes as defined by " documentation = "https://docs.rs/sysexits" readme = "README.md" @@ -41,6 +41,10 @@ required-features = ["default"] [dependencies] +[dev-dependencies] +proptest = "1.4.0" +test-strategy = "0.3.1" + [features] default = ["std"] std = [] diff --git a/README.md b/README.md index 44f10bc..7b2507a 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Add this to your `Cargo.toml`: ```toml [dependencies] -sysexits = "0.7.14" +sysexits = "0.8.0" ``` ### Example @@ -75,7 +75,7 @@ See the [documentation][docs-url] for more details. ## Minimum supported Rust version -The minimum supported Rust version (MSRV) of this library is v1.61.0. +The minimum supported Rust version (MSRV) of this library is v1.65.0. ## Changelog diff --git a/clippy.toml b/clippy.toml index 10aa7c9..20799c4 100644 --- a/clippy.toml +++ b/clippy.toml @@ -2,4 +2,4 @@ # # SPDX-License-Identifier: Apache-2.0 OR MIT -msrv = "1.61.0" +msrv = "1.65.0" diff --git a/src/error.rs b/src/error.rs index 67b9a19..97effac 100644 --- a/src/error.rs +++ b/src/error.rs @@ -5,8 +5,24 @@ //! Error types for this crate. -use std::fmt; +use core::fmt; +/// The error type indicating that [`ExitCode`](crate::ExitCode) was out of +/// range. +#[allow(clippy::module_name_repetitions)] +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct ExitCodeRangeError; + +impl fmt::Display for ExitCodeRangeError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "value is out of range for `ExitCode`") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for ExitCodeRangeError {} + +#[cfg(feature = "std")] /// An error which can be returned when converting an /// [`ExitCode`](crate::ExitCode) from an /// [`ExitStatus`](std::process::ExitStatus). @@ -14,6 +30,7 @@ use std::fmt; #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct TryFromExitStatusError(Option); +#[cfg(feature = "std")] impl TryFromExitStatusError { #[inline] pub(crate) const fn new(code: Option) -> Self { @@ -30,6 +47,7 @@ impl TryFromExitStatusError { } } +#[cfg(feature = "std")] impl fmt::Display for TryFromExitStatusError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(code) = self.code() { @@ -40,12 +58,52 @@ impl fmt::Display for TryFromExitStatusError { } } +#[cfg(feature = "std")] impl std::error::Error for TryFromExitStatusError {} #[cfg(test)] mod tests { use super::*; + #[test] + fn clone_exit_code_range_error() { + assert_eq!(ExitCodeRangeError.clone(), ExitCodeRangeError); + } + + #[test] + fn copy_exit_code_range_error() { + let a = ExitCodeRangeError; + let b = a; + assert_eq!(a, b); + } + + #[test] + fn debug_exit_code_range_error() { + assert_eq!(format!("{ExitCodeRangeError:?}"), "ExitCodeRangeError"); + } + + #[test] + fn exit_code_range_error_equality() { + assert_eq!(ExitCodeRangeError, ExitCodeRangeError); + } + + #[test] + fn display_exit_code_range_error() { + assert_eq!( + format!("{ExitCodeRangeError}"), + "value is out of range for `ExitCode`" + ); + } + + #[cfg(feature = "std")] + #[test] + fn source_exit_code_range_error() { + use std::error::Error; + + assert!(ExitCodeRangeError.source().is_none()); + } + + #[cfg(feature = "std")] #[test] fn clone_try_from_exit_status_error() { assert_eq!( @@ -58,6 +116,7 @@ mod tests { ); } + #[cfg(feature = "std")] #[test] fn copy_try_from_exit_status_error() { { @@ -72,6 +131,7 @@ mod tests { } } + #[cfg(feature = "std")] #[test] fn debug_try_from_exit_status_error() { assert_eq!( @@ -84,6 +144,7 @@ mod tests { ); } + #[cfg(feature = "std")] #[test] fn try_from_exit_status_error_equality() { assert_eq!( @@ -104,12 +165,14 @@ mod tests { ); } + #[cfg(feature = "std")] #[test] fn code_try_from_exit_status_error() { assert_eq!(TryFromExitStatusError::new(Some(1)).code(), Some(1)); assert_eq!(TryFromExitStatusError::new(None).code(), None); } + #[cfg(feature = "std")] #[test] fn display_try_from_exit_status_error() { assert_eq!( @@ -122,6 +185,7 @@ mod tests { ); } + #[cfg(feature = "std")] #[test] fn source_try_from_exit_status_error() { use std::error::Error; diff --git a/src/exit_code/convert.rs b/src/exit_code/convert.rs index 26a9d78..c36d9de 100644 --- a/src/exit_code/convert.rs +++ b/src/exit_code/convert.rs @@ -6,9 +6,11 @@ //! Implementations of conversions between [`ExitCode`] and other types. +use crate::error::ExitCodeRangeError; + use super::ExitCode; -macro_rules! impl_from_exit_code_for_integer { +macro_rules! impl_from_exit_code_to_integer { ($T:ty, $ok:expr, $usage:expr) => { impl From for $T { /// Converts an `ExitCode` into the raw underlying integer value. @@ -30,7 +32,7 @@ macro_rules! impl_from_exit_code_for_integer { } }; ($T:ty) => { - impl_from_exit_code_for_integer!( + impl_from_exit_code_to_integer!( $T, concat!("assert_eq!(", stringify!($T), "::from(ExitCode::Ok), 0);"), concat!( @@ -41,18 +43,18 @@ macro_rules! impl_from_exit_code_for_integer { ); }; } -impl_from_exit_code_for_integer!(i8); -impl_from_exit_code_for_integer!(i16); -impl_from_exit_code_for_integer!(i32); -impl_from_exit_code_for_integer!(i64); -impl_from_exit_code_for_integer!(i128); -impl_from_exit_code_for_integer!(isize); -impl_from_exit_code_for_integer!(u8); -impl_from_exit_code_for_integer!(u16); -impl_from_exit_code_for_integer!(u32); -impl_from_exit_code_for_integer!(u64); -impl_from_exit_code_for_integer!(u128); -impl_from_exit_code_for_integer!(usize); +impl_from_exit_code_to_integer!(i8); +impl_from_exit_code_to_integer!(i16); +impl_from_exit_code_to_integer!(i32); +impl_from_exit_code_to_integer!(i64); +impl_from_exit_code_to_integer!(i128); +impl_from_exit_code_to_integer!(isize); +impl_from_exit_code_to_integer!(u8); +impl_from_exit_code_to_integer!(u16); +impl_from_exit_code_to_integer!(u32); +impl_from_exit_code_to_integer!(u64); +impl_from_exit_code_to_integer!(u128); +impl_from_exit_code_to_integer!(usize); #[cfg(feature = "std")] impl From for std::process::ExitCode { @@ -65,6 +67,85 @@ impl From for std::process::ExitCode { } } +macro_rules! impl_try_from_integer_to_exit_code { + ($T:ty, $ok:expr, $usage:expr, $err:expr) => { + impl TryFrom<$T> for ExitCode { + type Error = ExitCodeRangeError; + + /// Converts an integer value into an `ExitCode`. + /// + /// # Errors + /// + /// Returns [`Err`] if `value` is not `0` or `64..=78`. + /// + /// # Examples + /// + /// ``` + /// # use sysexits::ExitCode; + /// # + #[doc = $ok] + #[doc = $usage] + /// + #[doc = $err] + /// ``` + #[inline] + fn try_from(value: $T) -> core::result::Result { + match value { + 0 => Ok(Self::Ok), + 64 => Ok(Self::Usage), + 65 => Ok(Self::DataErr), + 66 => Ok(Self::NoInput), + 67 => Ok(Self::NoUser), + 68 => Ok(Self::NoHost), + 69 => Ok(Self::Unavailable), + 70 => Ok(Self::Software), + 71 => Ok(Self::OsErr), + 72 => Ok(Self::OsFile), + 73 => Ok(Self::CantCreat), + 74 => Ok(Self::IoErr), + 75 => Ok(Self::TempFail), + 76 => Ok(Self::Protocol), + 77 => Ok(Self::NoPerm), + 78 => Ok(Self::Config), + _ => Err(ExitCodeRangeError), + } + } + } + }; + ($T:ty) => { + impl_try_from_integer_to_exit_code!( + $T, + concat!( + "assert_eq!(ExitCode::try_from(0_", + stringify!($T), + ").unwrap(), ExitCode::Ok);" + ), + concat!( + "assert_eq!(ExitCode::try_from(64_", + stringify!($T), + ").unwrap(), ExitCode::Usage);" + ), + concat!( + "assert!(ExitCode::try_from(79_", + stringify!($T), + ").is_err());" + ) + ); + }; +} +impl_try_from_integer_to_exit_code!(i8); +impl_try_from_integer_to_exit_code!(i16); +impl_try_from_integer_to_exit_code!(i32); +impl_try_from_integer_to_exit_code!(i64); +impl_try_from_integer_to_exit_code!(i128); +impl_try_from_integer_to_exit_code!(isize); +impl_try_from_integer_to_exit_code!(u8); +impl_try_from_integer_to_exit_code!(u16); +impl_try_from_integer_to_exit_code!(u32); +impl_try_from_integer_to_exit_code!(u64); +impl_try_from_integer_to_exit_code!(u128); +impl_try_from_integer_to_exit_code!(usize); + #[cfg(feature = "std")] impl From for ExitCode { /// Converts an [`Error`](std::io::Error) into an `ExitCode`. @@ -296,6 +377,258 @@ mod tests { ); } + macro_rules! test_try_from_integer_to_exit_code { + ($T:ty, $name:ident) => { + #[test] + fn $name() { + assert_eq!(ExitCode::try_from(0 as $T).unwrap(), ExitCode::Ok); + assert_eq!(ExitCode::try_from(64 as $T).unwrap(), ExitCode::Usage); + assert_eq!(ExitCode::try_from(65 as $T).unwrap(), ExitCode::DataErr); + assert_eq!(ExitCode::try_from(66 as $T).unwrap(), ExitCode::NoInput); + assert_eq!(ExitCode::try_from(67 as $T).unwrap(), ExitCode::NoUser); + assert_eq!(ExitCode::try_from(68 as $T).unwrap(), ExitCode::NoHost); + assert_eq!(ExitCode::try_from(69 as $T).unwrap(), ExitCode::Unavailable); + assert_eq!(ExitCode::try_from(70 as $T).unwrap(), ExitCode::Software); + assert_eq!(ExitCode::try_from(71 as $T).unwrap(), ExitCode::OsErr); + assert_eq!(ExitCode::try_from(72 as $T).unwrap(), ExitCode::OsFile); + assert_eq!(ExitCode::try_from(73 as $T).unwrap(), ExitCode::CantCreat); + assert_eq!(ExitCode::try_from(74 as $T).unwrap(), ExitCode::IoErr); + assert_eq!(ExitCode::try_from(75 as $T).unwrap(), ExitCode::TempFail); + assert_eq!(ExitCode::try_from(76 as $T).unwrap(), ExitCode::Protocol); + assert_eq!(ExitCode::try_from(77 as $T).unwrap(), ExitCode::NoPerm); + assert_eq!(ExitCode::try_from(78 as $T).unwrap(), ExitCode::Config); + } + }; + } + test_try_from_integer_to_exit_code!(i8, try_from_i8_to_exit_code); + test_try_from_integer_to_exit_code!(i16, try_from_i16_to_exit_code); + test_try_from_integer_to_exit_code!(i32, try_from_i32_to_exit_code); + test_try_from_integer_to_exit_code!(i64, try_from_i64_to_exit_code); + test_try_from_integer_to_exit_code!(i128, try_from_i128_to_exit_code); + test_try_from_integer_to_exit_code!(isize, try_from_isize_to_exit_code); + test_try_from_integer_to_exit_code!(u8, try_from_u8_to_exit_code); + test_try_from_integer_to_exit_code!(u16, try_from_u16_to_exit_code); + test_try_from_integer_to_exit_code!(u32, try_from_u32_to_exit_code); + test_try_from_integer_to_exit_code!(u64, try_from_u64_to_exit_code); + test_try_from_integer_to_exit_code!(u128, try_from_u128_to_exit_code); + test_try_from_integer_to_exit_code!(usize, try_from_usize_to_exit_code); + + macro_rules! test_try_from_integer_to_exit_code_when_out_of_range { + ($T:ty, $name:ident) => { + #[test] + fn $name() { + assert_eq!( + ExitCode::try_from(79 as $T).unwrap_err(), + ExitCodeRangeError + ); + } + }; + } + test_try_from_integer_to_exit_code_when_out_of_range!( + i8, + try_from_i8_to_exit_code_when_out_of_range + ); + test_try_from_integer_to_exit_code_when_out_of_range!( + i16, + try_from_i16_to_exit_code_when_out_of_range + ); + test_try_from_integer_to_exit_code_when_out_of_range!( + i32, + try_from_i32_to_exit_code_when_out_of_range + ); + test_try_from_integer_to_exit_code_when_out_of_range!( + i64, + try_from_i64_to_exit_code_when_out_of_range + ); + test_try_from_integer_to_exit_code_when_out_of_range!( + i128, + try_from_i128_to_exit_code_when_out_of_range + ); + test_try_from_integer_to_exit_code_when_out_of_range!( + isize, + try_from_isize_to_exit_code_when_out_of_range + ); + test_try_from_integer_to_exit_code_when_out_of_range!( + u8, + try_from_u8_to_exit_code_when_out_of_range + ); + test_try_from_integer_to_exit_code_when_out_of_range!( + u16, + try_from_u16_to_exit_code_when_out_of_range + ); + test_try_from_integer_to_exit_code_when_out_of_range!( + u32, + try_from_u32_to_exit_code_when_out_of_range + ); + test_try_from_integer_to_exit_code_when_out_of_range!( + u64, + try_from_u64_to_exit_code_when_out_of_range + ); + test_try_from_integer_to_exit_code_when_out_of_range!( + u128, + try_from_u128_to_exit_code_when_out_of_range + ); + test_try_from_integer_to_exit_code_when_out_of_range!( + usize, + try_from_usize_to_exit_code_when_out_of_range + ); + + macro_rules! test_try_from_integer_to_exit_code_when_negative_integer_roundtrip { + ($T:ty, $name:ident) => { + #[cfg(feature = "std")] + #[test_strategy::proptest] + fn $name(#[strategy(..<$T>::default())] v: $T) { + use proptest::prop_assert_eq; + + prop_assert_eq!(ExitCode::try_from(v).unwrap_err(), ExitCodeRangeError); + } + }; + } + test_try_from_integer_to_exit_code_when_negative_integer_roundtrip!( + i8, + try_from_i8_to_exit_code_when_negative_i8_roundtrip + ); + test_try_from_integer_to_exit_code_when_negative_integer_roundtrip!( + i16, + try_from_i16_to_exit_code_when_negative_i16_roundtrip + ); + test_try_from_integer_to_exit_code_when_negative_integer_roundtrip!( + i32, + try_from_i32_to_exit_code_when_negative_i32_roundtrip + ); + test_try_from_integer_to_exit_code_when_negative_integer_roundtrip!( + i64, + try_from_i64_to_exit_code_when_negative_i64_roundtrip + ); + test_try_from_integer_to_exit_code_when_negative_integer_roundtrip!( + i128, + try_from_i128_to_exit_code_when_negative_i128_roundtrip + ); + test_try_from_integer_to_exit_code_when_negative_integer_roundtrip!( + isize, + try_from_isize_to_exit_code_when_negative_isize_roundtrip + ); + + macro_rules! test_try_from_integer_to_exit_code_when_middle_integer_roundtrip { + ($T:ty, $name:ident) => { + #[cfg(feature = "std")] + #[test_strategy::proptest] + fn $name(#[strategy(1..(64 as $T))] v: $T) { + use proptest::prop_assert_eq; + + prop_assert_eq!(ExitCode::try_from(v).unwrap_err(), ExitCodeRangeError); + } + }; + } + test_try_from_integer_to_exit_code_when_middle_integer_roundtrip!( + i8, + try_from_i8_to_exit_code_when_middle_i8_roundtrip + ); + test_try_from_integer_to_exit_code_when_middle_integer_roundtrip!( + i16, + try_from_i16_to_exit_code_when_middle_i16_roundtrip + ); + test_try_from_integer_to_exit_code_when_middle_integer_roundtrip!( + i32, + try_from_i32_to_exit_code_when_middle_i32_roundtrip + ); + test_try_from_integer_to_exit_code_when_middle_integer_roundtrip!( + i64, + try_from_i64_to_exit_code_when_middle_i64_roundtrip + ); + test_try_from_integer_to_exit_code_when_middle_integer_roundtrip!( + i128, + try_from_i128_to_exit_code_when_middle_i128_roundtrip + ); + test_try_from_integer_to_exit_code_when_middle_integer_roundtrip!( + isize, + try_from_isize_to_exit_code_when_middle_isize_roundtrip + ); + test_try_from_integer_to_exit_code_when_middle_integer_roundtrip!( + u8, + try_from_u8_to_exit_code_when_middle_u8_roundtrip + ); + test_try_from_integer_to_exit_code_when_middle_integer_roundtrip!( + u16, + try_from_u16_to_exit_code_when_middle_u16_roundtrip + ); + test_try_from_integer_to_exit_code_when_middle_integer_roundtrip!( + u32, + try_from_u32_to_exit_code_when_middle_u32_roundtrip + ); + test_try_from_integer_to_exit_code_when_middle_integer_roundtrip!( + u64, + try_from_u64_to_exit_code_when_middle_u64_roundtrip + ); + test_try_from_integer_to_exit_code_when_middle_integer_roundtrip!( + u128, + try_from_u128_to_exit_code_when_middle_u128_roundtrip + ); + test_try_from_integer_to_exit_code_when_middle_integer_roundtrip!( + usize, + try_from_usize_to_exit_code_when_middle_usize_roundtrip + ); + + macro_rules! test_try_from_integer_to_exit_code_when_positive_integer_roundtrip { + ($T:ty, $name:ident) => { + #[cfg(feature = "std")] + #[test_strategy::proptest] + fn $name(#[strategy((79 as $T)..)] v: $T) { + use proptest::prop_assert_eq; + + prop_assert_eq!(ExitCode::try_from(v).unwrap_err(), ExitCodeRangeError); + } + }; + } + test_try_from_integer_to_exit_code_when_positive_integer_roundtrip!( + i8, + try_from_i8_to_exit_code_when_positive_i8_roundtrip + ); + test_try_from_integer_to_exit_code_when_positive_integer_roundtrip!( + i16, + try_from_i16_to_exit_code_when_positive_i16_roundtrip + ); + test_try_from_integer_to_exit_code_when_positive_integer_roundtrip!( + i32, + try_from_i32_to_exit_code_when_positive_i32_roundtrip + ); + test_try_from_integer_to_exit_code_when_positive_integer_roundtrip!( + i64, + try_from_i64_to_exit_code_when_positive_i64_roundtrip + ); + test_try_from_integer_to_exit_code_when_positive_integer_roundtrip!( + i128, + try_from_i128_to_exit_code_when_positive_i128_roundtrip + ); + test_try_from_integer_to_exit_code_when_positive_integer_roundtrip!( + isize, + try_from_isize_to_exit_code_when_positive_isize_roundtrip + ); + test_try_from_integer_to_exit_code_when_positive_integer_roundtrip!( + u8, + try_from_u8_to_exit_code_when_positive_u8_roundtrip + ); + test_try_from_integer_to_exit_code_when_positive_integer_roundtrip!( + u16, + try_from_u16_to_exit_code_when_positive_u16_roundtrip + ); + test_try_from_integer_to_exit_code_when_positive_integer_roundtrip!( + u32, + try_from_u32_to_exit_code_when_positive_u32_roundtrip + ); + test_try_from_integer_to_exit_code_when_positive_integer_roundtrip!( + u64, + try_from_u64_to_exit_code_when_positive_u64_roundtrip + ); + test_try_from_integer_to_exit_code_when_positive_integer_roundtrip!( + u128, + try_from_u128_to_exit_code_when_positive_u128_roundtrip + ); + test_try_from_integer_to_exit_code_when_positive_integer_roundtrip!( + usize, + try_from_usize_to_exit_code_when_positive_usize_roundtrip + ); + #[cfg(feature = "std")] #[allow(clippy::too_many_lines)] #[test] diff --git a/src/lib.rs b/src/lib.rs index 3358709..832c706 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -42,7 +42,7 @@ //! [``]: https://man.openbsd.org/sysexits #![cfg_attr(feature = "extended_io_error", feature(io_error_more))] -#![doc(html_root_url = "https://docs.rs/sysexits/0.7.14/")] +#![doc(html_root_url = "https://docs.rs/sysexits/0.8.0/")] #![no_std] #![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))] // Lint levels of rustc. @@ -58,10 +58,7 @@ extern crate alloc; #[cfg(feature = "std")] extern crate std; -#[cfg(feature = "std")] -mod error; +pub mod error; mod exit_code; -#[cfg(feature = "std")] -pub use crate::error::TryFromExitStatusError; pub use crate::exit_code::{result::Result, ExitCode};