Skip to content

Commit f4c5102

Browse files
committed
Derive Zero and One for newtypes
1 parent c9d285d commit f4c5102

File tree

2 files changed

+55
-1
lines changed

2 files changed

+55
-1
lines changed

src/lib.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,3 +496,45 @@ pub fn num_cast(input: TokenStream) -> TokenStream {
496496
}
497497
}).into()
498498
}
499+
500+
/// Derives [`num_traits::Zero`][zero] for newtypes. The inner type must already implement `Zero`.
501+
///
502+
/// [zero]: https://docs.rs/num-traits/0.2/num_traits/cast/trait.Zero.html
503+
#[proc_macro_derive(Zero)]
504+
pub fn zero(input: TokenStream) -> TokenStream {
505+
let ast: syn::DeriveInput = syn::parse(input).unwrap();
506+
let name = &ast.ident;
507+
let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
508+
dummy_const_trick("Zero", &name, quote! {
509+
extern crate num_traits as _num_traits;
510+
impl _num_traits::Zero for #name {
511+
fn zero() -> Self {
512+
#name(<#inner_ty as _num_traits::Zero>::zero())
513+
}
514+
fn is_zero(&self) -> bool {
515+
<#inner_ty as _num_traits::Zero>::is_zero(&self.0)
516+
}
517+
}
518+
}).into()
519+
}
520+
521+
/// Derives [`num_traits::One`][one] for newtypes. The inner type must already implement `One`.
522+
///
523+
/// [one]: https://docs.rs/num-traits/0.2/num_traits/cast/trait.One.html
524+
#[proc_macro_derive(One)]
525+
pub fn one(input: TokenStream) -> TokenStream {
526+
let ast: syn::DeriveInput = syn::parse(input).unwrap();
527+
let name = &ast.ident;
528+
let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
529+
dummy_const_trick("One", &name, quote! {
530+
extern crate num_traits as _num_traits;
531+
impl _num_traits::One for #name {
532+
fn one() -> Self {
533+
#name(<#inner_ty as _num_traits::One>::one())
534+
}
535+
fn is_one(&self) -> bool {
536+
<#inner_ty as _num_traits::One>::is_one(&self.0)
537+
}
538+
}
539+
}).into()
540+
}

tests/newtype.rs

Lines changed: 13 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, NumCast};
5+
use num_renamed::{FromPrimitive, ToPrimitive, NumCast, One, Zero};
66

77
#[derive(
88
Debug,
@@ -14,6 +14,8 @@ use num_renamed::{FromPrimitive, ToPrimitive, NumCast};
1414
FromPrimitive,
1515
NumOps,
1616
NumCast,
17+
One,
18+
Zero,
1719
)]
1820
struct MyFloat(f64);
1921

@@ -40,3 +42,13 @@ fn test_num_ops() {
4042
fn test_num_cast() {
4143
assert_eq!(<MyFloat as NumCast>::from(25u8), Some(MyFloat(25.0)));
4244
}
45+
46+
#[test]
47+
fn test_zero() {
48+
assert_eq!(MyFloat::zero(), MyFloat(0.0));
49+
}
50+
51+
#[test]
52+
fn test_one() {
53+
assert_eq!(MyFloat::one(), MyFloat(1.0));
54+
}

0 commit comments

Comments
 (0)