| 1 | #![doc = include_str!("../README.md" )] |
| 2 | #![cfg_attr (docsrs, feature(doc_auto_cfg))] |
| 3 | #![recursion_limit = "128" ] |
| 4 | #![cfg_attr (any(not(docsrs), ci), deny(rustdoc::all))] |
| 5 | #![forbid (non_ascii_idents, unsafe_code)] |
| 6 | #![warn (clippy::nonstandard_macro_braces)] |
| 7 | |
| 8 | use proc_macro::TokenStream; |
| 9 | use syn::parse::Error as ParseError; |
| 10 | |
| 11 | mod utils; |
| 12 | |
| 13 | #[cfg (any(feature = "add_assign" , feature = "mul_assign" ))] |
| 14 | mod add_assign_like; |
| 15 | #[cfg (any( |
| 16 | feature = "add" , |
| 17 | feature = "add_assign" , |
| 18 | feature = "mul" , |
| 19 | feature = "mul_assign" , |
| 20 | ))] |
| 21 | mod add_helpers; |
| 22 | #[cfg (any(feature = "add" , feature = "mul" ))] |
| 23 | mod add_like; |
| 24 | #[cfg (feature = "as_ref" )] |
| 25 | mod r#as; |
| 26 | #[cfg (feature = "constructor" )] |
| 27 | mod constructor; |
| 28 | #[cfg (feature = "deref" )] |
| 29 | mod deref; |
| 30 | #[cfg (feature = "deref_mut" )] |
| 31 | mod deref_mut; |
| 32 | #[cfg (feature = "error" )] |
| 33 | mod error; |
| 34 | #[cfg (any(feature = "debug" , feature = "display" ))] |
| 35 | mod fmt; |
| 36 | #[cfg (feature = "from" )] |
| 37 | mod from; |
| 38 | #[cfg (feature = "from_str" )] |
| 39 | mod from_str; |
| 40 | #[cfg (feature = "index" )] |
| 41 | mod index; |
| 42 | #[cfg (feature = "index_mut" )] |
| 43 | mod index_mut; |
| 44 | #[cfg (feature = "into" )] |
| 45 | mod into; |
| 46 | #[cfg (feature = "into_iterator" )] |
| 47 | mod into_iterator; |
| 48 | #[cfg (feature = "is_variant" )] |
| 49 | mod is_variant; |
| 50 | #[cfg (feature = "mul_assign" )] |
| 51 | mod mul_assign_like; |
| 52 | #[cfg (any(feature = "mul" , feature = "mul_assign" ))] |
| 53 | mod mul_helpers; |
| 54 | #[cfg (feature = "mul" )] |
| 55 | mod mul_like; |
| 56 | #[cfg (feature = "not" )] |
| 57 | mod not_like; |
| 58 | #[cfg (any(feature = "debug" , feature = "display" ))] |
| 59 | pub(crate) mod parsing; |
| 60 | #[cfg (feature = "sum" )] |
| 61 | mod sum_like; |
| 62 | #[cfg (feature = "try_from" )] |
| 63 | mod try_from; |
| 64 | #[cfg (feature = "try_into" )] |
| 65 | mod try_into; |
| 66 | #[cfg (feature = "try_unwrap" )] |
| 67 | mod try_unwrap; |
| 68 | #[cfg (feature = "unwrap" )] |
| 69 | mod unwrap; |
| 70 | |
| 71 | // This trait describes the possible return types of |
| 72 | // the derives. A derive can generally be infallible and |
| 73 | // return a TokenStream, or it can be fallible and return |
| 74 | // a Result<TokenStream, syn::parse::Error>. |
| 75 | // |
| 76 | // This trait can be unused if no feature is enabled. We already error in that case but this |
| 77 | // warning distracts from the actual error. |
| 78 | #[allow (dead_code)] |
| 79 | trait Output { |
| 80 | fn process(self) -> TokenStream; |
| 81 | } |
| 82 | |
| 83 | impl Output for proc_macro2::TokenStream { |
| 84 | fn process(self) -> TokenStream { |
| 85 | self.into() |
| 86 | } |
| 87 | } |
| 88 | |
| 89 | impl Output for Result<proc_macro2::TokenStream, ParseError> { |
| 90 | fn process(self) -> TokenStream { |
| 91 | match self { |
| 92 | Ok(ts: TokenStream) => ts.into(), |
| 93 | Err(e: Error) => e.to_compile_error().into(), |
| 94 | } |
| 95 | } |
| 96 | } |
| 97 | |
| 98 | macro_rules! create_derive( |
| 99 | ($feature:literal, $mod_:ident $(:: $mod_rest:ident)*, $trait_:ident, $fn_name: ident $(,$attribute:ident)* $(,)?) => { |
| 100 | #[cfg(feature = $feature)] |
| 101 | #[proc_macro_derive($trait_, attributes($($attribute),*))] |
| 102 | #[doc = include_str!(concat!("../doc/" , $feature, ".md" ))] |
| 103 | pub fn $fn_name(input: TokenStream) -> TokenStream { |
| 104 | let ast = syn::parse(input).unwrap(); |
| 105 | Output::process($mod_$(:: $mod_rest)*::expand(&ast, stringify!($trait_))) |
| 106 | } |
| 107 | } |
| 108 | ); |
| 109 | |
| 110 | create_derive!("add" , add_like, Add, add_derive); |
| 111 | create_derive!("add" , add_like, Sub, sub_derive); |
| 112 | create_derive!("add" , add_like, BitAnd, bit_and_derive); |
| 113 | create_derive!("add" , add_like, BitOr, bit_or_derive); |
| 114 | create_derive!("add" , add_like, BitXor, bit_xor_derive); |
| 115 | |
| 116 | create_derive!("add_assign" , add_assign_like, AddAssign, add_assign_derive,); |
| 117 | create_derive!("add_assign" , add_assign_like, SubAssign, sub_assign_derive,); |
| 118 | create_derive!( |
| 119 | "add_assign" , |
| 120 | add_assign_like, |
| 121 | BitAndAssign, |
| 122 | bit_and_assign_derive, |
| 123 | ); |
| 124 | create_derive!( |
| 125 | "add_assign" , |
| 126 | add_assign_like, |
| 127 | BitOrAssign, |
| 128 | bit_or_assign_derive, |
| 129 | ); |
| 130 | create_derive!( |
| 131 | "add_assign" , |
| 132 | add_assign_like, |
| 133 | BitXorAssign, |
| 134 | bit_xor_assign_derive, |
| 135 | ); |
| 136 | |
| 137 | create_derive!("as_ref" , r#as::r#mut, AsMut, as_mut_derive, as_mut); |
| 138 | create_derive!("as_ref" , r#as::r#ref, AsRef, as_ref_derive, as_ref); |
| 139 | |
| 140 | create_derive!("constructor" , constructor, Constructor, constructor_derive); |
| 141 | |
| 142 | create_derive!("debug" , fmt::debug, Debug, debug_derive, debug); |
| 143 | |
| 144 | create_derive!("deref" , deref, Deref, deref_derive, deref); |
| 145 | |
| 146 | create_derive!( |
| 147 | "deref_mut" , |
| 148 | deref_mut, |
| 149 | DerefMut, |
| 150 | deref_mut_derive, |
| 151 | deref_mut, |
| 152 | ); |
| 153 | |
| 154 | create_derive!("display" , fmt::display, Display, display_derive, display); |
| 155 | create_derive!("display" , fmt::display, Binary, binary_derive, binary); |
| 156 | create_derive!("display" , fmt::display, Octal, octal_derive, octal); |
| 157 | create_derive!( |
| 158 | "display" , |
| 159 | fmt::display, |
| 160 | LowerHex, |
| 161 | lower_hex_derive, |
| 162 | lower_hex, |
| 163 | ); |
| 164 | create_derive!( |
| 165 | "display" , |
| 166 | fmt::display, |
| 167 | UpperHex, |
| 168 | upper_hex_derive, |
| 169 | upper_hex, |
| 170 | ); |
| 171 | create_derive!( |
| 172 | "display" , |
| 173 | fmt::display, |
| 174 | LowerExp, |
| 175 | lower_exp_derive, |
| 176 | lower_exp, |
| 177 | ); |
| 178 | create_derive!( |
| 179 | "display" , |
| 180 | fmt::display, |
| 181 | UpperExp, |
| 182 | upper_exp_derive, |
| 183 | upper_exp, |
| 184 | ); |
| 185 | create_derive!("display" , fmt::display, Pointer, pointer_derive, pointer); |
| 186 | |
| 187 | create_derive!("error" , error, Error, error_derive, error); |
| 188 | |
| 189 | create_derive!("from" , from, From, from_derive, from); |
| 190 | |
| 191 | create_derive!("from_str" , from_str, FromStr, from_str_derive); |
| 192 | |
| 193 | create_derive!("index" , index, Index, index_derive, index); |
| 194 | |
| 195 | create_derive!( |
| 196 | "index_mut" , |
| 197 | index_mut, |
| 198 | IndexMut, |
| 199 | index_mut_derive, |
| 200 | index_mut, |
| 201 | ); |
| 202 | |
| 203 | create_derive!("into" , into, Into, into_derive, into); |
| 204 | |
| 205 | create_derive!( |
| 206 | "into_iterator" , |
| 207 | into_iterator, |
| 208 | IntoIterator, |
| 209 | into_iterator_derive, |
| 210 | into_iterator, |
| 211 | ); |
| 212 | |
| 213 | create_derive!( |
| 214 | "is_variant" , |
| 215 | is_variant, |
| 216 | IsVariant, |
| 217 | is_variant_derive, |
| 218 | is_variant, |
| 219 | ); |
| 220 | |
| 221 | create_derive!("mul" , mul_like, Mul, mul_derive, mul); |
| 222 | create_derive!("mul" , mul_like, Div, div_derive, div); |
| 223 | create_derive!("mul" , mul_like, Rem, rem_derive, rem); |
| 224 | create_derive!("mul" , mul_like, Shr, shr_derive, shr); |
| 225 | create_derive!("mul" , mul_like, Shl, shl_derive, shl); |
| 226 | |
| 227 | create_derive!( |
| 228 | "mul_assign" , |
| 229 | mul_assign_like, |
| 230 | MulAssign, |
| 231 | mul_assign_derive, |
| 232 | mul_assign, |
| 233 | ); |
| 234 | create_derive!( |
| 235 | "mul_assign" , |
| 236 | mul_assign_like, |
| 237 | DivAssign, |
| 238 | div_assign_derive, |
| 239 | div_assign, |
| 240 | ); |
| 241 | create_derive!( |
| 242 | "mul_assign" , |
| 243 | mul_assign_like, |
| 244 | RemAssign, |
| 245 | rem_assign_derive, |
| 246 | rem_assign, |
| 247 | ); |
| 248 | create_derive!( |
| 249 | "mul_assign" , |
| 250 | mul_assign_like, |
| 251 | ShrAssign, |
| 252 | shr_assign_derive, |
| 253 | shr_assign, |
| 254 | ); |
| 255 | create_derive!( |
| 256 | "mul_assign" , |
| 257 | mul_assign_like, |
| 258 | ShlAssign, |
| 259 | shl_assign_derive, |
| 260 | shl_assign, |
| 261 | ); |
| 262 | |
| 263 | create_derive!("not" , not_like, Not, not_derive); |
| 264 | create_derive!("not" , not_like, Neg, neg_derive); |
| 265 | |
| 266 | create_derive!("sum" , sum_like, Sum, sum_derive); |
| 267 | create_derive!("sum" , sum_like, Product, product_derive); |
| 268 | |
| 269 | create_derive!("try_from" , try_from, TryFrom, try_from_derive, try_from); |
| 270 | |
| 271 | create_derive!("try_into" , try_into, TryInto, try_into_derive, try_into); |
| 272 | |
| 273 | create_derive!( |
| 274 | "try_unwrap" , |
| 275 | try_unwrap, |
| 276 | TryUnwrap, |
| 277 | try_unwrap_derive, |
| 278 | try_unwrap, |
| 279 | ); |
| 280 | |
| 281 | create_derive!("unwrap" , unwrap, Unwrap, unwrap_derive, unwrap); |
| 282 | |