Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/rust/quote/format.rs
38271 views
1
// SPDX-License-Identifier: Apache-2.0 OR MIT
2
3
/// Formatting macro for constructing `Ident`s.
4
///
5
/// <br>
6
///
7
/// # Syntax
8
///
9
/// Syntax is copied from the [`format!`] macro, supporting both positional and
10
/// named arguments.
11
///
12
/// Only a limited set of formatting traits are supported. The current mapping
13
/// of format types to traits is:
14
///
15
/// * `{}` ⇒ [`IdentFragment`]
16
/// * `{:o}` ⇒ [`Octal`](std::fmt::Octal)
17
/// * `{:x}` ⇒ [`LowerHex`](std::fmt::LowerHex)
18
/// * `{:X}` ⇒ [`UpperHex`](std::fmt::UpperHex)
19
/// * `{:b}` ⇒ [`Binary`](std::fmt::Binary)
20
///
21
/// See [`std::fmt`] for more information.
22
///
23
/// <br>
24
///
25
/// # IdentFragment
26
///
27
/// Unlike `format!`, this macro uses the [`IdentFragment`] formatting trait by
28
/// default. This trait is like `Display`, with a few differences:
29
///
30
/// * `IdentFragment` is only implemented for a limited set of types, such as
31
/// unsigned integers and strings.
32
/// * [`Ident`] arguments will have their `r#` prefixes stripped, if present.
33
///
34
/// [`IdentFragment`]: crate::IdentFragment
35
/// [`Ident`]: proc_macro2::Ident
36
///
37
/// <br>
38
///
39
/// # Hygiene
40
///
41
/// The [`Span`] of the first `Ident` argument is used as the span of the final
42
/// identifier, falling back to [`Span::call_site`] when no identifiers are
43
/// provided.
44
///
45
/// ```
46
/// # use quote::format_ident;
47
/// # let ident = format_ident!("Ident");
48
/// // If `ident` is an Ident, the span of `my_ident` will be inherited from it.
49
/// let my_ident = format_ident!("My{}{}", ident, "IsCool");
50
/// assert_eq!(my_ident, "MyIdentIsCool");
51
/// ```
52
///
53
/// Alternatively, the span can be overridden by passing the `span` named
54
/// argument.
55
///
56
/// ```
57
/// # use quote::format_ident;
58
/// # const IGNORE_TOKENS: &'static str = stringify! {
59
/// let my_span = /* ... */;
60
/// # };
61
/// # let my_span = proc_macro2::Span::call_site();
62
/// format_ident!("MyIdent", span = my_span);
63
/// ```
64
///
65
/// [`Span`]: proc_macro2::Span
66
/// [`Span::call_site`]: proc_macro2::Span::call_site
67
///
68
/// <p><br></p>
69
///
70
/// # Panics
71
///
72
/// This method will panic if the resulting formatted string is not a valid
73
/// identifier.
74
///
75
/// <br>
76
///
77
/// # Examples
78
///
79
/// Composing raw and non-raw identifiers:
80
/// ```
81
/// # use quote::format_ident;
82
/// let my_ident = format_ident!("My{}", "Ident");
83
/// assert_eq!(my_ident, "MyIdent");
84
///
85
/// let raw = format_ident!("r#Raw");
86
/// assert_eq!(raw, "r#Raw");
87
///
88
/// let my_ident_raw = format_ident!("{}Is{}", my_ident, raw);
89
/// assert_eq!(my_ident_raw, "MyIdentIsRaw");
90
/// ```
91
///
92
/// Integer formatting options:
93
/// ```
94
/// # use quote::format_ident;
95
/// let num: u32 = 10;
96
///
97
/// let decimal = format_ident!("Id_{}", num);
98
/// assert_eq!(decimal, "Id_10");
99
///
100
/// let octal = format_ident!("Id_{:o}", num);
101
/// assert_eq!(octal, "Id_12");
102
///
103
/// let binary = format_ident!("Id_{:b}", num);
104
/// assert_eq!(binary, "Id_1010");
105
///
106
/// let lower_hex = format_ident!("Id_{:x}", num);
107
/// assert_eq!(lower_hex, "Id_a");
108
///
109
/// let upper_hex = format_ident!("Id_{:X}", num);
110
/// assert_eq!(upper_hex, "Id_A");
111
/// ```
112
#[macro_export]
113
macro_rules! format_ident {
114
($fmt:expr) => {
115
$crate::format_ident_impl!([
116
$crate::__private::Option::None,
117
$fmt
118
])
119
};
120
121
($fmt:expr, $($rest:tt)*) => {
122
$crate::format_ident_impl!([
123
$crate::__private::Option::None,
124
$fmt
125
] $($rest)*)
126
};
127
}
128
129
#[macro_export]
130
#[doc(hidden)]
131
macro_rules! format_ident_impl {
132
// Final state
133
([$span:expr, $($fmt:tt)*]) => {
134
$crate::__private::mk_ident(
135
&$crate::__private::format!($($fmt)*),
136
$span,
137
)
138
};
139
140
// Span argument
141
([$old:expr, $($fmt:tt)*] span = $span:expr) => {
142
$crate::format_ident_impl!([$old, $($fmt)*] span = $span,)
143
};
144
([$old:expr, $($fmt:tt)*] span = $span:expr, $($rest:tt)*) => {
145
$crate::format_ident_impl!([
146
$crate::__private::Option::Some::<$crate::__private::Span>($span),
147
$($fmt)*
148
] $($rest)*)
149
};
150
151
// Named argument
152
([$span:expr, $($fmt:tt)*] $name:ident = $arg:expr) => {
153
$crate::format_ident_impl!([$span, $($fmt)*] $name = $arg,)
154
};
155
([$span:expr, $($fmt:tt)*] $name:ident = $arg:expr, $($rest:tt)*) => {
156
match $crate::__private::IdentFragmentAdapter(&$arg) {
157
arg => $crate::format_ident_impl!([$span.or(arg.span()), $($fmt)*, $name = arg] $($rest)*),
158
}
159
};
160
161
// Positional argument
162
([$span:expr, $($fmt:tt)*] $arg:expr) => {
163
$crate::format_ident_impl!([$span, $($fmt)*] $arg,)
164
};
165
([$span:expr, $($fmt:tt)*] $arg:expr, $($rest:tt)*) => {
166
match $crate::__private::IdentFragmentAdapter(&$arg) {
167
arg => $crate::format_ident_impl!([$span.or(arg.span()), $($fmt)*, arg] $($rest)*),
168
}
169
};
170
}
171
172