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 attr.path().is_ident("num_traits") {
174 if let syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(ref lit_str), .. }) = attr.meta.require_name_value().unwrap().value {
175 return NumTraits {
176 import: syn::Ident::new(&lit_str.value(), lit_str.span()),
177 explicit: true,
178 }
179 } else {
180 panic!("#[num_traits] attribute value must be a str");
181 }
182 }
183 }
184
185 // Otherwise, we'll implicitly import our own.
186 NumTraits {
187 import: Ident::new("_num_traits", Span::call_site()),
188 explicit: false,
189 }
190 }
191
wrap(&self, trait_: &str, name: &Ident, output: TokenStream2) -> TokenStream2192 fn wrap(&self, trait_: &str, name: &Ident, output: TokenStream2) -> TokenStream2 {
193 if self.explicit {
194 output
195 } else {
196 dummy_const_trick(trait_, &name, output)
197 }
198 }
199 }
200
201 /// Derives [`num_traits::FromPrimitive`][from] for simple enums and newtypes.
202 ///
203 /// [from]: https://docs.rs/num-traits/0.2/num_traits/cast/trait.FromPrimitive.html
204 ///
205 /// # Examples
206 ///
207 /// Simple enums can be derived:
208 ///
209 /// ```rust
210 /// # #[macro_use]
211 /// # extern crate num_derive;
212 ///
213 /// #[derive(FromPrimitive)]
214 /// enum Color {
215 /// Red,
216 /// Blue,
217 /// Green = 42,
218 /// }
219 /// # fn main() {}
220 /// ```
221 ///
222 /// Enums that contain data are not allowed:
223 ///
224 /// ```compile_fail
225 /// # #[macro_use]
226 /// # extern crate num_derive;
227 ///
228 /// #[derive(FromPrimitive)]
229 /// enum Color {
230 /// Rgb(u8, u8, u8),
231 /// Hsv(u8, u8, u8),
232 /// }
233 /// # fn main() {}
234 /// ```
235 ///
236 /// Structs are not allowed:
237 ///
238 /// ```compile_fail
239 /// # #[macro_use]
240 /// # extern crate num_derive;
241 /// #[derive(FromPrimitive)]
242 /// struct Color {
243 /// r: u8,
244 /// g: u8,
245 /// b: u8,
246 /// }
247 /// # fn main() {}
248 /// ```
249 #[proc_macro_derive(FromPrimitive, attributes(num_traits))]
from_primitive(input: TokenStream) -> TokenStream250 pub fn from_primitive(input: TokenStream) -> TokenStream {
251 let ast = parse!(input as syn::DeriveInput);
252 let name = &ast.ident;
253
254 let import = NumTraits::new(&ast);
255
256 let impl_ = if let Some(inner_ty) = newtype_inner(&ast.data) {
257 quote! {
258 impl #import::FromPrimitive for #name {
259 #[inline]
260 fn from_i64(n: i64) -> Option<Self> {
261 <#inner_ty as #import::FromPrimitive>::from_i64(n).map(#name)
262 }
263 #[inline]
264 fn from_u64(n: u64) -> Option<Self> {
265 <#inner_ty as #import::FromPrimitive>::from_u64(n).map(#name)
266 }
267 #[inline]
268 fn from_isize(n: isize) -> Option<Self> {
269 <#inner_ty as #import::FromPrimitive>::from_isize(n).map(#name)
270 }
271 #[inline]
272 fn from_i8(n: i8) -> Option<Self> {
273 <#inner_ty as #import::FromPrimitive>::from_i8(n).map(#name)
274 }
275 #[inline]
276 fn from_i16(n: i16) -> Option<Self> {
277 <#inner_ty as #import::FromPrimitive>::from_i16(n).map(#name)
278 }
279 #[inline]
280 fn from_i32(n: i32) -> Option<Self> {
281 <#inner_ty as #import::FromPrimitive>::from_i32(n).map(#name)
282 }
283 #[inline]
284 fn from_i128(n: i128) -> Option<Self> {
285 <#inner_ty as #import::FromPrimitive>::from_i128(n).map(#name)
286 }
287 #[inline]
288 fn from_usize(n: usize) -> Option<Self> {
289 <#inner_ty as #import::FromPrimitive>::from_usize(n).map(#name)
290 }
291 #[inline]
292 fn from_u8(n: u8) -> Option<Self> {
293 <#inner_ty as #import::FromPrimitive>::from_u8(n).map(#name)
294 }
295 #[inline]
296 fn from_u16(n: u16) -> Option<Self> {
297 <#inner_ty as #import::FromPrimitive>::from_u16(n).map(#name)
298 }
299 #[inline]
300 fn from_u32(n: u32) -> Option<Self> {
301 <#inner_ty as #import::FromPrimitive>::from_u32(n).map(#name)
302 }
303 #[inline]
304 fn from_u128(n: u128) -> Option<Self> {
305 <#inner_ty as #import::FromPrimitive>::from_u128(n).map(#name)
306 }
307 #[inline]
308 fn from_f32(n: f32) -> Option<Self> {
309 <#inner_ty as #import::FromPrimitive>::from_f32(n).map(#name)
310 }
311 #[inline]
312 fn from_f64(n: f64) -> Option<Self> {
313 <#inner_ty as #import::FromPrimitive>::from_f64(n).map(#name)
314 }
315 }
316 }
317 } else {
318 let variants = match ast.data {
319 Data::Enum(ref data_enum) => &data_enum.variants,
320 _ => panic!(
321 "`FromPrimitive` can be applied only to enums and newtypes, {} is neither",
322 name
323 ),
324 };
325
326 let from_i64_var = quote! { n };
327 let clauses: Vec<_> = variants
328 .iter()
329 .map(|variant| {
330 let ident = &variant.ident;
331 match variant.fields {
332 Fields::Unit => (),
333 _ => panic!(
334 "`FromPrimitive` can be applied only to unitary enums and newtypes, \
335 {}::{} is either struct or tuple",
336 name, ident
337 ),
338 }
339
340 quote! {
341 if #from_i64_var == #name::#ident as i64 {
342 Some(#name::#ident)
343 }
344 }
345 })
346 .collect();
347
348 let from_i64_var = if clauses.is_empty() {
349 quote!(_)
350 } else {
351 from_i64_var
352 };
353
354 quote! {
355 impl #import::FromPrimitive for #name {
356 #[allow(trivial_numeric_casts)]
357 #[inline]
358 fn from_i64(#from_i64_var: i64) -> Option<Self> {
359 #(#clauses else)* {
360 None
361 }
362 }
363
364 #[inline]
365 fn from_u64(n: u64) -> Option<Self> {
366 Self::from_i64(n as i64)
367 }
368 }
369 }
370 };
371
372 import.wrap("FromPrimitive", &name, impl_).into()
373 }
374
375 /// Derives [`num_traits::ToPrimitive`][to] for simple enums and newtypes.
376 ///
377 /// [to]: https://docs.rs/num-traits/0.2/num_traits/cast/trait.ToPrimitive.html
378 ///
379 /// # Examples
380 ///
381 /// Simple enums can be derived:
382 ///
383 /// ```rust
384 /// # #[macro_use]
385 /// # extern crate num_derive;
386 ///
387 /// #[derive(ToPrimitive)]
388 /// enum Color {
389 /// Red,
390 /// Blue,
391 /// Green = 42,
392 /// }
393 /// # fn main() {}
394 /// ```
395 ///
396 /// Enums that contain data are not allowed:
397 ///
398 /// ```compile_fail
399 /// # #[macro_use]
400 /// # extern crate num_derive;
401 ///
402 /// #[derive(ToPrimitive)]
403 /// enum Color {
404 /// Rgb(u8, u8, u8),
405 /// Hsv(u8, u8, u8),
406 /// }
407 /// # fn main() {}
408 /// ```
409 ///
410 /// Structs are not allowed:
411 ///
412 /// ```compile_fail
413 /// # #[macro_use]
414 /// # extern crate num_derive;
415 /// #[derive(ToPrimitive)]
416 /// struct Color {
417 /// r: u8,
418 /// g: u8,
419 /// b: u8,
420 /// }
421 /// # fn main() {}
422 /// ```
423 #[proc_macro_derive(ToPrimitive, attributes(num_traits))]
to_primitive(input: TokenStream) -> TokenStream424 pub fn to_primitive(input: TokenStream) -> TokenStream {
425 let ast = parse!(input as syn::DeriveInput);
426 let name = &ast.ident;
427
428 let import = NumTraits::new(&ast);
429
430 let impl_ = if let Some(inner_ty) = newtype_inner(&ast.data) {
431 quote! {
432 impl #import::ToPrimitive for #name {
433 #[inline]
434 fn to_i64(&self) -> Option<i64> {
435 <#inner_ty as #import::ToPrimitive>::to_i64(&self.0)
436 }
437 #[inline]
438 fn to_u64(&self) -> Option<u64> {
439 <#inner_ty as #import::ToPrimitive>::to_u64(&self.0)
440 }
441 #[inline]
442 fn to_isize(&self) -> Option<isize> {
443 <#inner_ty as #import::ToPrimitive>::to_isize(&self.0)
444 }
445 #[inline]
446 fn to_i8(&self) -> Option<i8> {
447 <#inner_ty as #import::ToPrimitive>::to_i8(&self.0)
448 }
449 #[inline]
450 fn to_i16(&self) -> Option<i16> {
451 <#inner_ty as #import::ToPrimitive>::to_i16(&self.0)
452 }
453 #[inline]
454 fn to_i32(&self) -> Option<i32> {
455 <#inner_ty as #import::ToPrimitive>::to_i32(&self.0)
456 }
457 #[inline]
458 fn to_i128(&self) -> Option<i128> {
459 <#inner_ty as #import::ToPrimitive>::to_i128(&self.0)
460 }
461 #[inline]
462 fn to_usize(&self) -> Option<usize> {
463 <#inner_ty as #import::ToPrimitive>::to_usize(&self.0)
464 }
465 #[inline]
466 fn to_u8(&self) -> Option<u8> {
467 <#inner_ty as #import::ToPrimitive>::to_u8(&self.0)
468 }
469 #[inline]
470 fn to_u16(&self) -> Option<u16> {
471 <#inner_ty as #import::ToPrimitive>::to_u16(&self.0)
472 }
473 #[inline]
474 fn to_u32(&self) -> Option<u32> {
475 <#inner_ty as #import::ToPrimitive>::to_u32(&self.0)
476 }
477 #[inline]
478 fn to_u128(&self) -> Option<u128> {
479 <#inner_ty as #import::ToPrimitive>::to_u128(&self.0)
480 }
481 #[inline]
482 fn to_f32(&self) -> Option<f32> {
483 <#inner_ty as #import::ToPrimitive>::to_f32(&self.0)
484 }
485 #[inline]
486 fn to_f64(&self) -> Option<f64> {
487 <#inner_ty as #import::ToPrimitive>::to_f64(&self.0)
488 }
489 }
490 }
491 } else {
492 let variants = match ast.data {
493 Data::Enum(ref data_enum) => &data_enum.variants,
494 _ => panic!(
495 "`ToPrimitive` can be applied only to enums and newtypes, {} is neither",
496 name
497 ),
498 };
499
500 let variants: Vec<_> = variants
501 .iter()
502 .map(|variant| {
503 let ident = &variant.ident;
504 match variant.fields {
505 Fields::Unit => (),
506 _ => {
507 panic!("`ToPrimitive` can be applied only to unitary enums and newtypes, {}::{} is either struct or tuple", name, ident)
508 },
509 }
510
511 // NB: We have to check each variant individually, because we'll only have `&self`
512 // for the input. We can't move from that, and it might not be `Clone` or `Copy`.
513 // (Otherwise we could just do `*self as i64` without a `match` at all.)
514 quote!(#name::#ident => #name::#ident as i64)
515 })
516 .collect();
517
518 let match_expr = if variants.is_empty() {
519 // No variants found, so do not use Some to not to trigger `unreachable_code` lint
520 quote! {
521 match *self {}
522 }
523 } else {
524 quote! {
525 Some(match *self {
526 #(#variants,)*
527 })
528 }
529 };
530
531 quote! {
532 impl #import::ToPrimitive for #name {
533 #[inline]
534 #[allow(trivial_numeric_casts)]
535 fn to_i64(&self) -> Option<i64> {
536 #match_expr
537 }
538
539 #[inline]
540 fn to_u64(&self) -> Option<u64> {
541 self.to_i64().map(|x| x as u64)
542 }
543 }
544 }
545 };
546
547 import.wrap("ToPrimitive", &name, impl_).into()
548 }
549
550 const NEWTYPE_ONLY: &str = "This trait can only be derived for newtypes";
551
552 /// Derives [`num_traits::NumOps`][num_ops] for newtypes. The inner type must already implement
553 /// `NumOps`.
554 ///
555 /// [num_ops]: https://docs.rs/num-traits/0.2/num_traits/trait.NumOps.html
556 ///
557 /// Note that, since `NumOps` is really a trait alias for `Add + Sub + Mul + Div + Rem`, this macro
558 /// generates impls for _those_ traits. Furthermore, in all generated impls, `RHS=Self` and
559 /// `Output=Self`.
560 #[proc_macro_derive(NumOps)]
num_ops(input: TokenStream) -> TokenStream561 pub fn num_ops(input: TokenStream) -> TokenStream {
562 let ast = parse!(input as syn::DeriveInput);
563 let name = &ast.ident;
564 let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
565 let impl_ = quote! {
566 impl ::core::ops::Add for #name {
567 type Output = Self;
568 #[inline]
569 fn add(self, other: Self) -> Self {
570 #name(<#inner_ty as ::core::ops::Add>::add(self.0, other.0))
571 }
572 }
573 impl ::core::ops::Sub for #name {
574 type Output = Self;
575 #[inline]
576 fn sub(self, other: Self) -> Self {
577 #name(<#inner_ty as ::core::ops::Sub>::sub(self.0, other.0))
578 }
579 }
580 impl ::core::ops::Mul for #name {
581 type Output = Self;
582 #[inline]
583 fn mul(self, other: Self) -> Self {
584 #name(<#inner_ty as ::core::ops::Mul>::mul(self.0, other.0))
585 }
586 }
587 impl ::core::ops::Div for #name {
588 type Output = Self;
589 #[inline]
590 fn div(self, other: Self) -> Self {
591 #name(<#inner_ty as ::core::ops::Div>::div(self.0, other.0))
592 }
593 }
594 impl ::core::ops::Rem for #name {
595 type Output = Self;
596 #[inline]
597 fn rem(self, other: Self) -> Self {
598 #name(<#inner_ty as ::core::ops::Rem>::rem(self.0, other.0))
599 }
600 }
601 };
602 impl_.into()
603 }
604
605 /// Derives [`num_traits::NumCast`][num_cast] for newtypes. The inner type must already implement
606 /// `NumCast`.
607 ///
608 /// [num_cast]: https://docs.rs/num-traits/0.2/num_traits/cast/trait.NumCast.html
609 #[proc_macro_derive(NumCast, attributes(num_traits))]
num_cast(input: TokenStream) -> TokenStream610 pub fn num_cast(input: TokenStream) -> TokenStream {
611 let ast = parse!(input as syn::DeriveInput);
612 let name = &ast.ident;
613 let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
614
615 let import = NumTraits::new(&ast);
616
617 let impl_ = quote! {
618 impl #import::NumCast for #name {
619 #[inline]
620 fn from<T: #import::ToPrimitive>(n: T) -> Option<Self> {
621 <#inner_ty as #import::NumCast>::from(n).map(#name)
622 }
623 }
624 };
625
626 import.wrap("NumCast", &name, impl_).into()
627 }
628
629 /// Derives [`num_traits::Zero`][zero] for newtypes. The inner type must already implement `Zero`.
630 ///
631 /// [zero]: https://docs.rs/num-traits/0.2/num_traits/identities/trait.Zero.html
632 #[proc_macro_derive(Zero, attributes(num_traits))]
zero(input: TokenStream) -> TokenStream633 pub fn zero(input: TokenStream) -> TokenStream {
634 let ast = parse!(input as syn::DeriveInput);
635 let name = &ast.ident;
636 let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
637
638 let import = NumTraits::new(&ast);
639
640 let impl_ = quote! {
641 impl #import::Zero for #name {
642 #[inline]
643 fn zero() -> Self {
644 #name(<#inner_ty as #import::Zero>::zero())
645 }
646 #[inline]
647 fn is_zero(&self) -> bool {
648 <#inner_ty as #import::Zero>::is_zero(&self.0)
649 }
650 }
651 };
652
653 import.wrap("Zero", &name, impl_).into()
654 }
655
656 /// Derives [`num_traits::One`][one] for newtypes. The inner type must already implement `One`.
657 ///
658 /// [one]: https://docs.rs/num-traits/0.2/num_traits/identities/trait.One.html
659 #[proc_macro_derive(One, attributes(num_traits))]
one(input: TokenStream) -> TokenStream660 pub fn one(input: TokenStream) -> TokenStream {
661 let ast = parse!(input as syn::DeriveInput);
662 let name = &ast.ident;
663 let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
664
665 let import = NumTraits::new(&ast);
666
667 let impl_ = quote! {
668 impl #import::One for #name {
669 #[inline]
670 fn one() -> Self {
671 #name(<#inner_ty as #import::One>::one())
672 }
673 #[inline]
674 fn is_one(&self) -> bool {
675 <#inner_ty as #import::One>::is_one(&self.0)
676 }
677 }
678 };
679
680 import.wrap("One", &name, impl_).into()
681 }
682
683 /// Derives [`num_traits::Num`][num] for newtypes. The inner type must already implement `Num`.
684 ///
685 /// [num]: https://docs.rs/num-traits/0.2/num_traits/trait.Num.html
686 #[proc_macro_derive(Num, attributes(num_traits))]
num(input: TokenStream) -> TokenStream687 pub fn num(input: TokenStream) -> TokenStream {
688 let ast = parse!(input as syn::DeriveInput);
689 let name = &ast.ident;
690 let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
691
692 let import = NumTraits::new(&ast);
693
694 let impl_ = quote! {
695 impl #import::Num for #name {
696 type FromStrRadixErr = <#inner_ty as #import::Num>::FromStrRadixErr;
697 #[inline]
698 fn from_str_radix(s: &str, radix: u32) -> Result<Self, Self::FromStrRadixErr> {
699 <#inner_ty as #import::Num>::from_str_radix(s, radix).map(#name)
700 }
701 }
702 };
703
704 import.wrap("Num", &name, impl_).into()
705 }
706
707 /// Derives [`num_traits::Float`][float] for newtypes. The inner type must already implement
708 /// `Float`.
709 ///
710 /// [float]: https://docs.rs/num-traits/0.2/num_traits/float/trait.Float.html
711 #[proc_macro_derive(Float, attributes(num_traits))]
float(input: TokenStream) -> TokenStream712 pub fn float(input: TokenStream) -> TokenStream {
713 let ast = parse!(input as syn::DeriveInput);
714 let name = &ast.ident;
715 let inner_ty = newtype_inner(&ast.data).expect(NEWTYPE_ONLY);
716
717 let import = NumTraits::new(&ast);
718
719 let impl_ = quote! {
720 impl #import::Float for #name {
721 #[inline]
722 fn nan() -> Self {
723 #name(<#inner_ty as #import::Float>::nan())
724 }
725 #[inline]
726 fn infinity() -> Self {
727 #name(<#inner_ty as #import::Float>::infinity())
728 }
729 #[inline]
730 fn neg_infinity() -> Self {
731 #name(<#inner_ty as #import::Float>::neg_infinity())
732 }
733 #[inline]
734 fn neg_zero() -> Self {
735 #name(<#inner_ty as #import::Float>::neg_zero())
736 }
737 #[inline]
738 fn min_value() -> Self {
739 #name(<#inner_ty as #import::Float>::min_value())
740 }
741 #[inline]
742 fn min_positive_value() -> Self {
743 #name(<#inner_ty as #import::Float>::min_positive_value())
744 }
745 #[inline]
746 fn max_value() -> Self {
747 #name(<#inner_ty as #import::Float>::max_value())
748 }
749 #[inline]
750 fn is_nan(self) -> bool {
751 <#inner_ty as #import::Float>::is_nan(self.0)
752 }
753 #[inline]
754 fn is_infinite(self) -> bool {
755 <#inner_ty as #import::Float>::is_infinite(self.0)
756 }
757 #[inline]
758 fn is_finite(self) -> bool {
759 <#inner_ty as #import::Float>::is_finite(self.0)
760 }
761 #[inline]
762 fn is_normal(self) -> bool {
763 <#inner_ty as #import::Float>::is_normal(self.0)
764 }
765 #[inline]
766 fn classify(self) -> ::std::num::FpCategory {
767 <#inner_ty as #import::Float>::classify(self.0)
768 }
769 #[inline]
770 fn floor(self) -> Self {
771 #name(<#inner_ty as #import::Float>::floor(self.0))
772 }
773 #[inline]
774 fn ceil(self) -> Self {
775 #name(<#inner_ty as #import::Float>::ceil(self.0))
776 }
777 #[inline]
778 fn round(self) -> Self {
779 #name(<#inner_ty as #import::Float>::round(self.0))
780 }
781 #[inline]
782 fn trunc(self) -> Self {
783 #name(<#inner_ty as #import::Float>::trunc(self.0))
784 }
785 #[inline]
786 fn fract(self) -> Self {
787 #name(<#inner_ty as #import::Float>::fract(self.0))
788 }
789 #[inline]
790 fn abs(self) -> Self {
791 #name(<#inner_ty as #import::Float>::abs(self.0))
792 }
793 #[inline]
794 fn signum(self) -> Self {
795 #name(<#inner_ty as #import::Float>::signum(self.0))
796 }
797 #[inline]
798 fn is_sign_positive(self) -> bool {
799 <#inner_ty as #import::Float>::is_sign_positive(self.0)
800 }
801 #[inline]
802 fn is_sign_negative(self) -> bool {
803 <#inner_ty as #import::Float>::is_sign_negative(self.0)
804 }
805 #[inline]
806 fn mul_add(self, a: Self, b: Self) -> Self {
807 #name(<#inner_ty as #import::Float>::mul_add(self.0, a.0, b.0))
808 }
809 #[inline]
810 fn recip(self) -> Self {
811 #name(<#inner_ty as #import::Float>::recip(self.0))
812 }
813 #[inline]
814 fn powi(self, n: i32) -> Self {
815 #name(<#inner_ty as #import::Float>::powi(self.0, n))
816 }
817 #[inline]
818 fn powf(self, n: Self) -> Self {
819 #name(<#inner_ty as #import::Float>::powf(self.0, n.0))
820 }
821 #[inline]
822 fn sqrt(self) -> Self {
823 #name(<#inner_ty as #import::Float>::sqrt(self.0))
824 }
825 #[inline]
826 fn exp(self) -> Self {
827 #name(<#inner_ty as #import::Float>::exp(self.0))
828 }
829 #[inline]
830 fn exp2(self) -> Self {
831 #name(<#inner_ty as #import::Float>::exp2(self.0))
832 }
833 #[inline]
834 fn ln(self) -> Self {
835 #name(<#inner_ty as #import::Float>::ln(self.0))
836 }
837 #[inline]
838 fn log(self, base: Self) -> Self {
839 #name(<#inner_ty as #import::Float>::log(self.0, base.0))
840 }
841 #[inline]
842 fn log2(self) -> Self {
843 #name(<#inner_ty as #import::Float>::log2(self.0))
844 }
845 #[inline]
846 fn log10(self) -> Self {
847 #name(<#inner_ty as #import::Float>::log10(self.0))
848 }
849 #[inline]
850 fn max(self, other: Self) -> Self {
851 #name(<#inner_ty as #import::Float>::max(self.0, other.0))
852 }
853 #[inline]
854 fn min(self, other: Self) -> Self {
855 #name(<#inner_ty as #import::Float>::min(self.0, other.0))
856 }
857 #[inline]
858 fn abs_sub(self, other: Self) -> Self {
859 #name(<#inner_ty as #import::Float>::abs_sub(self.0, other.0))
860 }
861 #[inline]
862 fn cbrt(self) -> Self {
863 #name(<#inner_ty as #import::Float>::cbrt(self.0))
864 }
865 #[inline]
866 fn hypot(self, other: Self) -> Self {
867 #name(<#inner_ty as #import::Float>::hypot(self.0, other.0))
868 }
869 #[inline]
870 fn sin(self) -> Self {
871 #name(<#inner_ty as #import::Float>::sin(self.0))
872 }
873 #[inline]
874 fn cos(self) -> Self {
875 #name(<#inner_ty as #import::Float>::cos(self.0))
876 }
877 #[inline]
878 fn tan(self) -> Self {
879 #name(<#inner_ty as #import::Float>::tan(self.0))
880 }
881 #[inline]
882 fn asin(self) -> Self {
883 #name(<#inner_ty as #import::Float>::asin(self.0))
884 }
885 #[inline]
886 fn acos(self) -> Self {
887 #name(<#inner_ty as #import::Float>::acos(self.0))
888 }
889 #[inline]
890 fn atan(self) -> Self {
891 #name(<#inner_ty as #import::Float>::atan(self.0))
892 }
893 #[inline]
894 fn atan2(self, other: Self) -> Self {
895 #name(<#inner_ty as #import::Float>::atan2(self.0, other.0))
896 }
897 #[inline]
898 fn sin_cos(self) -> (Self, Self) {
899 let (x, y) = <#inner_ty as #import::Float>::sin_cos(self.0);
900 (#name(x), #name(y))
901 }
902 #[inline]
903 fn exp_m1(self) -> Self {
904 #name(<#inner_ty as #import::Float>::exp_m1(self.0))
905 }
906 #[inline]
907 fn ln_1p(self) -> Self {
908 #name(<#inner_ty as #import::Float>::ln_1p(self.0))
909 }
910 #[inline]
911 fn sinh(self) -> Self {
912 #name(<#inner_ty as #import::Float>::sinh(self.0))
913 }
914 #[inline]
915 fn cosh(self) -> Self {
916 #name(<#inner_ty as #import::Float>::cosh(self.0))
917 }
918 #[inline]
919 fn tanh(self) -> Self {
920 #name(<#inner_ty as #import::Float>::tanh(self.0))
921 }
922 #[inline]
923 fn asinh(self) -> Self {
924 #name(<#inner_ty as #import::Float>::asinh(self.0))
925 }
926 #[inline]
927 fn acosh(self) -> Self {
928 #name(<#inner_ty as #import::Float>::acosh(self.0))
929 }
930 #[inline]
931 fn atanh(self) -> Self {
932 #name(<#inner_ty as #import::Float>::atanh(self.0))
933 }
934 #[inline]
935 fn integer_decode(self) -> (u64, i16, i8) {
936 <#inner_ty as #import::Float>::integer_decode(self.0)
937 }
938 #[inline]
939 fn epsilon() -> Self {
940 #name(<#inner_ty as #import::Float>::epsilon())
941 }
942 #[inline]
943 fn to_degrees(self) -> Self {
944 #name(<#inner_ty as #import::Float>::to_degrees(self.0))
945 }
946 #[inline]
947 fn to_radians(self) -> Self {
948 #name(<#inner_ty as #import::Float>::to_radians(self.0))
949 }
950 }
951 };
952
953 import.wrap("Float", &name, impl_).into()
954 }
955