Skip to content

Commit e4d40fe

Browse files
committed
Derive NumCast for newtypes
1 parent 52e86e2 commit e4d40fe

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

src/lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,3 +496,22 @@ pub fn num_ops(input: TokenStream) -> TokenStream {
496496
}
497497
}).into()
498498
}
499+
500+
/// Derives [`num_traits::NumCast`][num_cast] for newtypes. The inner type must already implement
501+
/// `NumCast`.
502+
///
503+
/// [num_cast]: https://docs.rs/num-traits/0.2/num_traits/cast/trait.NumCast.html
504+
#[proc_macro_derive(NumCast)]
505+
pub fn num_cast(input: TokenStream) -> TokenStream {
506+
let ast: syn::DeriveInput = syn::parse(input).unwrap();
507+
let name = &ast.ident;
508+
let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
509+
dummy_const_trick("NumCast", &name, quote! {
510+
extern crate num_traits as _num_traits;
511+
impl _num_traits::NumCast for #name {
512+
fn from<T: _num_traits::ToPrimitive>(n: T) -> Option<Self> {
513+
<#inner_ty as _num_traits::NumCast>::from(n).map(#name)
514+
}
515+
}
516+
}).into()
517+
}

tests/newtype.rs

Lines changed: 7 additions & 1 deletion
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};
5+
use num_renamed::{FromPrimitive, ToPrimitive, NumCast};
66

77
#[derive(
88
Debug,
@@ -13,6 +13,7 @@ use num_renamed::{FromPrimitive, ToPrimitive};
1313
ToPrimitive,
1414
FromPrimitive,
1515
NumOps,
16+
NumCast,
1617
)]
1718
struct MyFloat(f64);
1819

@@ -34,3 +35,8 @@ fn test_num_ops() {
3435
assert_eq!(MyFloat(25.0) / MyFloat(10.0), MyFloat(2.5));
3536
assert_eq!(MyFloat(25.0) % MyFloat(10.0), MyFloat(5.0));
3637
}
38+
39+
#[test]
40+
fn test_num_cast() {
41+
assert_eq!(<MyFloat as NumCast>::from(25u8), Some(MyFloat(25.0)));
42+
}

0 commit comments

Comments
 (0)