Skip to content

Commit 2c5013e

Browse files
bors[bot]tdelabrocuviper
authored
Merge #55
55: Add derive macro for num_traits::Signed r=cuviper a=tdelabro Co-authored-by: Timothée Delabrouille <[email protected]> Co-authored-by: Josh Stone <[email protected]>
2 parents 38d08c8 + 3329097 commit 2c5013e

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

src/lib.rs

+58
Original file line numberDiff line numberDiff line change
@@ -952,3 +952,61 @@ pub fn float(input: TokenStream) -> TokenStream {
952952

953953
import.wrap("Float", name, impl_).into()
954954
}
955+
956+
/// Derives [`num_traits::Signed`][signed] for newtypes. The inner type must already implement
957+
/// `Signed`.
958+
///
959+
/// [signed]: https://docs.rs/num-traits/0.2/num_traits/sign/trait.Signed.html
960+
#[proc_macro_derive(Signed, attributes(num_traits))]
961+
pub fn signed(input: TokenStream) -> TokenStream {
962+
let ast = parse!(input as syn::DeriveInput);
963+
let name = &ast.ident;
964+
let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
965+
966+
let import = NumTraits::new(&ast);
967+
968+
let impl_ = quote! {
969+
impl #import::Signed for #name {
970+
#[inline]
971+
fn abs(&self) -> Self {
972+
#name(<#inner_ty as #import::Signed>::abs(&self.0))
973+
}
974+
#[inline]
975+
fn abs_sub(&self, other: &Self) -> Self {
976+
#name(<#inner_ty as #import::Signed>::abs_sub(&self.0, &other.0))
977+
}
978+
#[inline]
979+
fn signum(&self) -> Self {
980+
#name(<#inner_ty as #import::Signed>::signum(&self.0))
981+
}
982+
#[inline]
983+
fn is_positive(&self) -> bool {
984+
<#inner_ty as #import::Signed>::is_positive(&self.0)
985+
}
986+
#[inline]
987+
fn is_negative(&self) -> bool {
988+
<#inner_ty as #import::Signed>::is_negative(&self.0)
989+
}
990+
}
991+
};
992+
993+
import.wrap("Signed", &name, impl_).into()
994+
}
995+
996+
/// Derives [`num_traits::Unsigned`][unsigned]. The inner type must already implement
997+
/// `Unsigned`.
998+
///
999+
/// [unsigned]: https://docs.rs/num/latest/num/traits/trait.Unsigned.html
1000+
#[proc_macro_derive(Unsigned, attributes(num_traits))]
1001+
pub fn unsigned(input: TokenStream) -> TokenStream {
1002+
let ast = parse!(input as syn::DeriveInput);
1003+
let name = &ast.ident;
1004+
1005+
let import = NumTraits::new(&ast);
1006+
1007+
let impl_ = quote! {
1008+
impl #import::Unsigned for #name {}
1009+
};
1010+
1011+
import.wrap("Unsigned", &name, impl_).into()
1012+
}

tests/newtype.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,22 @@ extern crate num as num_renamed;
22
#[macro_use]
33
extern crate num_derive;
44

5-
use crate::num_renamed::{Float, FromPrimitive, Num, NumCast, One, ToPrimitive, Zero};
5+
use crate::num_renamed::{
6+
Float, FromPrimitive, Num, NumCast, One, Signed, ToPrimitive, Unsigned, Zero,
7+
};
68
use std::ops::Neg;
79

10+
#[derive(PartialEq, Zero, One, NumOps, Num, Unsigned)]
11+
struct MyNum(u32);
12+
13+
#[test]
14+
fn test_derive_unsigned_works() {
15+
fn do_nothing_on_unsigned(_input: impl Unsigned) {}
16+
17+
let x = MyNum(42);
18+
do_nothing_on_unsigned(x);
19+
}
20+
821
#[derive(
922
Debug,
1023
Clone,
@@ -19,6 +32,7 @@ use std::ops::Neg;
1932
Zero,
2033
Num,
2134
Float,
35+
Signed,
2236
)]
2337
struct MyFloat(f64);
2438

@@ -87,3 +101,8 @@ fn test_num() {
87101
fn test_float() {
88102
assert_eq!(MyFloat(4.0).log(MyFloat(2.0)), MyFloat(2.0));
89103
}
104+
105+
#[test]
106+
fn test_signed() {
107+
assert!(MyFloat(-2.0).is_negative())
108+
}

0 commit comments

Comments
 (0)