From f1e50050c2656f518b845094e11fda3955509ee4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Delabrouille?= Date: Mon, 3 Jul 2023 22:17:05 +0200 Subject: [PATCH 1/3] Add derive macro for num_traits::Signed --- src/lib.rs | 40 ++++++++++++++++++++++++++++++++++++++++ tests/newtype.rs | 8 +++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 26b9c77..8ba7b9a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -952,3 +952,43 @@ pub fn float(input: TokenStream) -> TokenStream { import.wrap("Float", &name, impl_).into() } + +/// Derives [`num_traits::Signed`][signed] for newtypes. The inner type must already implement +/// `Signed`. +/// +/// [signed]: https://docs.rs/num-traits/0.2/num_traits/sign/trait.Signed.html +#[proc_macro_derive(Signed, attributes(num_traits))] +pub fn signed(input: TokenStream) -> TokenStream { + let ast = parse!(input as syn::DeriveInput); + let name = &ast.ident; + let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY); + + let import = NumTraits::new(&ast); + + let impl_ = quote! { + impl #import::Signed for #name { + #[inline] + fn abs(&self) -> Self { + #name(<#inner_ty as #import::Signed>::abs(&self.0)) + } + #[inline] + fn abs_sub(&self, other: &Self) -> Self { + #name(<#inner_ty as #import::Signed>::abs_sub(&self.0, &other.0)) + } + #[inline] + fn signum(&self) -> Self { + #name(<#inner_ty as #import::Signed>::signum(&self.0)) + } + #[inline] + fn is_positive(&self) -> bool { + <#inner_ty as #import::Signed>::is_positive(&self.0) + } + #[inline] + fn is_negative(&self) -> bool { + <#inner_ty as #import::Signed>::is_negative(&self.0) + } + } + }; + + import.wrap("Signed", &name, impl_).into() +} diff --git a/tests/newtype.rs b/tests/newtype.rs index 6eafd09..e62fe24 100644 --- a/tests/newtype.rs +++ b/tests/newtype.rs @@ -2,7 +2,7 @@ extern crate num as num_renamed; #[macro_use] extern crate num_derive; -use crate::num_renamed::{Float, FromPrimitive, Num, NumCast, One, ToPrimitive, Zero}; +use crate::num_renamed::{Float, FromPrimitive, Num, NumCast, One, Signed, ToPrimitive, Zero}; use std::ops::Neg; #[derive( @@ -19,6 +19,7 @@ use std::ops::Neg; Zero, Num, Float, + Signed, )] struct MyFloat(f64); @@ -87,3 +88,8 @@ fn test_num() { fn test_float() { assert_eq!(MyFloat(4.0).log(MyFloat(2.0)), MyFloat(2.0)); } + +#[test] +fn test_signed() { + assert_eq!(MyFloat(-2.0).is_negative(), true) +} From 0a8f903337dee6d39bc3438d1dec8e172f788201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Delabrouille?= Date: Fri, 22 Sep 2023 15:46:52 +0200 Subject: [PATCH 2/3] add derive macro for trait Unsigned --- src/lib.rs | 18 ++++++++++++++++++ tests/newtype.rs | 15 ++++++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 8ba7b9a..62e8f4c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -992,3 +992,21 @@ pub fn signed(input: TokenStream) -> TokenStream { import.wrap("Signed", &name, impl_).into() } + +/// Derives [`num_traits::Unsigned`][unsigned]. The inner type must already implement +/// `Unsigned`. +/// +/// [unsigned]: https://docs.rs/num/latest/num/traits/trait.Unsigned.html +#[proc_macro_derive(Unsigned, attributes(num_traits))] +pub fn unsigned(input: TokenStream) -> TokenStream { + let ast = parse!(input as syn::DeriveInput); + let name = &ast.ident; + + let import = NumTraits::new(&ast); + + let impl_ = quote! { + impl #import::Unsigned for #name {} + }; + + import.wrap("Unsigned", &name, impl_).into() +} diff --git a/tests/newtype.rs b/tests/newtype.rs index e62fe24..6e49a7c 100644 --- a/tests/newtype.rs +++ b/tests/newtype.rs @@ -2,9 +2,22 @@ extern crate num as num_renamed; #[macro_use] extern crate num_derive; -use crate::num_renamed::{Float, FromPrimitive, Num, NumCast, One, Signed, ToPrimitive, Zero}; +use crate::num_renamed::{ + Float, FromPrimitive, Num, NumCast, One, Signed, ToPrimitive, Unsigned, Zero, +}; use std::ops::Neg; +#[derive(PartialEq, Zero, One, NumOps, Num, Unsigned)] +struct MyNum(u32); + +#[test] +fn test_derive_unsingned_works() { + fn do_nothing_on_unsigned(_input: impl Unsigned) {} + + let x = MyNum(42); + do_nothing_on_unsigned(x); +} + #[derive( Debug, Clone, From 3329097557c7fd6b64398a5da2232421f36b0d65 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Sat, 7 Oct 2023 15:09:53 -0700 Subject: [PATCH 3/3] Apply suggestions from code review --- tests/newtype.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/newtype.rs b/tests/newtype.rs index 6e49a7c..71b06b3 100644 --- a/tests/newtype.rs +++ b/tests/newtype.rs @@ -11,7 +11,7 @@ use std::ops::Neg; struct MyNum(u32); #[test] -fn test_derive_unsingned_works() { +fn test_derive_unsigned_works() { fn do_nothing_on_unsigned(_input: impl Unsigned) {} let x = MyNum(42); @@ -104,5 +104,5 @@ fn test_float() { #[test] fn test_signed() { - assert_eq!(MyFloat(-2.0).is_negative(), true) + assert!(MyFloat(-2.0).is_negative()) }