1use rustc_data_structures::fx::FxHashMap;
2use rustc_macros::{Decodable, Encodable, Walkable};
3use rustc_span::{Ident, Span, Symbol};
4
5use crate::Expr;
6use crate::token::LitKind;
7
8#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
44pub struct FormatArgs {
45 pub span: Span,
46 pub template: Vec<FormatArgsPiece>,
47 pub arguments: FormatArguments,
48 pub uncooked_fmt_str: (LitKind, Symbol),
52 pub is_source_literal: bool,
60}
61
62#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
66pub enum FormatArgsPiece {
67 Literal(Symbol),
68 Placeholder(FormatPlaceholder),
69}
70
71#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
76pub struct FormatArguments {
77 arguments: Vec<FormatArgument>,
78 num_unnamed_args: usize,
79 num_explicit_args: usize,
80 names: FxHashMap<Symbol, usize>,
81}
82
83impl FormatArguments {
84 pub fn new() -> Self {
85 Self {
86 arguments: Vec::new(),
87 names: FxHashMap::default(),
88 num_unnamed_args: 0,
89 num_explicit_args: 0,
90 }
91 }
92
93 pub fn add(&mut self, arg: FormatArgument) -> usize {
94 let index = self.arguments.len();
95 if let Some(name) = arg.kind.ident() {
96 self.names.insert(name.name, index);
97 } else if self.names.is_empty() {
98 self.num_unnamed_args += 1;
101 }
102 if !matches!(arg.kind, FormatArgumentKind::Captured(..)) {
103 assert_eq!(
106 self.num_explicit_args,
107 self.arguments.len(),
108 "captured arguments must be added last"
109 );
110 self.num_explicit_args += 1;
111 }
112 self.arguments.push(arg);
113 index
114 }
115
116 pub fn by_name(&self, name: Symbol) -> Option<(usize, &FormatArgument)> {
117 let i = *self.names.get(&name)?;
118 Some((i, &self.arguments[i]))
119 }
120
121 pub fn by_index(&self, i: usize) -> Option<&FormatArgument> {
122 (i < self.num_explicit_args).then(|| &self.arguments[i])
123 }
124
125 pub fn unnamed_args(&self) -> &[FormatArgument] {
126 &self.arguments[..self.num_unnamed_args]
127 }
128
129 pub fn named_args(&self) -> &[FormatArgument] {
130 &self.arguments[self.num_unnamed_args..self.num_explicit_args]
131 }
132
133 pub fn explicit_args(&self) -> &[FormatArgument] {
134 &self.arguments[..self.num_explicit_args]
135 }
136
137 pub fn all_args(&self) -> &[FormatArgument] {
138 &self.arguments[..]
139 }
140
141 pub fn all_args_mut(&mut self) -> &mut Vec<FormatArgument> {
142 &mut self.arguments
143 }
144}
145
146#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
147pub struct FormatArgument {
148 pub kind: FormatArgumentKind,
149 pub expr: Box<Expr>,
150}
151
152#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
153pub enum FormatArgumentKind {
154 Normal,
156 Named(Ident),
158 Captured(Ident),
160}
161
162impl FormatArgumentKind {
163 pub fn ident(&self) -> Option<Ident> {
164 match self {
165 &Self::Normal => None,
166 &Self::Named(id) => Some(id),
167 &Self::Captured(id) => Some(id),
168 }
169 }
170}
171
172#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, Walkable)]
173pub struct FormatPlaceholder {
174 pub argument: FormatArgPosition,
176 pub span: Option<Span>,
178 #[visitable(ignore)]
180 pub format_trait: FormatTrait,
181 #[visitable(ignore)]
183 pub format_options: FormatOptions,
184}
185
186#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq, Walkable)]
187pub struct FormatArgPosition {
188 #[visitable(ignore)]
191 pub index: Result<usize, usize>,
192 #[visitable(ignore)]
194 pub kind: FormatArgPositionKind,
195 pub span: Option<Span>,
197}
198
199#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
200pub enum FormatArgPositionKind {
201 Implicit,
203 Number,
205 Named,
207}
208
209#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq, Hash)]
210pub enum FormatTrait {
211 Display,
213 Debug,
215 LowerExp,
217 UpperExp,
219 Octal,
221 Pointer,
223 Binary,
225 LowerHex,
227 UpperHex,
229}
230
231#[derive(Clone, Encodable, Decodable, Default, Debug, PartialEq, Eq)]
232pub struct FormatOptions {
233 pub width: Option<FormatCount>,
235 pub precision: Option<FormatCount>,
237 pub alignment: Option<FormatAlignment>,
239 pub fill: Option<char>,
241 pub sign: Option<FormatSign>,
243 pub alternate: bool,
245 pub zero_pad: bool,
247 pub debug_hex: Option<FormatDebugHex>,
249}
250
251#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
252pub enum FormatSign {
253 Plus,
255 Minus,
257}
258
259#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
260pub enum FormatDebugHex {
261 Lower,
263 Upper,
265}
266
267#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
268pub enum FormatAlignment {
269 Left,
271 Right,
273 Center,
275}
276
277#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
278pub enum FormatCount {
279 Literal(u16),
281 Argument(FormatArgPosition),
283}