| 32 | |
| 33 | impl FormatSpec { |
| 34 | fn parse(spec: &str) -> Result<Self, VmError> { |
| 35 | let mut result = FormatSpec::default(); |
| 36 | let mut chars = spec.chars().peekable(); |
| 37 | |
| 38 | // Skip the initial ':' |
| 39 | if chars.next_if_eq(&':').is_some() { |
| 40 | // Parse fill and align |
| 41 | let mut next = chars.peek().copied(); |
| 42 | if let Some(c) = next { |
| 43 | if chars.clone().nth(1).is_some_and(|n| "<>^".contains(n)) { |
| 44 | result.fill = Some(c); |
| 45 | chars.next(); |
| 46 | next = chars.peek().copied(); |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | // Parse align |
| 51 | if let Some(c) = next { |
| 52 | if "<>^".contains(c) { |
| 53 | result.align = Some(c); |
| 54 | chars.next(); |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | // Parse sign |
| 59 | if let Some(c) = chars.peek() { |
| 60 | if "+-".contains(*c) { |
| 61 | result.sign = Some(*c); |
| 62 | chars.next(); |
| 63 | } |
| 64 | } |
| 65 | |
| 66 | // Parse width |
| 67 | let mut width = String::new(); |
| 68 | while let Some(c) = chars.peek() { |
| 69 | if c.is_ascii_digit() { |
| 70 | width.push(*c); |
| 71 | chars.next(); |
| 72 | } else { |
| 73 | break; |
| 74 | } |
| 75 | } |
| 76 | if !width.is_empty() { |
| 77 | result.width = Some(width.parse().unwrap()); |
| 78 | } |
| 79 | |
| 80 | // Parse precision |
| 81 | if chars.next_if_eq(&'.').is_some() { |
| 82 | let mut precision = String::new(); |
| 83 | while let Some(c) = chars.peek() { |
| 84 | if c.is_ascii_digit() { |
| 85 | precision.push(*c); |
| 86 | chars.next(); |
| 87 | } else { |
| 88 | break; |
| 89 | } |
| 90 | } |
| 91 | if !precision.is_empty() { |