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