core_extensions/macros/
macro_utils.rs

1/// Rewraps the tokens inside macro parameters into parentheses.
2///
3/// # Syntax
4/// 
5/// This macro transforms `~` immediately followed by a macro parameter 
6/// into its tokens wrapped in parentheses.
7/// 
8/// You can escape `~` by writing it twice (`~~`), returning a single `~` from the macro.
9/// 
10/// # Example
11/// 
12/// ```rust
13/// pub use core_extensions::rewrap_macro_parameters;
14/// 
15/// crate::constify!{
16///     pub fn foo() -> u32 {
17///         100
18///     }
19///     pub unsafe fn bar() -> u32 {
20///         200
21///     }
22/// }
23/// 
24/// const X: &[u32] = unsafe{ &[foo(), bar()] };
25/// 
26/// fn main() {
27///     assert_eq!(X, &[100, 200]);
28/// }
29/// 
30/// #[macro_export]
31/// macro_rules! constify {
32///     ($($item:item)*) => {
33///         rewrap_macro_parameters!{
34///             $crate::__priv_constify_inner!{
35///                 hello world ~~~~
36///                 // `__priv_constify_inner` can't destructure `$item`,
37///                 // so you need to use `rewrap_macro_parameters` and prefix the parameter with
38///                 // `~` to rewrap its tokens in parentheses
39///                 $(~$item)*
40///             }
41///         }
42///     }
43/// }
44/// 
45/// #[macro_export]
46/// #[doc(hidden)]
47/// macro_rules! __priv_constify_inner{
48///     (
49///         hello world ~ ~
50///         $((
51///             $(#[$attr:meta])*
52///             $vis:vis
53///             $(unsafe $(@$unsafe:tt@)?)?
54///             fn
55///             $($rem:tt)*
56///         ))*
57///     ) => {
58///         $(
59///             $(#[$attr])*
60///             $vis const $(unsafe $(@$unsafe@)?)? fn
61///             $($rem)*
62///         )*
63///     }
64/// }
65/// 
66/// 
67/// 
68/// ```
69/// 
70#[cfg_attr(feature = "docsrs", doc(cfg(feature = "macro_utils")))]
71#[macro_export]
72macro_rules! rewrap_macro_parameters {
73    (
74        $($tokens:tt)*
75    ) => {
76        $crate::__::__priv_rewrap_macro_parameters!{
77            $($tokens)*
78        }
79    };
80}
81
82
83#[doc(hidden)]
84#[macro_export]
85macro_rules! __priv_usize_const {
86    ($value:literal) => {
87        pub const __USIZE_CONST: $crate::__::usize = $value;
88    };
89}
90
91
92if_rust_1_46!{
93    /// Counts the amount of token trees passed to this macro,
94    /// passing the amount to an (optional) callback macro.
95    /// 
96    /// 
97    /// Note that macro parameters (eg: `$foo`) are one token tree,
98    /// and matched pairs of `[]`/`()`/`{}` count as one token tree regardless of 
99    /// the tokens inside.
100    /// 
101    /// # Callback
102    /// 
103    /// You need to pass a callback macro whenever the macro expects a literal.
104    /// 
105    /// If you only need the count for an expression(ie: the length of an array),
106    /// then no callback macro is necessary.
107    /// 
108    /// # Version compatibility
109    /// 
110    /// This macro requires Rust 1.45.0 to be invoked with a callback parameter,
111    /// inside an expression.
112    ///
113    /// # Example
114    /// 
115    /// ```rust
116    /// use core_extensions::count_tts;
117    /// 
118    /// fn main() {
119    ///     // The counted tokens must be wrapped in parentheses,
120    ///     // otherwise passing a callback macro would be syntactically ambiguous.
121    ///     assert_eq!(count_tts!(()), 0);
122    ///     assert_eq!(count_tts!((zero)), 1);
123    ///     assert_eq!(count_tts!((zero one)), 2);
124    ///     assert_eq!(count_tts!((zero (one two three) four)), 3);
125    ///     
126    ///     assert_eq!(hello(), "hello");
127    /// }
128    ///
129    /// macro_rules! expects_5{
130    ///     (
131    ///         foo $ident:ident baz
132    ///         5
133    ///     ) => {
134    ///         fn $ident() -> &'static str {
135    ///             stringify!($ident) 
136    ///         }
137    ///     }
138    /// }
139    /// 
140    /// // Calls the `expects_5` macro.
141    /// count_tts!{
142    ///     // The invoked macro, and the first arguments passed to it
143    ///     expects_5!{foo hello baz}
144    ///
145    ///     // The token trees to count
146    ///     (a [b c d] (e f) {g h i} 10 )
147    /// }
148    /// ```
149    /// 
150    #[cfg_attr(feature = "docsrs", doc(cfg(feature = "macro_utils")))]
151    =>
152    (
153        #[macro_export]
154        macro_rules! count_tts {
155            ($parentheses:tt) => {{
156                mod __ {
157                    $crate::__::count_tts!{
158                        $crate::__priv_usize_const!{}
159                        $parentheses
160                    }
161                }
162                __::__USIZE_CONST
163            }};
164            ($($everything:tt)*) => {
165                $crate::__::count_tts!{$($everything)*}
166            };
167        }
168    )
169    (
170        pub use core_extensions_proc_macros::count_tts;
171    )
172}
173
174
175/// Generates identifiers. passing them to a callback macro.
176/// 
177/// # Repetition Syntax
178/// 
179/// The syntax for describing the generated identifiers:
180/// 
181/// `for <ident> * in <range>`
182/// 
183/// Where `<ident>` is any valid identifier.
184/// 
185/// Where `<range>` can be either `<number> .. <number>` or `<number> ..= <number>`.
186/// 
187/// <span id = "number-syntax"></span>
188/// Where `<number>` can be any of:
189/// 
190/// - An integer literal
191/// 
192/// - `count(....)`: Which counts the amount of token trees in `(....)`.
193/// Macro parameters (eg: `$foo`) are one token tree,
194/// and matched pairs of `[]`/`()`/`{}` count as one token tree regardless of 
195/// the tokens inside.
196/// 
197/// [`count_tts`]: ./macro.count_tts.html
198/// 
199/// # Version compatibility
200/// 
201/// This macro requires Rust 1.45.0 to be invoked inside of a function.
202/// 
203/// # Example
204/// 
205/// ### Basic
206/// 
207/// Basic examples of using this macro, and what it passes to a callback macro.
208/// 
209/// For a more realistic example you can look [at the one below](#realistic-example)
210/// 
211/// ```rust
212/// use core_extensions::gen_ident_range;
213/// 
214/// fn main() {
215///     assert_eq!(hello(), "world");
216///     assert_eq!(foo(), "bar");
217/// }
218/// 
219/// // Calls the `expected_0_to_2` macro.
220/// gen_ident_range!{
221///     crate::expected_0_to_2!{hello "world"}
222///     for stuff_* in 0..3
223/// }
224/// 
225/// // Calls the `expected_1_to_4` macro.
226/// gen_ident_range!{
227///     crate::expected_1_to_4!{foo "bar" baz}
228///     // `count(....)` here counts 4 token trees
229///     for pre_* in 1..=count(a (b c) [d e f] {g h i j})
230/// }
231///
232/// #[macro_export]
233/// macro_rules! expected_0_to_2{
234///     ($func:ident $lit:literal  (stuff_0 stuff_1 stuff_2)) => {
235///         fn $func() -> &'static str {
236///             $lit
237///         }
238///     }
239/// }
240/// 
241/// #[macro_export]
242/// macro_rules! expected_1_to_4{
243///     ($func:ident $lit:literal baz  (pre_1 pre_2 pre_3 pre_4)) => {
244///         fn $func() -> &'static str {
245///             $lit
246///         }
247///     }
248/// }
249/// ```
250/// 
251/// <div id = "realistic-example"></div>
252///
253/// ### More Realistic Example
254/// 
255/// ```rust
256/// use core_extensions::gen_ident_range;
257/// 
258/// fn main() {
259///     assert_eq!(add_unsigned(3, 5, 8), 16);
260///     assert_eq!(add_signed(-3, 8), 5);
261/// 
262/// }
263/// 
264/// adder_fn!{ pub fn add_unsigned(u16, u32, u64) -> u64 }
265/// adder_fn!{ fn add_signed(i8, i16) -> i64 }
266/// 
267/// 
268/// 
269/// #[macro_export]
270/// macro_rules! adder_fn {
271///     ($vis:vis fn $func:ident ($($arg_ty:ty),* $(,)?) -> $ret_ty:ty) => {
272///         gen_ident_range!{
273///             $crate::__priv_adder_fn!{
274///                 ($vis fn $func ($($arg_ty,)*) -> $ret_ty)
275///             }
276///             for arg_* in 0..count($($arg_ty)*)
277///         }
278///     }
279/// }
280/// 
281/// #[macro_export]
282/// macro_rules! __priv_adder_fn {
283///     (
284///         ($vis:vis fn $func:ident ($($arg_ty:ty,)*) -> $ret_ty:ty)
285///         ($($arg:ident)*)
286///     ) => {
287///         $vis fn $func($($arg: $arg_ty,)*) -> $ret_ty {
288///             // assuming that Default::default is zero or empty
289///             <$ret_ty as $crate::__::Default>::default()
290///             $(
291///                 + <$ret_ty as $crate::__::From<_>>::from($arg)
292///             )*
293///         }
294///     }
295/// }
296/// 
297/// 
298/// #[doc(hidden)]
299/// pub mod __ {
300///     pub use core_extensions::gen_ident_range;
301///     
302///     pub use std::convert::From;
303///     pub use std::default::Default;
304/// }
305/// 
306/// ```
307/// 
308#[cfg_attr(feature = "docsrs", doc(cfg(feature = "macro_utils")))]
309pub use core_extensions_proc_macros::gen_ident_range;
310
311/// For using function-like macros as attributes.
312/// 
313/// # Examples
314/// 
315/// ### Module
316/// 
317/// ```rust
318/// use core_extensions::macro_attr;
319/// 
320/// fn main() {
321///     assert_eq!(hello::Hello(3, 5).sum(), 8);
322///     assert_eq!(hello::Hello(13, 21).sum(), 34);
323/// }
324/// 
325/// #[macro_attr(in_mod!(pub mod hello;))]
326/// #[derive(Debug, PartialEq)]
327/// pub struct Hello(pub u32, pub u32);
328/// 
329/// impl hello::Hello {
330///     const fn sum(&self) -> u64 {
331///         self.0 as u64 + self.1 as u64
332///     }
333/// }
334/// 
335/// #[macro_export]
336/// macro_rules! in_mod {
337///     (
338///         $(#[$attr:meta])*
339///         $vis:vis mod $module:ident;
340///         
341///         $($item:item)*
342///     ) => {
343///         $(#[$attr])*
344///         $vis mod $module {
345///             $($item)*
346///         }
347///     }
348/// }
349/// 
350/// ```
351/// 
352/// ### Item count
353/// 
354/// This example only works from 1.46.0 onwards, not sure why.
355/// 
356#[cfg_attr(feature = "rust_1_46", doc = "```rust")]
357#[cfg_attr(not(feature = "rust_1_46"), doc = "```ignore")]
358/// use core_extensions::macro_attr;
359/// 
360/// fn main() {
361///     assert_eq!(items::COUNT, 4);
362///
363///     assert_eq!(items::foo(), 3);
364///     assert_eq!(items::BAR, 5);
365/// }
366/// 
367/// #[macro_attr(crate::and_item_count)]
368/// pub mod items {
369///     pub fn foo() -> u32 {
370///         3
371///     }
372///
373///     pub const BAR: u32 = 5;
374///     
375///     pub struct Baz;
376///
377///     pub struct Qux {
378///         pub x: u64,
379///         pub y: u64,
380///     }
381/// }
382/// 
383/// #[macro_export]
384/// macro_rules! and_item_count {
385///     (
386///         $(#[$attr:meta])*
387///         $vis:vis mod $module:ident {
388///             $($item:item)*
389///         }
390///     ) => {
391///         $(#[$attr])*
392///         $vis mod $module {
393///             pub const COUNT: usize = $crate::__::count_tts!(($($item)*));
394///             
395///             $($item)*
396///         }
397///     }
398/// }
399/// 
400/// #[doc(hidden)]
401/// mod __ {
402///     pub use core_extensions::count_tts;
403/// }
404/// ```
405/// 
406#[cfg_attr(feature = "docsrs", doc(cfg(feature = "macro_utils")))]
407pub use core_extensions_proc_macros::macro_attr;
408
409
410
411/// Stringifies the input tokens, and errors with `compile_error`.
412/// 
413/// Ỳou can use this to show the tokens passed to a macro.
414#[macro_export]
415#[cfg_attr(feature = "docsrs", doc(cfg(feature = "macro_utils")))]
416macro_rules! compile_error_stringify {
417    ($($tt:tt)*) => {
418        $crate::__::compile_error!{
419            $crate::__::stringify!($($tt)*)
420        }
421    };
422}
423
424
425include!{"./macro_utils/tokens_method.rs"}
426
427
428/// Adaptor macro which passes arguments to a callback macro, wrapping them in parentheses.
429/// 
430/// # Example
431/// 
432/// ```rust
433/// use core_extensions::{count_tts, parenthesize_args};
434/// 
435/// 
436/// fn main() {
437///     assert_eq!(foo(), 5);
438/// }
439/// 
440/// macro_rules! the_macro {
441///     ($func:ident $count:literal) => {
442///         pub fn $func() -> u32 { $count }
443///     }
444/// }
445///
446/// // `parenthesize_args` invokes `count_tts` here,
447/// // then `count_tts` counts `a b c d e` as having 5 tokens,
448/// // passing `5` as the `$count` parameter to `the_macro`.
449/// parenthesize_args!{
450///     count_tts!{
451///         the_macro!{foo}
452///     }
453///     a b c d e
454/// }
455/// 
456/// ```
457#[macro_export]
458#[cfg_attr(feature = "docsrs", doc(cfg(feature = "macro_utils")))]
459macro_rules! parenthesize_args {
460    (
461        $(:: $(@$leading:tt@)? )? $first:ident $(:: $trailing:ident)* ! { $($prefix:tt)* }
462
463        $($extra:tt)*
464    ) => {
465        $(:: $(@$leading@)? )? $first $(:: $trailing)* ! {
466            $($prefix)*
467            ($($extra)*)
468        }
469    };
470}