1use rustc_data_structures::fx::FxHashMap;
2use rustc_macros::{Decodable, Encodable};
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)]
45pub struct FormatArgs {
46 pub span: Span,
47 pub template: Vec<FormatArgsPiece>,
48 pub arguments: FormatArguments,
49 pub uncooked_fmt_str: (LitKind, Symbol),
53}
54
55#[derive(Clone, Encodable, Decodable, Debug)]
59pub enum FormatArgsPiece {
60 Literal(Symbol),
61 Placeholder(FormatPlaceholder),
62}
63
64#[derive(Clone, Encodable, Decodable, Debug)]
69pub struct FormatArguments {
70 arguments: Vec<FormatArgument>,
71 num_unnamed_args: usize,
72 num_explicit_args: usize,
73 names: FxHashMap<Symbol, usize>,
74}
75
76impl FormatArguments {
77 pub fn new() -> Self {
78 Self {
79 arguments: Vec::new(),
80 names: FxHashMap::default(),
81 num_unnamed_args: 0,
82 num_explicit_args: 0,
83 }
84 }
85
86 pub fn add(&mut self, arg: FormatArgument) -> usize {
87 let index = self.arguments.len();
88 if let Some(name) = arg.kind.ident() {
89 self.names.insert(name.name, index);
90 } else if self.names.is_empty() {
91 self.num_unnamed_args += 1;
94 }
95 if !matches!(arg.kind, FormatArgumentKind::Captured(..)) {
96 assert_eq!(
99 self.num_explicit_args,
100 self.arguments.len(),
101 "captured arguments must be added last"
102 );
103 self.num_explicit_args += 1;
104 }
105 self.arguments.push(arg);
106 index
107 }
108
109 pub fn by_name(&self, name: Symbol) -> Option<(usize, &FormatArgument)> {
110 let i = *self.names.get(&name)?;
111 Some((i, &self.arguments[i]))
112 }
113
114 pub fn by_index(&self, i: usize) -> Option<&FormatArgument> {
115 (i < self.num_explicit_args).then(|| &self.arguments[i])
116 }
117
118 pub fn unnamed_args(&self) -> &[FormatArgument] {
119 &self.arguments[..self.num_unnamed_args]
120 }
121
122 pub fn named_args(&self) -> &[FormatArgument] {
123 &self.arguments[self.num_unnamed_args..self.num_explicit_args]
124 }
125
126 pub fn explicit_args(&self) -> &[FormatArgument] {
127 &self.arguments[..self.num_explicit_args]
128 }
129
130 pub fn all_args(&self) -> &[FormatArgument] {
131 &self.arguments[..]
132 }
133
134 pub fn all_args_mut(&mut self) -> &mut Vec<FormatArgument> {
135 &mut self.arguments
136 }
137}
138
139#[derive(Clone, Encodable, Decodable, Debug)]
140pub struct FormatArgument {
141 pub kind: FormatArgumentKind,
142 pub expr: P<Expr>,
143}
144
145#[derive(Clone, Encodable, Decodable, Debug)]
146pub enum FormatArgumentKind {
147 Normal,
149 Named(Ident),
151 Captured(Ident),
153}
154
155impl FormatArgumentKind {
156 pub fn ident(&self) -> Option<Ident> {
157 match self {
158 &Self::Normal => None,
159 &Self::Named(id) => Some(id),
160 &Self::Captured(id) => Some(id),
161 }
162 }
163}
164
165#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
166pub struct FormatPlaceholder {
167 pub argument: FormatArgPosition,
169 pub span: Option<Span>,
171 pub format_trait: FormatTrait,
173 pub format_options: FormatOptions,
175}
176
177#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
178pub struct FormatArgPosition {
179 pub index: Result<usize, usize>,
182 pub kind: FormatArgPositionKind,
184 pub span: Option<Span>,
186}
187
188#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
189pub enum FormatArgPositionKind {
190 Implicit,
192 Number,
194 Named,
196}
197
198#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq, Hash)]
199pub enum FormatTrait {
200 Display,
202 Debug,
204 LowerExp,
206 UpperExp,
208 Octal,
210 Pointer,
212 Binary,
214 LowerHex,
216 UpperHex,
218}
219
220#[derive(Clone, Encodable, Decodable, Default, Debug, PartialEq, Eq)]
221pub struct FormatOptions {
222 pub width: Option<FormatCount>,
224 pub precision: Option<FormatCount>,
226 pub alignment: Option<FormatAlignment>,
228 pub fill: Option<char>,
230 pub sign: Option<FormatSign>,
232 pub alternate: bool,
234 pub zero_pad: bool,
236 pub debug_hex: Option<FormatDebugHex>,
238}
239
240#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
241pub enum FormatSign {
242 Plus,
244 Minus,
246}
247
248#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
249pub enum FormatDebugHex {
250 Lower,
252 Upper,
254}
255
256#[derive(Copy, Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
257pub enum FormatAlignment {
258 Left,
260 Right,
262 Center,
264}
265
266#[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
267pub enum FormatCount {
268 Literal(usize),
270 Argument(FormatArgPosition),
272}