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}