From f6e6f319884fac5abb6274a9110baa12928abc14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tu=E1=BA=A5n-Anh=20Nguy=E1=BB=85n?= Date: Fri, 15 Mar 2024 21:57:18 +0700 Subject: [PATCH] feat: Support Rust's non-zero integer types --- CHANGELOG.md | 1 + Cargo.toml | 1 + guide/src/type-conversions.md | 6 ++++ src/types/integer.rs | 62 +++++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c386b5e..35d57ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] - Upgraded to Rust 2021 edition. - This also raised the minimum supported Rust version to 1.56. +- Added support for Rust's non-zero integer types. ## [0.18.0] - 2021-09-26 - Eliminated the build-time dependency on LLVM by putting the raw Rust bindings in source, instead of generating them at build time. This would also make builds faster. diff --git a/Cargo.toml b/Cargo.toml index 7d7c710..7d0348a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ rustc_version = "0.2.3" default = [] utf-8-validation = [] lossy-integer-conversion = [] +nonzero-integer-conversion = [] # This feature is intended as a workaround when building on new untested platforms. If the crate # cannot be built without this feature, please report the issue at # https://github.com/ubolonton/emacs-module-rs/issues/new. diff --git a/guide/src/type-conversions.md b/guide/src/type-conversions.md index c37857b..d7bf859 100644 --- a/guide/src/type-conversions.md +++ b/guide/src/type-conversions.md @@ -49,6 +49,12 @@ To disable this behavior, use the `lossy-integer-conversion` feature: features = ["lossy-integer-conversion"] ``` +Support for Rust's `NonZero` integer types is disabled by default. To enable it, use the `nonzero-integer-conversion` feature: +```toml +[dependencies.emacs] +features = ["nonzero-integer-conversion"] +``` + ## Strings By default, no utf-8 validation is done when converting Lisp strings into Rust strings, because the string data returned by Emacs is guaranteed to be valid utf-8 sequence. If you think you've otherwise encountered an Emacs bug, utf-8 validation can be enabled through a feature: diff --git a/src/types/integer.rs b/src/types/integer.rs index 60372b9..000880b 100644 --- a/src/types/integer.rs +++ b/src/types/integer.rs @@ -35,6 +35,42 @@ int_from_lisp!(u32); int_from_lisp!(u64); int_from_lisp!(usize); +// ------------------------------------------------------------------------------------------------- + +macro_rules! nonzero_int_from_lisp { + ($name:ident($primitive:ident)) => { + impl FromLisp<'_> for std::num::$name { + #[cfg(not(feature = "lossy-integer-conversion"))] + fn from_lisp(value: Value<'_>) -> Result { + let i: i64 = value.into_rust()?; + let i: $primitive = i.try_into()?; + Ok(i.try_into()?) + } + + #[cfg(feature = "lossy-integer-conversion")] + fn from_lisp(value: Value<'_>) -> Result { + let i: i64 = value.into_rust()?; + let i: $primitive = i as $primitive; + Ok(i.try_into()?) + } + } + } +} + +nonzero_int_from_lisp!(NonZeroU8(u8)); +nonzero_int_from_lisp!(NonZeroU16(u16)); +nonzero_int_from_lisp!(NonZeroU32(u32)); +nonzero_int_from_lisp!(NonZeroU64(u64)); +nonzero_int_from_lisp!(NonZeroUsize(usize)); + +nonzero_int_from_lisp!(NonZeroI8(i8)); +nonzero_int_from_lisp!(NonZeroI16(i16)); +nonzero_int_from_lisp!(NonZeroI32(i32)); +nonzero_int_from_lisp!(NonZeroI64(i64)); +nonzero_int_from_lisp!(NonZeroIsize(isize)); + +// ------------------------------------------------------------------------------------------------- + impl IntoLisp<'_> for i64 { fn into_lisp(self, env: &Env) -> Result> { unsafe_raw_call_value_unprotected!(env, make_integer, self) @@ -81,3 +117,29 @@ int_into_lisp!(isize, lossless); int_into_lisp!(u64, lossless); #[cfg(not(feature = "lossy-integer-conversion"))] int_into_lisp!(usize, lossless); + +// ------------------------------------------------------------------------------------------------- + +macro_rules! nonzero_int_into_lisp { + ($name:ident) => { + #[cfg(feature = "nonzero-integer-conversion")] + impl IntoLisp<'_> for std::num::$name { + #[inline] + fn into_lisp(self, env: &Env) -> Result> { + self.get().into_lisp(env) + } + } + }; +} + +nonzero_int_into_lisp!(NonZeroU8); +nonzero_int_into_lisp!(NonZeroU16); +nonzero_int_into_lisp!(NonZeroU32); +nonzero_int_into_lisp!(NonZeroU64); +nonzero_int_into_lisp!(NonZeroUsize); + +nonzero_int_into_lisp!(NonZeroI8); +nonzero_int_into_lisp!(NonZeroI16); +nonzero_int_into_lisp!(NonZeroI32); +nonzero_int_into_lisp!(NonZeroI64); +nonzero_int_into_lisp!(NonZeroIsize);