Parses a printf-style format string into a Formatter with validation. This method implements a comprehensive parser for Java `java.util.Formatter` syntax, processing the format string character by character to identify and validate format specifiers against the provided argument types. # Arguments `fmt` - The format string containing literal text and format specifiers `arg_types` - Array of Dat
(fmt: &'a str, arg_types: &[DataType])
| 283 | /// Returns a Formatter containing the parsed elements and the maximum argument |
| 284 | /// index encountered, enabling efficient argument validation during formatting. |
| 285 | pub fn parse(fmt: &'a str, arg_types: &[DataType]) -> Result<Self> { |
| 286 | // find the first % |
| 287 | let mut res = Vec::new(); |
| 288 | |
| 289 | let mut rem = fmt; |
| 290 | let mut argument_index = 0; |
| 291 | |
| 292 | let mut prev: Option<usize> = None; |
| 293 | |
| 294 | while !rem.is_empty() { |
| 295 | if let Some((verbatim_prefix, rest)) = rem.split_once('%') { |
| 296 | if !verbatim_prefix.is_empty() { |
| 297 | res.push(FormatElement::Verbatim(verbatim_prefix)); |
| 298 | } |
| 299 | if let Some(rest) = rest.strip_prefix('%') { |
| 300 | res.push(FormatElement::Verbatim("%")); |
| 301 | rem = rest; |
| 302 | continue; |
| 303 | } |
| 304 | if let Some(rest) = rest.strip_prefix('n') { |
| 305 | res.push(FormatElement::Verbatim("\n")); |
| 306 | rem = rest; |
| 307 | continue; |
| 308 | } |
| 309 | if let Some(rest) = rest.strip_prefix('<') { |
| 310 | // %< means reuse the previous argument |
| 311 | let Some(p) = prev else { |
| 312 | return exec_err!("No previous argument to reference"); |
| 313 | }; |
| 314 | let (spec, rest) = |
| 315 | take_conversion_specifier(rest, p, &arg_types[p - 1])?; |
| 316 | res.push(FormatElement::Format(spec)); |
| 317 | rem = rest; |
| 318 | continue; |
| 319 | } |
| 320 | |
| 321 | let (current_argument_index, rest2) = take_numeric_param(rest, false); |
| 322 | let (current_argument_index, rest) = |
| 323 | match (current_argument_index, rest2.starts_with('$')) { |
| 324 | (NumericParam::Literal(index), true) => { |
| 325 | (index as usize, &rest2[1..]) |
| 326 | } |
| 327 | (NumericParam::FromArgument, true) => { |
| 328 | return exec_err!("Invalid numeric parameter"); |
| 329 | } |
| 330 | (_, false) => { |
| 331 | argument_index += 1; |
| 332 | (argument_index, rest) |
| 333 | } |
| 334 | }; |
| 335 | if current_argument_index == 0 || current_argument_index > arg_types.len() |
| 336 | { |
| 337 | return exec_err!( |
| 338 | "Argument index {} is out of bounds", |
| 339 | current_argument_index |
| 340 | ); |
| 341 | } |
| 342 |
no test coverage detected