From 9d32e5fa070bf70c4e332230c51ce827396342ec Mon Sep 17 00:00:00 2001 From: Alex Sayers Date: Sat, 29 Sep 2018 21:28:07 +0900 Subject: [PATCH] Derive Num for newtypes --- src/lib.rs | 19 +++++++++++++++++++ tests/newtype.rs | 8 +++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 2c30849..4a510d2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -538,3 +538,22 @@ pub fn one(input: TokenStream) -> TokenStream { } }).into() } + +/// Derives [`num_traits::Num`][num] for newtypes. The inner type must already implement `Num`. +/// +/// [num]: https://docs.rs/num-traits/0.2/num_traits/trait.Num.html +#[proc_macro_derive(Num)] +pub fn num(input: TokenStream) -> TokenStream { + let ast: syn::DeriveInput = syn::parse(input).unwrap(); + let name = &ast.ident; + let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY); + dummy_const_trick("Num", &name, quote! { + extern crate num_traits as _num_traits; + impl _num_traits::Num for #name { + type FromStrRadixErr = <#inner_ty as _num_traits::Num>::FromStrRadixErr; + fn from_str_radix(s: &str, radix: u32) -> Result { + <#inner_ty as _num_traits::Num>::from_str_radix(s, radix).map(#name) + } + } + }).into() +} diff --git a/tests/newtype.rs b/tests/newtype.rs index cbdff4d..7136357 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 num_renamed::{FromPrimitive, ToPrimitive, NumCast, One, Zero}; +use num_renamed::{FromPrimitive, ToPrimitive, NumCast, One, Zero, Num}; #[derive( Debug, @@ -16,6 +16,7 @@ use num_renamed::{FromPrimitive, ToPrimitive, NumCast, One, Zero}; NumCast, One, Zero, + Num, )] struct MyFloat(f64); @@ -52,3 +53,8 @@ fn test_zero() { fn test_one() { assert_eq!(MyFloat::one(), MyFloat(1.0)); } + +#[test] +fn test_num() { + assert_eq!(MyFloat::from_str_radix("25", 10).ok(), Some(MyFloat(25.0))); +}