1 //! # `derive_more`
2 //! Rust has lots of builtin traits that are implemented for its basic types, such as [`Add`],
3 //! [`Not`] or [`From`].
4 //! However, when wrapping these types inside your own structs or enums you lose the
5 //! implementations of these traits and are required to recreate them.
6 //! This is especially annoying when your own structures are very simple, such as when using the
7 //! commonly advised newtype pattern (e.g. `MyInt(i32)`).
8 //!
9 //! This library tries to remove these annoyances and the corresponding boilerplate code.
10 //! It does this by allowing you to derive lots of commonly used traits for both structs and enums.
11 //!
12 //! ## Example code
13 //!
14 //! By using this library the following code just works:
15 //!
16 //!
17 //! ```rust
18 //! #[macro_use]
19 //! extern crate derive_more;
20 //!
21 //! #[derive(Debug, Eq, PartialEq, From, Add)]
22 //! struct MyInt(i32);
23 //!
24 //! #[derive(Debug, Eq, PartialEq, From, Into, Constructor, Mul)]
25 //! struct Point2D {
26 //!     x: i32,
27 //!     y: i32,
28 //! }
29 //!
30 //! #[derive(Debug, Eq, PartialEq, From, Add)]
31 //! enum MyEnum {
32 //!     Int(i32),
33 //!     UnsignedInt(u32),
34 //!     Nothing,
35 //! }
36 //!
37 //! fn main() {
38 //!     let my_11 = MyInt(5) + 6.into();
39 //!     assert_eq!(MyInt(11), MyInt(5) + 6.into());
40 //!     assert_eq!(Point2D { x: 5, y: 6 } * 10, (50, 60).into());
41 //!     assert_eq!((5, 6), Point2D { x: 5, y: 6 }.into());
42 //!     assert_eq!(Point2D { x: 5, y: 6 }, Point2D::new(5, 6));
43 //!     assert_eq!(MyEnum::Int(15), (MyEnum::Int(8) + 7.into()).unwrap())
44 //! }
45 //! ```
46 //!
47 //! ## The derivable traits
48 //!
49 //! Below are all the traits that you can derive using this library.
50 //! Some trait derivations are so similar that the further documentation will only show a single one
51 //! of them.
52 //! You can recognize these by the "-like" suffix in their name.
53 //! The trait name before that will be the only one that is used throughout the further
54 //! documentation.
55 //!
56 //! **NOTE**: You still have to derive each trait separately. So `#[derive(Mul)]` doesn't
57 //! automatically derive `Div` as well. To derive both you should do `#[derive(Mul, Div)]`
58 //!
59 //! ### Conversion traits
60 //! These are traits that are used to convert automatically between types.
61 //!
62 //! 1. [`From`]
63 //! 2. [`Into`]
64 //! 3. [`FromStr`]
65 //! 4. [`TryInto`] (nightly-only as of writing)
66 //!
67 //! ### Formatting traits
68 //! These traits are used for converting a struct to a string in different ways.
69 //!
70 //! 1. `Display`-like, contains [`Display`], [`Binary`], [`Octal`], [`LowerHex`], [`UpperHex`],
71 //!    [`LowerExp`], [`UpperExp`], [`Pointer`]
72 //!
73 //! ### Operators
74 //! These are traits that can be used for operator overloading.
75 //!
76 //! 1. [`Index`]
77 //! 2. [`Deref`]
78 //! 3. `Not`-like, contains [`Not`] and [`Neg`]
79 //! 4. `Add`-like, contains [`Add`], [`Sub`], [`BitAnd`], [`BitOr`] and [`BitXor`]
80 //! 5. `Mul`-like, contains [`Mul`], [`Div`], [`Rem`], [`Shr`] and [`Shl`]
81 //! 6. [`IndexMut`]
82 //! 7. [`DerefMut`]
83 //! 8. `AddAssign`-like, contains [`AddAssign`], [`SubAssign`], [`BitAndAssign`], [`BitOrAssign`]
84 //!    and [`BitXorAssign`]
85 //! 9. `MulAssign`-like, contains [`MulAssign`], [`DivAssign`], [`RemAssign`], [`ShrAssign`] and
86 //!    [`ShlAssign`]
87 //!
88 //! ### Static methods
89 //! These don't derive traits, but derive static methods instead.
90 //!
91 //! 1. `Constructor`, this derives a `new` method that can be used as a constructor. This is very
92 //!    basic if you need more customization for your constructor, check out the [`derive-new`] crate.
93 //!
94 //!
95 //! ## Generated code
96 //!
97 //! It is important to understand what code gets generated when using one of the derives from this
98 //! crate.
99 //! That is why the links below explain what code gets generated for a trait for each group from
100 //! before.
101 //!
102 //! 1. [`#[derive(From)]`](https://jeltef.github.io/derive_more/derive_more/from.html)
103 //! 2. [`#[derive(Into)]`](https://jeltef.github.io/derive_more/derive_more/into.html)
104 //! 3. [`#[derive(FromStr)]`](https://jeltef.github.io/derive_more/derive_more/from_str.html)
105 //! 4. [`#[derive(TryInto)]`](https://jeltef.github.io/derive_more/derive_more/try_into.html)
106 //! 5. [`#[derive(Display)]`](https://jeltef.github.io/derive_more/derive_more/display.html)
107 //! 6. [`#[derive(Index)]`](https://jeltef.github.io/derive_more/derive_more/index_op.html)
108 //! 7. [`#[derive(Deref)]`](https://jeltef.github.io/derive_more/derive_more/deref.html)
109 //! 8. [`#[derive(Not)]`](https://jeltef.github.io/derive_more/derive_more/not.html)
110 //! 9. [`#[derive(Add)]`](https://jeltef.github.io/derive_more/derive_more/add.html)
111 //! 10. [`#[derive(Mul)]`](https://jeltef.github.io/derive_more/derive_more/mul.html)
112 //! 11. [`#[derive(IndexMut)]`](https://jeltef.github.io/derive_more/derive_more/index_mut.html)
113 //! 12. [`#[derive(DerefMut)]`](https://jeltef.github.io/derive_more/derive_more/deref_mut.html)
114 //! 13. [`#[derive(AddAssign)]`](https://jeltef.github.io/derive_more/derive_more/add_assign.html)
115 //! 14. [`#[derive(MulAssign)]`](https://jeltef.github.io/derive_more/derive_more/mul_assign.html)
116 //! 15. [`#[derive(Constructor)]`](https://jeltef.github.io/derive_more/derive_more/constructor.html)
117 //!
118 //! If you want to be sure what code is generated for your specific type I recommend using the
119 //! [`cargo-expand`] utility.
120 //! This will show you your code with all macros and derives expanded.
121 //!
122 //! ## Installation
123 //!
124 //! This library requires Rust 1.15 or higher, so this needs to be installed.
125 //! Then add the following to `Cargo.toml`:
126 //!
127 //! ```toml
128 //! [dependencies]
129 //! derive_more = "0.13.0"
130 //! ```
131 //!
132 //! And this to the top of your Rust file:
133 //!
134 //! ```rust
135 //! #[macro_use]
136 //! extern crate derive_more;
137 //! # fn main () {}
138 //! ```
139 //!
140 //! [`cargo-expand`]: https://github.com/dtolnay/cargo-expand
141 //! [`derive-new`]: https://github.com/nrc/derive-new
142 //! [`From`]: https://doc.rust-lang.org/core/convert/trait.From.html
143 //! [`Into`]: https://doc.rust-lang.org/core/convert/trait.Into.html
144 //! [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html
145 //! [`TryInto`]: https://doc.rust-lang.org/core/convert/trait.TryInto.html
146 //! [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html
147 //! [`Binary`]: https://doc.rust-lang.org/std/fmt/trait.Binary.html
148 //! [`Octal`]: https://doc.rust-lang.org/std/fmt/trait.Octal.html
149 //! [`LowerHex`]: https://doc.rust-lang.org/std/fmt/trait.LowerHex.html
150 //! [`UpperHex`]: https://doc.rust-lang.org/std/fmt/trait.UpperHex.html
151 //! [`LowerExp`]: https://doc.rust-lang.org/std/fmt/trait.LowerExp.html
152 //! [`UpperExp`]: https://doc.rust-lang.org/std/fmt/trait.UpperExp.html
153 //! [`Pointer`]: https://doc.rust-lang.org/std/fmt/trait.Pointer.html
154 //! [`Index`]: https://doc.rust-lang.org/std/ops/trait.Index.html
155 //! [`Deref`]: https://doc.rust-lang.org/std/ops/trait.Deref.html
156 //! [`Not`]: https://doc.rust-lang.org/std/ops/trait.Not.html
157 //! [`Neg`]: https://doc.rust-lang.org/std/ops/trait.Neg.html
158 //! [`Add`]: https://doc.rust-lang.org/std/ops/trait.Add.html
159 //! [`Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html
160 //! [`BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html
161 //! [`BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html
162 //! [`BitXor`]: https://doc.rust-lang.org/std/ops/trait.BitXor.html
163 //! [`Mul`]: https://doc.rust-lang.org/std/ops/trait.Mul.html
164 //! [`Div`]: https://doc.rust-lang.org/std/ops/trait.Div.html
165 //! [`Rem`]: https://doc.rust-lang.org/std/ops/trait.Rem.html
166 //! [`Shr`]: https://doc.rust-lang.org/std/ops/trait.Shr.html
167 //! [`Shl`]: https://doc.rust-lang.org/std/ops/trait.Shl.html
168 //! [`IndexMut`]: https://doc.rust-lang.org/std/ops/trait.IndexMut.html
169 //! [`DerefMut`]: https://doc.rust-lang.org/std/ops/trait.DerefMut.html
170 //! [`AddAssign`]: https://doc.rust-lang.org/std/ops/trait.AddAssign.html
171 //! [`SubAssign`]: https://doc.rust-lang.org/std/ops/trait.SubAssign.html
172 //! [`BitAndAssign`]: https://doc.rust-lang.org/std/ops/trait.BitAndAssign.html
173 //! [`BitOrAssign`]: https://doc.rust-lang.org/std/ops/trait.BitOrAssign.html
174 //! [`BitXorAssign`]: https://doc.rust-lang.org/std/ops/trait.BitXorAssign.html
175 //! [`MulAssign`]: https://doc.rust-lang.org/std/ops/trait.MulAssign.html
176 //! [`DivAssign`]: https://doc.rust-lang.org/std/ops/trait.DivAssign.html
177 //! [`RemAssign`]: https://doc.rust-lang.org/std/ops/trait.RemAssign.html
178 //! [`ShrAssign`]: https://doc.rust-lang.org/std/ops/trait.ShrAssign.html
179 //! [`ShlAssign`]: https://doc.rust-lang.org/std/ops/trait.ShlAssign.html
180 
181 #![recursion_limit = "128"]
182 extern crate proc_macro;
183 extern crate proc_macro2;
184 #[macro_use]
185 extern crate quote;
186 extern crate syn;
187 
188 use proc_macro::TokenStream;
189 use syn::parse::Error as ParseError;
190 
191 mod utils;
192 
193 mod add_assign_like;
194 mod add_like;
195 mod constructor;
196 mod deref;
197 mod deref_mut;
198 mod display;
199 mod from;
200 mod from_str;
201 mod index;
202 mod index_mut;
203 mod into;
204 mod mul_assign_like;
205 mod mul_like;
206 mod not_like;
207 mod try_into;
208 
209 // This trait describes the possible return types of
210 // the derives. A derive can generally be infallible and
211 // return a TokenStream, or it can be fallible and return
212 // a Result<TokenStream, syn::parse::Error>.
213 trait Output {
process(self) -> TokenStream214     fn process(self) -> TokenStream;
215 }
216 
217 impl Output for proc_macro2::TokenStream {
process(self) -> TokenStream218     fn process(self) -> TokenStream {
219         self.into()
220     }
221 }
222 
223 impl Output for Result<proc_macro2::TokenStream, ParseError> {
process(self) -> TokenStream224     fn process(self) -> TokenStream {
225         match self {
226             Ok(ts) => ts.into(),
227             Err(e) => e.to_compile_error().into(),
228         }
229     }
230 }
231 
232 macro_rules! create_derive(
233     ($mod_:ident, $trait_:ident, $fn_name: ident $(,$attribute:ident)*) => {
234         #[proc_macro_derive($trait_, attributes($($attribute),*))]
235         #[doc(hidden)]
236         pub fn $fn_name(input: TokenStream) -> TokenStream {
237             let ast = syn::parse(input).unwrap();
238             Output::process($mod_::expand(&ast, stringify!($trait_)))
239         }
240     }
241 );
242 
243 create_derive!(from, From, from_derive);
244 
245 create_derive!(into, Into, into_derive);
246 
247 create_derive!(constructor, Constructor, constructor_derive);
248 
249 create_derive!(not_like, Not, not_derive);
250 create_derive!(not_like, Neg, neg_derive);
251 
252 create_derive!(add_like, Add, add_derive);
253 create_derive!(add_like, Sub, sub_derive);
254 create_derive!(add_like, BitAnd, bit_and_derive);
255 create_derive!(add_like, BitOr, bit_or_derive);
256 create_derive!(add_like, BitXor, bit_xor_derive);
257 
258 create_derive!(mul_like, Mul, mul_derive);
259 create_derive!(mul_like, Div, div_derive);
260 create_derive!(mul_like, Rem, rem_derive);
261 create_derive!(mul_like, Shr, shr_derive);
262 create_derive!(mul_like, Shl, shl_derive);
263 
264 create_derive!(add_assign_like, AddAssign, add_assign_derive);
265 create_derive!(add_assign_like, SubAssign, sub_assign_derive);
266 create_derive!(add_assign_like, BitAndAssign, bit_and_assign_derive);
267 create_derive!(add_assign_like, BitOrAssign, bit_or_assign_derive);
268 create_derive!(add_assign_like, BitXorAssign, bit_xor_assign_derive);
269 
270 create_derive!(mul_assign_like, MulAssign, mul_assign_derive);
271 create_derive!(mul_assign_like, DivAssign, div_assign_derive);
272 create_derive!(mul_assign_like, RemAssign, rem_assign_derive);
273 create_derive!(mul_assign_like, ShrAssign, shr_assign_derive);
274 create_derive!(mul_assign_like, ShlAssign, shl_assign_derive);
275 
276 create_derive!(from_str, FromStr, from_str_derive);
277 
278 create_derive!(display, Display, display_derive, display);
279 create_derive!(display, Binary, binary_derive, binary);
280 create_derive!(display, Octal, octal_derive, octal);
281 create_derive!(display, LowerHex, lower_hex_derive, lower_hex);
282 create_derive!(display, UpperHex, upper_hex_derive, upper_hex);
283 create_derive!(display, LowerExp, lower_exp_derive, lower_exp);
284 create_derive!(display, UpperExp, upper_exp_derive, upper_exp);
285 create_derive!(display, Pointer, pointer_derive, pointer);
286 
287 create_derive!(index, Index, index_derive);
288 create_derive!(index_mut, IndexMut, index_mut_derive);
289 
290 create_derive!(try_into, TryInto, try_into_derive);
291 
292 create_derive!(deref, Deref, deref_derive);
293 create_derive!(deref_mut, DerefMut, deref_mut_derive);
294