Skip to content

Commit 9d32e5f

Browse files
committed
Derive Num for newtypes
1 parent 5c21e21 commit 9d32e5f

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

src/lib.rs

+19
Original file line numberDiff line numberDiff line change
@@ -538,3 +538,22 @@ pub fn one(input: TokenStream) -> TokenStream {
538538
}
539539
}).into()
540540
}
541+
542+
/// Derives [`num_traits::Num`][num] for newtypes. The inner type must already implement `Num`.
543+
///
544+
/// [num]: https://docs.rs/num-traits/0.2/num_traits/trait.Num.html
545+
#[proc_macro_derive(Num)]
546+
pub fn num(input: TokenStream) -> TokenStream {
547+
let ast: syn::DeriveInput = syn::parse(input).unwrap();
548+
let name = &ast.ident;
549+
let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
550+
dummy_const_trick("Num", &name, quote! {
551+
extern crate num_traits as _num_traits;
552+
impl _num_traits::Num for #name {
553+
type FromStrRadixErr = <#inner_ty as _num_traits::Num>::FromStrRadixErr;
554+
fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
555+
<#inner_ty as _num_traits::Num>::from_str_radix(s, radix).map(#name)
556+
}
557+
}
558+
}).into()
559+
}

tests/newtype.rs

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

5-
use num_renamed::{FromPrimitive, ToPrimitive, NumCast, One, Zero};
5+
use num_renamed::{FromPrimitive, ToPrimitive, NumCast, One, Zero, Num};
66

77
#[derive(
88
Debug,
@@ -16,6 +16,7 @@ use num_renamed::{FromPrimitive, ToPrimitive, NumCast, One, Zero};
1616
NumCast,
1717
One,
1818
Zero,
19+
Num,
1920
)]
2021
struct MyFloat(f64);
2122

@@ -52,3 +53,8 @@ fn test_zero() {
5253
fn test_one() {
5354
assert_eq!(MyFloat::one(), MyFloat(1.0));
5455
}
56+
57+
#[test]
58+
fn test_num() {
59+
assert_eq!(MyFloat::from_str_radix("25", 10).ok(), Some(MyFloat(25.0)));
60+
}

0 commit comments

Comments
 (0)