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