1use rustc_data_structures::fx::FxHashMap;
2use rustc_macros::{Decodable, Encodable, Walkable};
3use rustc_span::{Ident, Span, Symbol};
4
5use crate::Expr;
6use crate::ptr::P;
7use crate::token::LitKind;
8
9#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
45pub struct FormatArgs {
46 pub span: Span,
47 pub template: Vec<FormatArgsPiece>,
48 pub arguments: FormatArguments,
49 pub uncooked_fmt_str: (LitKind, Symbol),
53 pub is_source_literal: bool,
61}
62
63#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
67pub enum FormatArgsPiece {
68 Literal(Symbol),
69 Placeholder(FormatPlaceholder),
70}
71
72#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
77pub struct FormatArguments {
78 arguments: Vec<FormatArgument>,
79 num_unnamed_args: usize,
80 num_explicit_args: usize,
81 names: FxHashMap<Symbol, usize>,
82}
83
84impl FormatArguments {
85 pub fn new() -> Self {
86 Self {
87 arguments: Vec::new(),
88 names: FxHashMap::default(),
89 num_unnamed_args: 0,
90 num_explicit_args: 0,
91 }
92 }
93
94 pub fn add(&mut self, arg: FormatArgument) -> usize {
95 let index = self.arguments.len();
96 if let Some(name) = arg.kind.ident() {
97 self.names.insert(name.name, index);
98 } else if self.names.is_empty() {
99 self.num_unnamed_args += 1;
102 }
103 if !matches!(arg.kind, FormatArgumentKind::Captured(..)) {
104 assert_eq!(
107 self.num_explicit_args,
108 self.arguments.len(),
109 "captured arguments must be added last"
110 );
111 self.num_explicit_args += 1;
112 }
113 self.arguments.push(arg);
114 index
115 }
116
117 pub fn by_name(&self, name: Symbol) -> Option<(usize, &FormatArgument)> {
118 let i = *self.names.get(&name)?;
119 Some((i, &self.arguments[i]))
120 }
121
122 pub fn by_index(&self, i: usize) -> Option<&FormatArgument> {
123 (i < self.num_explicit_args).then(|| &self.arguments[i])
124 }
125
126 pub fn unnamed_args(&self) -> &[FormatArgument] {
127 &self.arguments[..self.num_unnamed_args]
128 }
129
130 pub fn named_args(&self) -> &[FormatArgument] {
131 &self.arguments[self.num_unnamed_args..self.num_explicit_args]
132 }
133
134 pub fn explicit_args(&self) -> &[FormatArgument] {
135 &self.arguments[..self.num_explicit_args]
136 }
137
138 pub fn all_args(&self) -> &[FormatArgument] {
139 &self.arguments[..]
140 }
141
142 pub fn all_args_mut(&mut self) -> &mut Vec<FormatArgument> {
143 &mut self.arguments
144 }
145}
146
147#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
148pub struct FormatArgument {
149 pub kind: FormatArgumentKind,
150 pub expr: P<Expr>,
151}
152
153#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
154pub enum FormatArgumentKind {
155 Normal,
157 Named(Ident),
159 Captured(Ident),
161}
162
163impl FormatArgumentKind {
164 pub fn ident(&self) -> Option<Ident> {
165 match self {
166 &Self::Normal => None,
167 &Self::Named(id) => Some(id),
168 &Self::Captured(id) => Some(id),
169 }
170 }
171}
172
173#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, Walkable)]
174pub struct FormatPlaceholder {
175 pub argument: FormatArgPosition,
177 pub span: Option<Span>,
179 #[visitable(ignore)]
181 pub format_trait: FormatTrait,
182 #[visitable(ignore)]
184 pub format_options: FormatOptions,
185}
186
187#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, Walkable)]
188pub struct FormatArgPosition {
189 #[visitable(ignore)]
192 pub index: Result<usize, usize>,
193 #[visitable(ignore)]
195 pub kind: FormatArgPositionKind,
196 pub span: Option<Span>,
198}
199
200#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
201pub enum FormatArgPositionKind {
202 Implicit,
204 Number,
206 Named,
208}
209
210#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq, Hash)]
211pub enum FormatTrait {
212 Display,
214 Debug,
216 LowerExp,
218 UpperExp,
220 Octal,
222 Pointer,
224 Binary,
226 LowerHex,
228 UpperHex,
230}
231
232#[derive(Clone, Encodable, Decodable, Default, Debug, PartialEq, Eq)]
233pub struct FormatOptions {
234 pub width: Option<FormatCount>,
236 pub precision: Option<FormatCount>,
238 pub alignment: Option<FormatAlignment>,
240 pub fill: Option<char>,
242 pub sign: Option<FormatSign>,
244 pub alternate: bool,
246 pub zero_pad: bool,
248 pub debug_hex: Option<FormatDebugHex>,
250}
251
252#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
253pub enum FormatSign {
254 Plus,
256 Minus,
258}
259
260#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
261pub enum FormatDebugHex {
262 Lower,
264 Upper,
266}
267
268#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
269pub enum FormatAlignment {
270 Left,
272 Right,
274 Center,
276}
277
278#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
279pub enum FormatCount {
280 Literal(u16),
282 Argument(FormatArgPosition),
284}