1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10 
11 #![crate_type = "proc-macro"]
12 #![doc(html_root_url = "https://docs.rs/num-derive/0.3")]
13 #![recursion_limit = "512"]
14 
15 //! Procedural macros to derive numeric traits in Rust.
16 //!
17 //! ## Usage
18 //!
19 //! Add this to your `Cargo.toml`:
20 //!
21 //! ```toml
22 //! [dependencies]
23 //! num-traits = "0.2"
24 //! num-derive = "0.3"
25 //! ```
26 //!
27 //! Then you can derive traits on your own types:
28 //!
29 //! ```rust
30 //! #[macro_use]
31 //! extern crate num_derive;
32 //!
33 //! #[derive(FromPrimitive, ToPrimitive)]
34 //! enum Color {
35 //!     Red,
36 //!     Blue,
37 //!     Green,
38 //! }
39 //! # fn main() {}
40 //! ```
41 //!
42 //! ## Explicit import
43 //!
44 //! By default the `num_derive` procedural macros assume that the
45 //! `num_traits` crate is a direct dependency. If `num_traits` is instead
46 //! a transitive dependency, the `num_traits` helper attribute can be
47 //! used to tell `num_derive` to use a specific identifier for its imports.
48 //!
49 //! ```rust
50 //! #[macro_use]
51 //! extern crate num_derive;
52 //! // Lets pretend this is a transitive dependency from another crate
53 //! // reexported as `some_other_ident`.
54 //! extern crate num_traits as some_other_ident;
55 //!
56 //! #[derive(FromPrimitive, ToPrimitive)]
57 //! #[num_traits = "some_other_ident"]
58 //! enum Color {
59 //!     Red,
60 //!     Blue,
61 //!     Green,
62 //! }
63 //! # fn main() {}
64 //! ```
65 
66 extern crate proc_macro;
67 
68 use proc_macro::TokenStream;
69 use proc_macro2::{Span, TokenStream as TokenStream2};
70 use quote::quote;
71 use syn::{Data, Fields, Ident};
72 
73 /// Try to parse the tokens, or else return a compilation error
74 /// suggesting "full-syntax" if that's not already enabled.
75 macro_rules! parse {
76     ($tokens:ident as $type:ty) => {
77         match syn::parse::<$type>($tokens) {
78             Ok(parsed) => parsed,
79             Err(mut error) => {
80                 if cfg!(not(feature = "full-syntax")) {
81                     let hint = syn::Error::new(
82                         Span::call_site(),
83                         r#"this might need the "full-syntax" feature of `num-derive`"#,
84                     );
85                     error.combine(hint);
86                 }
87                 return TokenStream::from(error.to_compile_error());
88             }
89         }
90     };
91 }
92 
93 // Within `exp`, you can bring things into scope with `extern crate`.
94 //
95 // We don't want to assume that `num_traits::` is in scope - the user may have imported it under a
96 // different name, or may have imported it in a non-toplevel module (common when putting impls
97 // behind a feature gate).
98 //
99 // Solution: let's just generate `extern crate num_traits as _num_traits` and then refer to
100 // `_num_traits` in the derived code.  However, macros are not allowed to produce `extern crate`
101 // statements at the toplevel.
102 //
103 // Solution: let's generate `mod _impl_foo` and import num_traits within that.  However, now we
104 // lose access to private members of the surrounding module.  This is a problem if, for example,
105 // we're deriving for a newtype, where the inner type is defined in the same module, but not
106 // exported.
107 //
108 // Solution: use the dummy const trick.  For some reason, `extern crate` statements are allowed
109 // here, but everything from the surrounding module is in scope.  This trick is taken from serde.
dummy_const_trick(trait_: &str, name: &Ident, exp: TokenStream2) -> TokenStream2110 fn dummy_const_trick(trait_: &str, name: &Ident, exp: TokenStream2) -> TokenStream2 {
111     let dummy_const = Ident::new(
112         &format!("_IMPL_NUM_{}_FOR_{}", trait_, unraw(name)),
113         Span::call_site(),
114     );
115     quote! {
116         #[allow(non_upper_case_globals, unused_qualifications)]
117         const #dummy_const: () = {
118             #[allow(clippy::useless_attribute)]
119             #[allow(rust_2018_idioms)]
120             extern crate num_traits as _num_traits;
121             #exp
122         };
123     }
124 }
125 
unraw(ident: &Ident) -> String126 fn unraw(ident: &Ident) -> String {
127     ident.to_string().trim_start_matches("r#").to_owned()
128 }
129 
130 // If `data` is a newtype, return the type it's wrapping.
newtype_inner(data: &syn::Data) -> Option<syn::Type>131 fn newtype_inner(data: &syn::Data) -> Option<syn::Type> {
132     match *data {
133         Data::Struct(ref s) => {
134             match s.fields {
135                 Fields::Unnamed(ref fs) => {
136                     if fs.unnamed.len() == 1 {
137                         Some(fs.unnamed[0].ty.clone())
138                     } else {
139                         None
140                     }
141                 }
142                 Fields::Named(ref fs) => {
143                     if fs.named.len() == 1 {
144                         panic!("num-derive doesn't know how to handle newtypes with named fields yet. \
145                            Please use a tuple-style newtype, or submit a PR!");
146                     }
147                     None
148                 }
149                 _ => None,
150             }
151         }
152         _ => None,
153     }
154 }
155 
156 struct NumTraits {
157     import: Ident,
158     explicit: bool,
159 }
160 
161 impl quote::ToTokens for NumTraits {
to_tokens(&self, tokens: &mut TokenStream2)162     fn to_tokens(&self, tokens: &mut TokenStream2) {
163         self.import.to_tokens(tokens);
164     }
165 }
166 
167 impl NumTraits {
new(ast: &syn::DeriveInput) -> Self168     fn new(ast: &syn::DeriveInput) -> Self {
169         // If there is a `num_traits` MetaNameValue attribute on the input,
170         // retrieve its value, and use it to create an `Ident` to be used
171         // to import the `num_traits` crate.
172         for attr in &ast.attrs {
173             if let Ok(syn::Meta::NameValue(mnv)) = attr.parse_meta() {
174                 if mnv.path.is_ident("num_traits") {
175                     if let syn::Lit::Str(lit_str) = mnv.lit {
176                         return NumTraits {
177                             import: syn::Ident::new(&lit_str.value(), lit_str.span()),
178                             explicit: true,
179                         };
180                     } else {
181                         panic!("#[num_traits] attribute value must be a str");
182                     }
183                 }
184             }
185         }
186 
187         // Otherwise, we'll implicitly import our own.
188         NumTraits {
189             import: Ident::new("_num_traits", Span::call_site()),
190             explicit: false,
191         }
192     }
193 
wrap(&self, trait_: &str, name: &Ident, output: TokenStream2) -> TokenStream2194     fn wrap(&self, trait_: &str, name: &Ident, output: TokenStream2) -> TokenStream2 {
195         if self.explicit {
196             output
197         } else {
198             dummy_const_trick(trait_, &name, output)
199         }
200     }
201 }
202 
203 /// Derives [`num_traits::FromPrimitive`][from] for simple enums and newtypes.
204 ///
205 /// [from]: https://docs.rs/num-traits/0.2/num_traits/cast/trait.FromPrimitive.html
206 ///
207 /// # Examples
208 ///
209 /// Simple enums can be derived:
210 ///
211 /// ```rust
212 /// # #[macro_use]
213 /// # extern crate num_derive;
214 ///
215 /// #[derive(FromPrimitive)]
216 /// enum Color {
217 ///     Red,
218 ///     Blue,
219 ///     Green = 42,
220 /// }
221 /// # fn main() {}
222 /// ```
223 ///
224 /// Enums that contain data are not allowed:
225 ///
226 /// ```compile_fail
227 /// # #[macro_use]
228 /// # extern crate num_derive;
229 ///
230 /// #[derive(FromPrimitive)]
231 /// enum Color {
232 ///     Rgb(u8, u8, u8),
233 ///     Hsv(u8, u8, u8),
234 /// }
235 /// # fn main() {}
236 /// ```
237 ///
238 /// Structs are not allowed:
239 ///
240 /// ```compile_fail
241 /// # #[macro_use]
242 /// # extern crate num_derive;
243 /// #[derive(FromPrimitive)]
244 /// struct Color {
245 ///     r: u8,
246 ///     g: u8,
247 ///     b: u8,
248 /// }
249 /// # fn main() {}
250 /// ```
251 #[proc_macro_derive(FromPrimitive, attributes(num_traits))]
from_primitive(input: TokenStream) -> TokenStream252 pub fn from_primitive(input: TokenStream) -> TokenStream {
253     let ast = parse!(input as syn::DeriveInput);
254     let name = &ast.ident;
255 
256     let import = NumTraits::new(&ast);
257 
258     let impl_ = if let Some(inner_ty) = newtype_inner(&ast.data) {
259         quote! {
260             impl #import::FromPrimitive for #name {
261                 #[inline]
262                 fn from_i64(n: i64) -> Option<Self> {
263                     <#inner_ty as #import::FromPrimitive>::from_i64(n).map(#name)
264                 }
265                 #[inline]
266                 fn from_u64(n: u64) -> Option<Self> {
267                     <#inner_ty as #import::FromPrimitive>::from_u64(n).map(#name)
268                 }
269                 #[inline]
270                 fn from_isize(n: isize) -> Option<Self> {
271                     <#inner_ty as #import::FromPrimitive>::from_isize(n).map(#name)
272                 }
273                 #[inline]
274                 fn from_i8(n: i8) -> Option<Self> {
275                     <#inner_ty as #import::FromPrimitive>::from_i8(n).map(#name)
276                 }
277                 #[inline]
278                 fn from_i16(n: i16) -> Option<Self> {
279                     <#inner_ty as #import::FromPrimitive>::from_i16(n).map(#name)
280                 }
281                 #[inline]
282                 fn from_i32(n: i32) -> Option<Self> {
283                     <#inner_ty as #import::FromPrimitive>::from_i32(n).map(#name)
284                 }
285                 #[inline]
286                 fn from_i128(n: i128) -> Option<Self> {
287                     <#inner_ty as #import::FromPrimitive>::from_i128(n).map(#name)
288                 }
289                 #[inline]
290                 fn from_usize(n: usize) -> Option<Self> {
291                     <#inner_ty as #import::FromPrimitive>::from_usize(n).map(#name)
292                 }
293                 #[inline]
294                 fn from_u8(n: u8) -> Option<Self> {
295                     <#inner_ty as #import::FromPrimitive>::from_u8(n).map(#name)
296                 }
297                 #[inline]
298                 fn from_u16(n: u16) -> Option<Self> {
299                     <#inner_ty as #import::FromPrimitive>::from_u16(n).map(#name)
300                 }
301                 #[inline]
302                 fn from_u32(n: u32) -> Option<Self> {
303                     <#inner_ty as #import::FromPrimitive>::from_u32(n).map(#name)
304                 }
305                 #[inline]
306                 fn from_u128(n: u128) -> Option<Self> {
307                     <#inner_ty as #import::FromPrimitive>::from_u128(n).map(#name)
308                 }
309                 #[inline]
310                 fn from_f32(n: f32) -> Option<Self> {
311                     <#inner_ty as #import::FromPrimitive>::from_f32(n).map(#name)
312                 }
313                 #[inline]
314                 fn from_f64(n: f64) -> Option<Self> {
315                     <#inner_ty as #import::FromPrimitive>::from_f64(n).map(#name)
316                 }
317             }
318         }
319     } else {
320         let variants = match ast.data {
321             Data::Enum(ref data_enum) => &data_enum.variants,
322             _ => panic!(
323                 "`FromPrimitive` can be applied only to enums and newtypes, {} is neither",
324                 name
325             ),
326         };
327 
328         let from_i64_var = quote! { n };
329         let clauses: Vec<_> = variants
330             .iter()
331             .map(|variant| {
332                 let ident = &variant.ident;
333                 match variant.fields {
334                     Fields::Unit => (),
335                     _ => panic!(
336                         "`FromPrimitive` can be applied only to unitary enums and newtypes, \
337                          {}::{} is either struct or tuple",
338                         name, ident
339                     ),
340                 }
341 
342                 quote! {
343                     if #from_i64_var == #name::#ident as i64 {
344                         Some(#name::#ident)
345                     }
346                 }
347             })
348             .collect();
349 
350         let from_i64_var = if clauses.is_empty() {
351             quote!(_)
352         } else {
353             from_i64_var
354         };
355 
356         quote! {
357             impl #import::FromPrimitive for #name {
358                 #[allow(trivial_numeric_casts)]
359                 #[inline]
360                 fn from_i64(#from_i64_var: i64) -> Option<Self> {
361                     #(#clauses else)* {
362                         None
363                     }
364                 }
365 
366                 #[inline]
367                 fn from_u64(n: u64) -> Option<Self> {
368                     Self::from_i64(n as i64)
369                 }
370             }
371         }
372     };
373 
374     import.wrap("FromPrimitive", &name, impl_).into()
375 }
376 
377 /// Derives [`num_traits::ToPrimitive`][to] for simple enums and newtypes.
378 ///
379 /// [to]: https://docs.rs/num-traits/0.2/num_traits/cast/trait.ToPrimitive.html
380 ///
381 /// # Examples
382 ///
383 /// Simple enums can be derived:
384 ///
385 /// ```rust
386 /// # #[macro_use]
387 /// # extern crate num_derive;
388 ///
389 /// #[derive(ToPrimitive)]
390 /// enum Color {
391 ///     Red,
392 ///     Blue,
393 ///     Green = 42,
394 /// }
395 /// # fn main() {}
396 /// ```
397 ///
398 /// Enums that contain data are not allowed:
399 ///
400 /// ```compile_fail
401 /// # #[macro_use]
402 /// # extern crate num_derive;
403 ///
404 /// #[derive(ToPrimitive)]
405 /// enum Color {
406 ///     Rgb(u8, u8, u8),
407 ///     Hsv(u8, u8, u8),
408 /// }
409 /// # fn main() {}
410 /// ```
411 ///
412 /// Structs are not allowed:
413 ///
414 /// ```compile_fail
415 /// # #[macro_use]
416 /// # extern crate num_derive;
417 /// #[derive(ToPrimitive)]
418 /// struct Color {
419 ///     r: u8,
420 ///     g: u8,
421 ///     b: u8,
422 /// }
423 /// # fn main() {}
424 /// ```
425 #[proc_macro_derive(ToPrimitive, attributes(num_traits))]
to_primitive(input: TokenStream) -> TokenStream426 pub fn to_primitive(input: TokenStream) -> TokenStream {
427     let ast = parse!(input as syn::DeriveInput);
428     let name = &ast.ident;
429 
430     let import = NumTraits::new(&ast);
431 
432     let impl_ = if let Some(inner_ty) = newtype_inner(&ast.data) {
433         quote! {
434             impl #import::ToPrimitive for #name {
435                 #[inline]
436                 fn to_i64(&self) -> Option<i64> {
437                     <#inner_ty as #import::ToPrimitive>::to_i64(&self.0)
438                 }
439                 #[inline]
440                 fn to_u64(&self) -> Option<u64> {
441                     <#inner_ty as #import::ToPrimitive>::to_u64(&self.0)
442                 }
443                 #[inline]
444                 fn to_isize(&self) -> Option<isize> {
445                     <#inner_ty as #import::ToPrimitive>::to_isize(&self.0)
446                 }
447                 #[inline]
448                 fn to_i8(&self) -> Option<i8> {
449                     <#inner_ty as #import::ToPrimitive>::to_i8(&self.0)
450                 }
451                 #[inline]
452                 fn to_i16(&self) -> Option<i16> {
453                     <#inner_ty as #import::ToPrimitive>::to_i16(&self.0)
454                 }
455                 #[inline]
456                 fn to_i32(&self) -> Option<i32> {
457                     <#inner_ty as #import::ToPrimitive>::to_i32(&self.0)
458                 }
459                 #[inline]
460                 fn to_i128(&self) -> Option<i128> {
461                     <#inner_ty as #import::ToPrimitive>::to_i128(&self.0)
462                 }
463                 #[inline]
464                 fn to_usize(&self) -> Option<usize> {
465                     <#inner_ty as #import::ToPrimitive>::to_usize(&self.0)
466                 }
467                 #[inline]
468                 fn to_u8(&self) -> Option<u8> {
469                     <#inner_ty as #import::ToPrimitive>::to_u8(&self.0)
470                 }
471                 #[inline]
472                 fn to_u16(&self) -> Option<u16> {
473                     <#inner_ty as #import::ToPrimitive>::to_u16(&self.0)
474                 }
475                 #[inline]
476                 fn to_u32(&self) -> Option<u32> {
477                     <#inner_ty as #import::ToPrimitive>::to_u32(&self.0)
478                 }
479                 #[inline]
480                 fn to_u128(&self) -> Option<u128> {
481                     <#inner_ty as #import::ToPrimitive>::to_u128(&self.0)
482                 }
483                 #[inline]
484                 fn to_f32(&self) -> Option<f32> {
485                     <#inner_ty as #import::ToPrimitive>::to_f32(&self.0)
486                 }
487                 #[inline]
488                 fn to_f64(&self) -> Option<f64> {
489                     <#inner_ty as #import::ToPrimitive>::to_f64(&self.0)
490                 }
491             }
492         }
493     } else {
494         let variants = match ast.data {
495             Data::Enum(ref data_enum) => &data_enum.variants,
496             _ => panic!(
497                 "`ToPrimitive` can be applied only to enums and newtypes, {} is neither",
498                 name
499             ),
500         };
501 
502         let variants: Vec<_> = variants
503             .iter()
504             .map(|variant| {
505                 let ident = &variant.ident;
506                 match variant.fields {
507                     Fields::Unit => (),
508                     _ => {
509                         panic!("`ToPrimitive` can be applied only to unitary enums and newtypes, {}::{} is either struct or tuple", name, ident)
510                     },
511                 }
512 
513                 // NB: We have to check each variant individually, because we'll only have `&self`
514                 // for the input.  We can't move from that, and it might not be `Clone` or `Copy`.
515                 // (Otherwise we could just do `*self as i64` without a `match` at all.)
516                 quote!(#name::#ident => #name::#ident as i64)
517             })
518             .collect();
519 
520         let match_expr = if variants.is_empty() {
521             // No variants found, so do not use Some to not to trigger `unreachable_code` lint
522             quote! {
523                 match *self {}
524             }
525         } else {
526             quote! {
527                 Some(match *self {
528                     #(#variants,)*
529                 })
530             }
531         };
532 
533         quote! {
534             impl #import::ToPrimitive for #name {
535                 #[inline]
536                 #[allow(trivial_numeric_casts)]
537                 fn to_i64(&self) -> Option<i64> {
538                     #match_expr
539                 }
540 
541                 #[inline]
542                 fn to_u64(&self) -> Option<u64> {
543                     self.to_i64().map(|x| x as u64)
544                 }
545             }
546         }
547     };
548 
549     import.wrap("ToPrimitive", &name, impl_).into()
550 }
551 
552 const NEWTYPE_ONLY: &str = "This trait can only be derived for newtypes";
553 
554 /// Derives [`num_traits::NumOps`][num_ops] for newtypes.  The inner type must already implement
555 /// `NumOps`.
556 ///
557 /// [num_ops]: https://docs.rs/num-traits/0.2/num_traits/trait.NumOps.html
558 ///
559 /// Note that, since `NumOps` is really a trait alias for `Add + Sub + Mul + Div + Rem`, this macro
560 /// generates impls for _those_ traits.  Furthermore, in all generated impls, `RHS=Self` and
561 /// `Output=Self`.
562 #[proc_macro_derive(NumOps)]
num_ops(input: TokenStream) -> TokenStream563 pub fn num_ops(input: TokenStream) -> TokenStream {
564     let ast = parse!(input as syn::DeriveInput);
565     let name = &ast.ident;
566     let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
567     let impl_ = quote! {
568         impl ::core::ops::Add for #name {
569             type Output = Self;
570             #[inline]
571             fn add(self, other: Self) -> Self {
572                 #name(<#inner_ty as ::core::ops::Add>::add(self.0, other.0))
573             }
574         }
575         impl ::core::ops::Sub for #name {
576             type Output = Self;
577             #[inline]
578             fn sub(self, other: Self) -> Self {
579                 #name(<#inner_ty as ::core::ops::Sub>::sub(self.0, other.0))
580             }
581         }
582         impl ::core::ops::Mul for #name {
583             type Output = Self;
584             #[inline]
585             fn mul(self, other: Self) -> Self {
586                 #name(<#inner_ty as ::core::ops::Mul>::mul(self.0, other.0))
587             }
588         }
589         impl ::core::ops::Div for #name {
590             type Output = Self;
591             #[inline]
592             fn div(self, other: Self) -> Self {
593                 #name(<#inner_ty as ::core::ops::Div>::div(self.0, other.0))
594             }
595         }
596         impl ::core::ops::Rem for #name {
597             type Output = Self;
598             #[inline]
599             fn rem(self, other: Self) -> Self {
600                 #name(<#inner_ty as ::core::ops::Rem>::rem(self.0, other.0))
601             }
602         }
603     };
604     impl_.into()
605 }
606 
607 /// Derives [`num_traits::NumCast`][num_cast] for newtypes.  The inner type must already implement
608 /// `NumCast`.
609 ///
610 /// [num_cast]: https://docs.rs/num-traits/0.2/num_traits/cast/trait.NumCast.html
611 #[proc_macro_derive(NumCast, attributes(num_traits))]
num_cast(input: TokenStream) -> TokenStream612 pub fn num_cast(input: TokenStream) -> TokenStream {
613     let ast = parse!(input as syn::DeriveInput);
614     let name = &ast.ident;
615     let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
616 
617     let import = NumTraits::new(&ast);
618 
619     let impl_ = quote! {
620         impl #import::NumCast for #name {
621             #[inline]
622             fn from<T: #import::ToPrimitive>(n: T) -> Option<Self> {
623                 <#inner_ty as #import::NumCast>::from(n).map(#name)
624             }
625         }
626     };
627 
628     import.wrap("NumCast", &name, impl_).into()
629 }
630 
631 /// Derives [`num_traits::Zero`][zero] for newtypes.  The inner type must already implement `Zero`.
632 ///
633 /// [zero]: https://docs.rs/num-traits/0.2/num_traits/identities/trait.Zero.html
634 #[proc_macro_derive(Zero, attributes(num_traits))]
zero(input: TokenStream) -> TokenStream635 pub fn zero(input: TokenStream) -> TokenStream {
636     let ast = parse!(input as syn::DeriveInput);
637     let name = &ast.ident;
638     let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
639 
640     let import = NumTraits::new(&ast);
641 
642     let impl_ = quote! {
643         impl #import::Zero for #name {
644             #[inline]
645             fn zero() -> Self {
646                 #name(<#inner_ty as #import::Zero>::zero())
647             }
648             #[inline]
649             fn is_zero(&self) -> bool {
650                 <#inner_ty as #import::Zero>::is_zero(&self.0)
651             }
652         }
653     };
654 
655     import.wrap("Zero", &name, impl_).into()
656 }
657 
658 /// Derives [`num_traits::One`][one] for newtypes.  The inner type must already implement `One`.
659 ///
660 /// [one]: https://docs.rs/num-traits/0.2/num_traits/identities/trait.One.html
661 #[proc_macro_derive(One, attributes(num_traits))]
one(input: TokenStream) -> TokenStream662 pub fn one(input: TokenStream) -> TokenStream {
663     let ast = parse!(input as syn::DeriveInput);
664     let name = &ast.ident;
665     let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
666 
667     let import = NumTraits::new(&ast);
668 
669     let impl_ = quote! {
670         impl #import::One for #name {
671             #[inline]
672             fn one() -> Self {
673                 #name(<#inner_ty as #import::One>::one())
674             }
675             #[inline]
676             fn is_one(&self) -> bool {
677                 <#inner_ty as #import::One>::is_one(&self.0)
678             }
679         }
680     };
681 
682     import.wrap("One", &name, impl_).into()
683 }
684 
685 /// Derives [`num_traits::Num`][num] for newtypes.  The inner type must already implement `Num`.
686 ///
687 /// [num]: https://docs.rs/num-traits/0.2/num_traits/trait.Num.html
688 #[proc_macro_derive(Num, attributes(num_traits))]
num(input: TokenStream) -> TokenStream689 pub fn num(input: TokenStream) -> TokenStream {
690     let ast = parse!(input as syn::DeriveInput);
691     let name = &ast.ident;
692     let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
693 
694     let import = NumTraits::new(&ast);
695 
696     let impl_ = quote! {
697         impl #import::Num for #name {
698             type FromStrRadixErr = <#inner_ty as #import::Num>::FromStrRadixErr;
699             #[inline]
700             fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
701                 <#inner_ty as #import::Num>::from_str_radix(s, radix).map(#name)
702             }
703         }
704     };
705 
706     import.wrap("Num", &name, impl_).into()
707 }
708 
709 /// Derives [`num_traits::Float`][float] for newtypes.  The inner type must already implement
710 /// `Float`.
711 ///
712 /// [float]: https://docs.rs/num-traits/0.2/num_traits/float/trait.Float.html
713 #[proc_macro_derive(Float, attributes(num_traits))]
float(input: TokenStream) -> TokenStream714 pub fn float(input: TokenStream) -> TokenStream {
715     let ast = parse!(input as syn::DeriveInput);
716     let name = &ast.ident;
717     let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
718 
719     let import = NumTraits::new(&ast);
720 
721     let impl_ = quote! {
722         impl #import::Float for #name {
723             #[inline]
724             fn nan() -> Self {
725                 #name(<#inner_ty as #import::Float>::nan())
726             }
727             #[inline]
728             fn infinity() -> Self {
729                 #name(<#inner_ty as #import::Float>::infinity())
730             }
731             #[inline]
732             fn neg_infinity() -> Self {
733                 #name(<#inner_ty as #import::Float>::neg_infinity())
734             }
735             #[inline]
736             fn neg_zero() -> Self {
737                 #name(<#inner_ty as #import::Float>::neg_zero())
738             }
739             #[inline]
740             fn min_value() -> Self {
741                 #name(<#inner_ty as #import::Float>::min_value())
742             }
743             #[inline]
744             fn min_positive_value() -> Self {
745                 #name(<#inner_ty as #import::Float>::min_positive_value())
746             }
747             #[inline]
748             fn max_value() -> Self {
749                 #name(<#inner_ty as #import::Float>::max_value())
750             }
751             #[inline]
752             fn is_nan(self) -> bool {
753                 <#inner_ty as #import::Float>::is_nan(self.0)
754             }
755             #[inline]
756             fn is_infinite(self) -> bool {
757                 <#inner_ty as #import::Float>::is_infinite(self.0)
758             }
759             #[inline]
760             fn is_finite(self) -> bool {
761                 <#inner_ty as #import::Float>::is_finite(self.0)
762             }
763             #[inline]
764             fn is_normal(self) -> bool {
765                 <#inner_ty as #import::Float>::is_normal(self.0)
766             }
767             #[inline]
768             fn classify(self) -> ::std::num::FpCategory {
769                 <#inner_ty as #import::Float>::classify(self.0)
770             }
771             #[inline]
772             fn floor(self) -> Self {
773                 #name(<#inner_ty as #import::Float>::floor(self.0))
774             }
775             #[inline]
776             fn ceil(self) -> Self {
777                 #name(<#inner_ty as #import::Float>::ceil(self.0))
778             }
779             #[inline]
780             fn round(self) -> Self {
781                 #name(<#inner_ty as #import::Float>::round(self.0))
782             }
783             #[inline]
784             fn trunc(self) -> Self {
785                 #name(<#inner_ty as #import::Float>::trunc(self.0))
786             }
787             #[inline]
788             fn fract(self) -> Self {
789                 #name(<#inner_ty as #import::Float>::fract(self.0))
790             }
791             #[inline]
792             fn abs(self) -> Self {
793                 #name(<#inner_ty as #import::Float>::abs(self.0))
794             }
795             #[inline]
796             fn signum(self) -> Self {
797                 #name(<#inner_ty as #import::Float>::signum(self.0))
798             }
799             #[inline]
800             fn is_sign_positive(self) -> bool {
801                 <#inner_ty as #import::Float>::is_sign_positive(self.0)
802             }
803             #[inline]
804             fn is_sign_negative(self) -> bool {
805                 <#inner_ty as #import::Float>::is_sign_negative(self.0)
806             }
807             #[inline]
808             fn mul_add(self, a: Self, b: Self) -> Self {
809                 #name(<#inner_ty as #import::Float>::mul_add(self.0, a.0, b.0))
810             }
811             #[inline]
812             fn recip(self) -> Self {
813                 #name(<#inner_ty as #import::Float>::recip(self.0))
814             }
815             #[inline]
816             fn powi(self, n: i32) -> Self {
817                 #name(<#inner_ty as #import::Float>::powi(self.0, n))
818             }
819             #[inline]
820             fn powf(self, n: Self) -> Self {
821                 #name(<#inner_ty as #import::Float>::powf(self.0, n.0))
822             }
823             #[inline]
824             fn sqrt(self) -> Self {
825                 #name(<#inner_ty as #import::Float>::sqrt(self.0))
826             }
827             #[inline]
828             fn exp(self) -> Self {
829                 #name(<#inner_ty as #import::Float>::exp(self.0))
830             }
831             #[inline]
832             fn exp2(self) -> Self {
833                 #name(<#inner_ty as #import::Float>::exp2(self.0))
834             }
835             #[inline]
836             fn ln(self) -> Self {
837                 #name(<#inner_ty as #import::Float>::ln(self.0))
838             }
839             #[inline]
840             fn log(self, base: Self) -> Self {
841                 #name(<#inner_ty as #import::Float>::log(self.0, base.0))
842             }
843             #[inline]
844             fn log2(self) -> Self {
845                 #name(<#inner_ty as #import::Float>::log2(self.0))
846             }
847             #[inline]
848             fn log10(self) -> Self {
849                 #name(<#inner_ty as #import::Float>::log10(self.0))
850             }
851             #[inline]
852             fn max(self, other: Self) -> Self {
853                 #name(<#inner_ty as #import::Float>::max(self.0, other.0))
854             }
855             #[inline]
856             fn min(self, other: Self) -> Self {
857                 #name(<#inner_ty as #import::Float>::min(self.0, other.0))
858             }
859             #[inline]
860             fn abs_sub(self, other: Self) -> Self {
861                 #name(<#inner_ty as #import::Float>::abs_sub(self.0, other.0))
862             }
863             #[inline]
864             fn cbrt(self) -> Self {
865                 #name(<#inner_ty as #import::Float>::cbrt(self.0))
866             }
867             #[inline]
868             fn hypot(self, other: Self) -> Self {
869                 #name(<#inner_ty as #import::Float>::hypot(self.0, other.0))
870             }
871             #[inline]
872             fn sin(self) -> Self {
873                 #name(<#inner_ty as #import::Float>::sin(self.0))
874             }
875             #[inline]
876             fn cos(self) -> Self {
877                 #name(<#inner_ty as #import::Float>::cos(self.0))
878             }
879             #[inline]
880             fn tan(self) -> Self {
881                 #name(<#inner_ty as #import::Float>::tan(self.0))
882             }
883             #[inline]
884             fn asin(self) -> Self {
885                 #name(<#inner_ty as #import::Float>::asin(self.0))
886             }
887             #[inline]
888             fn acos(self) -> Self {
889                 #name(<#inner_ty as #import::Float>::acos(self.0))
890             }
891             #[inline]
892             fn atan(self) -> Self {
893                 #name(<#inner_ty as #import::Float>::atan(self.0))
894             }
895             #[inline]
896             fn atan2(self, other: Self) -> Self {
897                 #name(<#inner_ty as #import::Float>::atan2(self.0, other.0))
898             }
899             #[inline]
900             fn sin_cos(self) -> (Self, Self) {
901                 let (x, y) = <#inner_ty as #import::Float>::sin_cos(self.0);
902                 (#name(x), #name(y))
903             }
904             #[inline]
905             fn exp_m1(self) -> Self {
906                 #name(<#inner_ty as #import::Float>::exp_m1(self.0))
907             }
908             #[inline]
909             fn ln_1p(self) -> Self {
910                 #name(<#inner_ty as #import::Float>::ln_1p(self.0))
911             }
912             #[inline]
913             fn sinh(self) -> Self {
914                 #name(<#inner_ty as #import::Float>::sinh(self.0))
915             }
916             #[inline]
917             fn cosh(self) -> Self {
918                 #name(<#inner_ty as #import::Float>::cosh(self.0))
919             }
920             #[inline]
921             fn tanh(self) -> Self {
922                 #name(<#inner_ty as #import::Float>::tanh(self.0))
923             }
924             #[inline]
925             fn asinh(self) -> Self {
926                 #name(<#inner_ty as #import::Float>::asinh(self.0))
927             }
928             #[inline]
929             fn acosh(self) -> Self {
930                 #name(<#inner_ty as #import::Float>::acosh(self.0))
931             }
932             #[inline]
933             fn atanh(self) -> Self {
934                 #name(<#inner_ty as #import::Float>::atanh(self.0))
935             }
936             #[inline]
937             fn integer_decode(self) -> (u64, i16, i8) {
938                 <#inner_ty as #import::Float>::integer_decode(self.0)
939             }
940             #[inline]
941             fn epsilon() -> Self {
942                 #name(<#inner_ty as #import::Float>::epsilon())
943             }
944             #[inline]
945             fn to_degrees(self) -> Self {
946                 #name(<#inner_ty as #import::Float>::to_degrees(self.0))
947             }
948             #[inline]
949             fn to_radians(self) -> Self {
950                 #name(<#inner_ty as #import::Float>::to_radians(self.0))
951             }
952         }
953     };
954 
955     import.wrap("Float", &name, impl_).into()
956 }
957 
958 mod test;
959