1//! # `derive_more`
2//!
3//! [![Build Status](https://github.com/JelteF/derive_more/workflows/CI/badge.svg)](https://github.com/JelteF/derive_more/actions)
4//! [![Latest Version](https://img.shields.io/crates/v/derive_more.svg)](https://crates.io/crates/derive_more)
5//! [![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://jeltef.github.io/derive_more/derive_more/)
6//! [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/JelteF/derive_more/master/LICENSE)
7//! [![Rust 1.36+](https://img.shields.io/badge/rustc-1.36+-lightgray.svg)](https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html)
8//!
9//! Rust has lots of builtin traits that are implemented for its basic types, such
10//! as `Add`, `Not`, `From` or `Display`.
11//! However, when wrapping these types inside your own structs or enums you lose the
12//! implementations of these traits and are required to recreate them.
13//! This is especially annoying when your own structures are very simple, such as
14//! when using the commonly advised newtype pattern (e.g. `MyInt(i32)`).
15//!
16//! This library tries to remove these annoyances and the corresponding boilerplate code.
17//! It does this by allowing you to derive lots of commonly used traits for both structs and enums.
18//!
19//! ## Example code
20//!
21//! By using this library the following code just works:
22//!
23//! ```rust
24//! extern crate derive_more;
25//! use derive_more::{Add, Display, From, Into};
26//!
27//! #[derive(PartialEq, From, Add)]
28//! struct MyInt(i32);
29//!
30//! #[derive(PartialEq, From, Into)]
31//! struct Point2D {
32//! x: i32,
33//! y: i32,
34//! }
35//!
36//! #[derive(PartialEq, From, Add, Display)]
37//! enum MyEnum {
38//! #[display(fmt = "int: {}", _0)]
39//! Int(i32),
40//! Uint(u32),
41//! #[display(fmt = "nothing")]
42//! Nothing,
43//! }
44//!
45//! assert!(MyInt(11) == MyInt(5) + 6.into());
46//! assert!((5, 6) == Point2D { x: 5, y: 6 }.into());
47//! assert!(MyEnum::Int(15) == (MyEnum::Int(8) + 7.into()).unwrap());
48//! assert!(MyEnum::Int(15).to_string() == "int: 15");
49//! assert!(MyEnum::Uint(42).to_string() == "42");
50//! assert!(MyEnum::Nothing.to_string() == "nothing");
51//! ```
52//!
53//! ## The derivable traits
54//!
55//! Below are all the traits that you can derive using this library.
56//! Some trait derivations are so similar that the further documentation will only show a single one
57//! of them.
58//! You can recognize these by the "-like" suffix in their name.
59//! The trait name before that will be the only one that is used throughout the further
60//! documentation.
61//!
62//! It is important to understand what code gets generated when using one of the
63//! derives from this crate.
64//! That is why the links below explain what code gets generated for a trait for
65//! each group from before.
66//!
67//! You can use the [`cargo-expand`] utility to see the exact code that is generated
68//! for your specific type.
69//! This will show you your code with all macros and derives expanded.
70//!
71//! **NOTE**: You still have to derive each trait separately. So `#[derive(Mul)]` doesn't
72//! automatically derive `Div` as well. To derive both you should do `#[derive(Mul, Div)]`
73//!
74//! ### Conversion traits
75//!
76//! These are traits that are used to convert automatically between types.
77//!
78//! 1. [`From`]
79//! 2. [`Into`]
80//! 3. [`FromStr`]
81//! 4. [`TryInto`]
82//! 5. [`IntoIterator`]
83//! 6. [`AsRef`]
84//! 7. [`AsMut`]
85//!
86//! ### Formatting traits
87//!
88//! These traits are used for converting a struct to a string in different ways.
89//!
90//! 1. [`Display`-like], contains `Display`, `Binary`, `Octal`, `LowerHex`,
91//! `UpperHex`, `LowerExp`, `UpperExp`, `Pointer`
92//!
93//! ### Error-handling traits
94//! These traits are used to define error-types.
95//!
96//! 1. [`Error`]
97//!
98//! ### Operators
99//!
100//! These are traits that can be used for operator overloading.
101//!
102//! 1. [`Index`]
103//! 2. [`Deref`]
104//! 3. [`Not`-like], contains `Not` and `Neg`
105//! 4. [`Add`-like], contains `Add`, `Sub`, `BitAnd`, `BitOr`, `BitXor`
106//! 5. [`Mul`-like], contains `Mul`, `Div`, `Rem`, `Shr` and `Shl`
107//! 3. [`Sum`-like], contains `Sum` and `Product`
108//! 6. [`IndexMut`]
109//! 7. [`DerefMut`]
110//! 8. [`AddAssign`-like], contains `AddAssign`, `SubAssign`, `BitAndAssign`,
111//! `BitOrAssign` and `BitXorAssign`
112//! 9. [`MulAssign`-like], contains `MulAssign`, `DivAssign`, `RemAssign`,
113//! `ShrAssign` and `ShlAssign`
114//!
115//! ### Static methods
116//!
117//! These don't derive traits, but derive static methods instead.
118//!
119//! 1. [`Constructor`], this derives a `new` method that can be used as a constructor.
120//! This is very basic if you need more customization for your constructor, check
121//! out the [`derive-new`] crate.
122//! 2. [`IsVariant`], for each variant `foo` of an enum type, derives a `is_foo` method.
123//! 3. [`Unwrap`], for each variant `foo` of an enum type, derives an `unwrap_foo` method.
124//!
125//! ## Generated code
126//!
127//! ## Installation
128//!
129//! This library requires Rust 1.36 or higher and it supports `no_std` out of the box.
130//! Then add the following to `Cargo.toml`:
131//!
132//! ```toml
133//! [dependencies]
134//! derive_more = "0.99.0"
135//! # You can specifiy the types of derives that you need for less time spent
136//! # compiling. For the full list of features see this crate its Cargo.toml.
137//! default-features = false
138//! features = ["from", "add", "iterator"]
139//! ```
140//!
141//! And this to the top of your Rust file for Rust 2018:
142//!
143//! ```rust
144//! extern crate derive_more;
145//! // use the derives that you want in the file
146//! use derive_more::{Add, Display, From};
147//! ```
148//! If you're still using Rust 2015 you should add this instead:
149//! ```rust
150//! extern crate core;
151//! #[macro_use]
152//! extern crate derive_more;
153//! # fn main(){}
154//! ```
155//!
156//! [`cargo-expand`]: https://github.com/dtolnay/cargo-expand
157//! [`derive-new`]: https://github.com/nrc/derive-new
158//!
159//! [`From`]: https://jeltef.github.io/derive_more/derive_more/from.html
160//! [`Into`]: https://jeltef.github.io/derive_more/derive_more/into.html
161//! [`FromStr`]: https://jeltef.github.io/derive_more/derive_more/from_str.html
162//! [`TryInto`]: https://jeltef.github.io/derive_more/derive_more/try_into.html
163//! [`IntoIterator`]: https://jeltef.github.io/derive_more/derive_more/into_iterator.html
164//! [`AsRef`]: https://jeltef.github.io/derive_more/derive_more/as_ref.html
165//! [`AsMut`]: https://jeltef.github.io/derive_more/derive_more/as_mut.html
166//!
167//! [`Display`-like]: https://jeltef.github.io/derive_more/derive_more/display.html
168//!
169//! [`Error`]: https://jeltef.github.io/derive_more/derive_more/error.html
170//!
171//! [`Index`]: https://jeltef.github.io/derive_more/derive_more/index_op.html
172//! [`Deref`]: https://jeltef.github.io/derive_more/derive_more/deref.html
173//! [`Not`-like]: https://jeltef.github.io/derive_more/derive_more/not.html
174//! [`Add`-like]: https://jeltef.github.io/derive_more/derive_more/add.html
175//! [`Mul`-like]: https://jeltef.github.io/derive_more/derive_more/mul.html
176//! [`Sum`-like]: https://jeltef.github.io/derive_more/derive_more/sum.html
177//! [`IndexMut`]: https://jeltef.github.io/derive_more/derive_more/index_mut.html
178//! [`DerefMut`]: https://jeltef.github.io/derive_more/derive_more/deref_mut.html
179//! [`AddAssign`-like]: https://jeltef.github.io/derive_more/derive_more/add_assign.html
180//! [`MulAssign`-like]: https://jeltef.github.io/derive_more/derive_more/mul_assign.html
181//!
182//! [`Constructor`]: https://jeltef.github.io/derive_more/derive_more/constructor.html
183//! [`IsVariant`]: https://jeltef.github.io/derive_more/derive_more/is_variant.html
184//! [`Unwrap`]: https://jeltef.github.io/derive_more/derive_more/unwrap.html
185
186#![recursion_limit = "128"]
187
188extern crate proc_macro;
189
190use proc_macro::TokenStream;
191use syn::parse::Error as ParseError;
192
193mod utils;
194
195#[cfg(any(feature = "add_assign", feature = "mul_assign"))]
196mod add_assign_like;
197#[cfg(any(
198 feature = "add",
199 feature = "add_assign",
200 feature = "mul",
201 feature = "mul_assign",
202))]
203mod add_helpers;
204#[cfg(any(feature = "add", feature = "mul"))]
205mod add_like;
206#[cfg(feature = "as_mut")]
207mod as_mut;
208#[cfg(feature = "as_ref")]
209mod as_ref;
210#[cfg(feature = "constructor")]
211mod constructor;
212#[cfg(feature = "deref")]
213mod deref;
214#[cfg(feature = "deref_mut")]
215mod deref_mut;
216#[cfg(feature = "display")]
217mod display;
218#[cfg(feature = "error")]
219mod error;
220#[cfg(feature = "from")]
221mod from;
222#[cfg(feature = "from_str")]
223mod from_str;
224#[cfg(feature = "index")]
225mod index;
226#[cfg(feature = "index_mut")]
227mod index_mut;
228#[cfg(feature = "into")]
229mod into;
230#[cfg(feature = "into_iterator")]
231mod into_iterator;
232#[cfg(feature = "is_variant")]
233mod is_variant;
234#[cfg(feature = "mul_assign")]
235mod mul_assign_like;
236#[cfg(any(feature = "mul", feature = "mul_assign"))]
237mod mul_helpers;
238#[cfg(feature = "mul")]
239mod mul_like;
240#[cfg(feature = "not")]
241mod not_like;
242#[cfg(feature = "display")]
243#[allow(ellipsis_inclusive_range_patterns)]
244#[allow(clippy::all)]
245mod parsing;
246#[cfg(feature = "sum")]
247mod sum_like;
248#[cfg(feature = "try_into")]
249mod try_into;
250#[cfg(feature = "unwrap")]
251mod unwrap;
252
253// This trait describes the possible return types of
254// the derives. A derive can generally be infallible and
255// return a TokenStream, or it can be fallible and return
256// a Result<TokenStream, syn::parse::Error>.
257trait Output {
258 fn process(self) -> TokenStream;
259}
260
261impl Output for proc_macro2::TokenStream {
262 fn process(self) -> TokenStream {
263 self.into()
264 }
265}
266
267impl Output for Result<proc_macro2::TokenStream, ParseError> {
268 fn process(self) -> TokenStream {
269 match self {
270 Ok(ts: TokenStream) => ts.into(),
271 Err(e: Error) => e.to_compile_error().into(),
272 }
273 }
274}
275
276macro_rules! create_derive(
277 ($feature:literal, $mod_:ident, $trait_:ident, $fn_name: ident $(,$attribute:ident)* $(,)?) => {
278 #[cfg(feature = $feature)]
279 #[proc_macro_derive($trait_, attributes($($attribute),*))]
280 #[doc(hidden)]
281 pub fn $fn_name(input: TokenStream) -> TokenStream {
282 let ast = syn::parse(input).unwrap();
283 Output::process($mod_::expand(&ast, stringify!($trait_)))
284 }
285 }
286);
287
288create_derive!("from", from, From, from_derive, from);
289
290create_derive!("into", into, Into, into_derive, into);
291
292create_derive!("constructor", constructor, Constructor, constructor_derive);
293
294create_derive!("not", not_like, Not, not_derive);
295create_derive!("not", not_like, Neg, neg_derive);
296
297create_derive!("add", add_like, Add, add_derive);
298create_derive!("add", add_like, Sub, sub_derive);
299create_derive!("add", add_like, BitAnd, bit_and_derive);
300create_derive!("add", add_like, BitOr, bit_or_derive);
301create_derive!("add", add_like, BitXor, bit_xor_derive);
302
303create_derive!("mul", mul_like, Mul, mul_derive, mul);
304create_derive!("mul", mul_like, Div, div_derive, div);
305create_derive!("mul", mul_like, Rem, rem_derive, rem);
306create_derive!("mul", mul_like, Shr, shr_derive, shr);
307create_derive!("mul", mul_like, Shl, shl_derive, shl);
308
309create_derive!("add_assign", add_assign_like, AddAssign, add_assign_derive,);
310create_derive!("add_assign", add_assign_like, SubAssign, sub_assign_derive,);
311create_derive!(
312 "add_assign",
313 add_assign_like,
314 BitAndAssign,
315 bit_and_assign_derive,
316);
317create_derive!(
318 "add_assign",
319 add_assign_like,
320 BitOrAssign,
321 bit_or_assign_derive,
322);
323create_derive!(
324 "add_assign",
325 add_assign_like,
326 BitXorAssign,
327 bit_xor_assign_derive,
328);
329
330create_derive!(
331 "mul_assign",
332 mul_assign_like,
333 MulAssign,
334 mul_assign_derive,
335 mul_assign,
336);
337create_derive!(
338 "mul_assign",
339 mul_assign_like,
340 DivAssign,
341 div_assign_derive,
342 div_assign,
343);
344create_derive!(
345 "mul_assign",
346 mul_assign_like,
347 RemAssign,
348 rem_assign_derive,
349 rem_assign,
350);
351create_derive!(
352 "mul_assign",
353 mul_assign_like,
354 ShrAssign,
355 shr_assign_derive,
356 shr_assign,
357);
358create_derive!(
359 "mul_assign",
360 mul_assign_like,
361 ShlAssign,
362 shl_assign_derive,
363 shl_assign,
364);
365
366create_derive!("sum", sum_like, Sum, sum_derive);
367create_derive!("sum", sum_like, Product, product_derive);
368
369create_derive!("error", error, Error, error_derive, error);
370
371create_derive!("from_str", from_str, FromStr, from_str_derive);
372
373create_derive!("display", display, Display, display_derive, display);
374create_derive!("display", display, Binary, binary_derive, binary);
375create_derive!("display", display, Octal, octal_derive, octal);
376create_derive!("display", display, LowerHex, lower_hex_derive, lower_hex);
377create_derive!("display", display, UpperHex, upper_hex_derive, upper_hex);
378create_derive!("display", display, LowerExp, lower_exp_derive, lower_exp);
379create_derive!("display", display, UpperExp, upper_exp_derive, upper_exp);
380create_derive!("display", display, Pointer, pointer_derive, pointer);
381create_derive!("display", display, DebugCustom, debug_custom_derive, debug);
382
383create_derive!("index", index, Index, index_derive, index);
384create_derive!(
385 "index_mut",
386 index_mut,
387 IndexMut,
388 index_mut_derive,
389 index_mut,
390);
391
392create_derive!(
393 "into_iterator",
394 into_iterator,
395 IntoIterator,
396 into_iterator_derive,
397 into_iterator,
398);
399
400create_derive!("try_into", try_into, TryInto, try_into_derive, try_into);
401
402create_derive!("deref", deref, Deref, deref_derive, deref);
403create_derive!(
404 "deref_mut",
405 deref_mut,
406 DerefMut,
407 deref_mut_derive,
408 deref_mut,
409);
410
411create_derive!("as_ref", as_ref, AsRef, as_ref_derive, as_ref);
412create_derive!("as_mut", as_mut, AsMut, as_mut_derive, as_mut);
413
414create_derive!(
415 "is_variant",
416 is_variant,
417 IsVariant,
418 is_variant_derive,
419 is_variant
420);
421
422create_derive!("unwrap", unwrap, Unwrap, unwrap_derive, unwrap);
423