1use std::str::FromStr;
2
3use crate::NonMaxU32;
4
5use super::{defns::*, defns_const::*, error::*};
6
7macro_rules! map_opt {
8 ($e:expr, $s:pat => $t:expr) => {
9 match $e {
10 Some($s) => Some($t),
11 None => None,
12 }
13 };
14 ($s:ident => $t:expr) => {
15 map_opt!($s, $s => $t)
16 };
17 ($e:expr, $s:pat => $t:expr, $d:expr) => {
18 match $e {
19 Some($s) => $t,
20 None => $d,
21 }
22 };
23 ($s:ident => $t:expr, $d:expr) => {
24 map_opt!($s, $s => $t, $d)
25 };
26 ($e:expr, Err($d:expr)) => {
27 match $e {
28 Some(s) => s,
29 None => return Err($d),
30 }
31 };
32}
33
34macro_rules! map_res {
35 ($e:expr) => {
36 map_res!($e, s => s, err => return Err(err))
37 };
38 ($e:expr, $err:ident => $f:expr) => {
39 map_res!($e, s => s, $err => return Err($f))
40 };
41 ($e:expr, $s:pat => $t:expr, $err:ident => $f:expr) => {
42 match $e {
43 Ok($s) => $t,
44 Err($err) => $f,
45 }
46 };
47}
48
49macro_rules! panic {
50 () => {
51 loop {
52 #[allow(unconditional_panic, clippy::out_of_bounds_indexing)]
53 [][0]
54 }
55 };
56}
57
58impl ChildIndex {
61 pub const fn parse(s: &str) -> ResultFormatterConst<'_, ([Option<Self>; 8], Self)> {
62 let tail = ConstOperations::strip_prefix(s, '#');
63 let s = map_opt!(tail, Err(ParseErrorConst::missing_hash(s)));
64 let rest = ConstOperations::split(s, ':');
65 let (_, mut last, mut rest) = rest.next::<false>();
66 let mut path: [Option<ChildIndex>; 8] = [None; 8];
67 let mut idx = 0;
68 while let Some(split) = rest {
69 path[idx] = Some(map_res!(Self::parse_single(last)));
70 idx += 1;
71 if idx >= 8 {
72 return Err(ParseErrorConst::too_many_children(s));
73 }
74 (_, last, rest) = split.next::<false>();
75 }
76 Ok((path, map_res!(Self::parse_single(last))))
77 }
78
79 pub const fn parse_single(s: &str) -> ResultFormatterConst<'_, Self> {
80 let index = map_res!(ConstOperations::parse_i32(s));
81 let index = map_opt!(
82 nonmax::NonMaxI32::new(index),
83 Err(ParseErrorConst::invalid_number(s))
84 );
85 Ok(Self(index))
86 }
87}
88
89impl ChildRange {
90 pub const fn parse(s: &str) -> ResultFormatterConst<'_, Self> {
91 let split = ConstOperations::split_2_first(s, '.', '.');
92 let (from, to) = map_opt!(split, Err(ParseErrorConst::missing_range(s)));
93 let (path, from) = map_res!(ChildIndex::parse(from));
94 let to = map_res!(ChildIndex::parse_single(to));
95 Ok(ChildRange { path, from, to })
96 }
97}
98
99impl BindPowerPair {
100 pub const fn parse(s: &str) -> ResultFormatterConst<'_, (bool, Self)> {
101 let split = ConstOperations::split(s, ',');
102 let (_, first, split) = split.next::<false>();
103 let first = map_res!(ConstOperations::parse_u32(first));
104 let (second, split) = ConstOperations::split_more(split);
105 let second = map_opt!(second => map_res!(ConstOperations::parse_u32(second)));
106 match (second, split) {
107 (.., Some(split)) => Err(ParseErrorConst::too_many_control(split)),
108 (None, ..) => Ok((false, BindPowerPair::symmetric(first))),
109 (Some(second), None) => Ok((true, BindPowerPair::asymmetric(first, second))),
110 }
111 }
112}
113
114impl SubFormatterSingle {
115 pub const fn parse(s: &str) -> ResultFormatterConst<'_, Self> {
117 let split = ConstOperations::split(s, SEPARATOR_CHARACTER);
118 let (_, index, split) = split.next::<false>();
119 let (path, index) = map_res!(ChildIndex::parse(index));
120 let bind_power = map_opt!(
121 split => map_res!(BindPowerPair::parse(split.remainder())).1,
122 BindPowerPair::symmetric(DEFAULT_BIND_POWER)
123 );
124 Ok(Self {
125 path,
126 index,
127 bind_power,
128 })
129 }
130}
131
132impl<'a> SubFormatterRepeatConst<'a> {
133 pub const fn parse(s: &'a str) -> ResultFormatterConst<'a, Self> {
134 let split = ConstOperations::split(s, CONTROL_CHARACTER);
135 let (_, left, sep) = split.next::<false>();
136
137 let left = ConstOperations::split(left, SEPARATOR_CHARACTER);
139 let (_, range, split) = left.next::<false>();
140 let range = map_res!(ChildRange::parse(range));
141 let (left, middle, right) = map_res!(Self::parse_triple(split));
142
143 let mut left_sep = SubFormatterRepeatSeparator::default();
145 let mut middle_sep = SubFormatterRepeatSeparator::default();
146 let mut right_sep = SubFormatterRepeatSeparator::default();
147 if let Some(sep) = sep {
148 let sep = ConstOperations::split(sep.remainder(), SEPARATOR_CHARACTER);
149 let (separator_deduplicate, separator, sep) = sep.next::<true>();
150 if let Some(sep_two) = sep {
151 left_sep.separator_deduplicate = separator_deduplicate;
152 left_sep.separator = separator;
153 let (separator_deduplicate, separator, sep) = sep_two.next::<true>();
154 let sep =
155 map_opt!(sep => sep, return Err(ParseErrorConst::too_many_control(sep_two)));
156 middle_sep.separator_deduplicate = separator_deduplicate;
157 middle_sep.separator = separator;
158 let (separator_deduplicate, separator, sep) = sep.next::<true>();
159 #[allow(unreachable_code, clippy::diverging_sub_expression)]
160 {
161 map_opt!(sep => return Err(ParseErrorConst::too_many_control(sep)));
162 }
163 right_sep.separator_deduplicate = separator_deduplicate;
164 right_sep.separator = separator;
165 } else {
166 middle_sep.separator_deduplicate = separator_deduplicate;
167 middle_sep.separator = separator;
168 }
169 }
170 Ok(Self {
171 range,
172 left_sep,
173 middle_sep,
174 right_sep,
175 left,
176 middle,
177 right,
178 })
179 }
180 const fn parse_triple(
182 split: Option<ConstSplit<'a, 1>>,
183 ) -> ResultFormatterConst<'a, (BindPower, BindPowerPair, BindPower)> {
184 const DEFAULT: BindPowerPair = BindPowerPair::symmetric(DEFAULT_BIND_POWER);
185 let split =
186 map_opt!(split => split, return Ok((DEFAULT_BIND_POWER, DEFAULT, DEFAULT_BIND_POWER)));
187 let (_, first, split) = split.next::<false>();
188 let (pair, fst) = map_res!(BindPowerPair::parse(first));
189 if pair {
190 let split =
192 map_opt!(split => split, return Ok((DEFAULT_BIND_POWER, fst, DEFAULT_BIND_POWER)));
193 let (_, second, split) = split.next::<false>();
194 #[allow(unreachable_code, clippy::diverging_sub_expression)]
195 {
196 map_opt!(split => return Err(ParseErrorConst::too_many_control(split)));
197 }
198 let (pair, snd) = map_res!(BindPowerPair::parse(second));
199 return if pair {
200 Err(ParseErrorConst::unexpected_pair(second))
201 } else {
202 let snd = snd.left;
204 Ok((DEFAULT_BIND_POWER, fst, snd))
205 };
206 }
207 let split = map_opt!(split => split, return Ok((fst.left, fst, fst.right)));
209 let fst = fst.left;
210 let (_, second, split) = split.next::<false>();
212 let (pair, snd) = map_res!(BindPowerPair::parse(second));
213 let split = map_opt!(split => split, return Ok(if pair {
214 (fst, snd, DEFAULT_BIND_POWER)
215 } else {
216 let snd = snd.left;
218 (fst, DEFAULT, snd)
219 }));
220 let (_, third, split) = split.next::<false>();
222 #[allow(unreachable_code, clippy::diverging_sub_expression)]
223 {
224 map_opt!(split => return Err(ParseErrorConst::too_many_control(split)));
225 }
226 let (pair, thrd) = map_res!(BindPowerPair::parse(third));
227 if pair {
228 Err(ParseErrorConst::unexpected_pair(third))
229 } else {
230 let thrd = thrd.left;
232 Ok((fst, snd, thrd))
233 }
234 }
235}
236
237impl<'a> SubFormatterConst<'a> {
238 pub const fn parse_control(s: &'a str) -> ResultFormatterConst<'a, (Self, &'a str)> {
239 if let Some(s) = ConstOperations::strip_prefix(s, '[') {
240 let split = ConstOperations::split_2(s, ']', CONTROL_CHARACTER);
241 let (_, control, split) = split.next::<false>();
242 let split = map_opt!(split, Err(ParseErrorConst::missing_control(s, "]$")));
243 let control = map_res!(SubFormatterSingle::parse(control));
244 return Ok((Self::Single(control), split.remainder()));
245 }
246 if let Some(s) = ConstOperations::strip_prefix(s, '(') {
247 let split = ConstOperations::split_2(s, ')', CONTROL_CHARACTER);
248 let (_, control, split) = split.next::<false>();
249 let split = map_opt!(split, Err(ParseErrorConst::missing_control(s, ")$")));
250 let control = map_res!(SubFormatterRepeatConst::parse(control));
251 return Ok((Self::Repeat(control), split.remainder()));
252 }
253 if let Some(s) = ConstOperations::strip_prefix(s, '{') {
254 let split = ConstOperations::split_2(s, '}', CONTROL_CHARACTER);
255 let (_, inner, split) = split.next::<false>();
256 let split = map_opt!(split, Err(ParseErrorConst::missing_control(s, "}$")));
257 let capture = map_res!(ConstOperations::parse_u32(inner));
258 if capture >= i32::MIN as u32 {
259 return Err(ParseErrorConst::capture_overflow(inner));
260 }
261 let capture = map_opt!(NonMaxU32::new(capture), s => s, panic!());
262 return Ok((Self::Capture(capture), split.remainder()));
263 }
264 Err(ParseErrorConst::incorrect_control(s))
265 }
266 pub const fn parse_one(s: &'a str) -> SubFormatterConstParseOneResult<'a> {
267 let split = ConstOperations::split(s, CONTROL_CHARACTER);
268 let (control_deduplicate, first, rest) = split.next::<true>();
269 let first = if first.is_empty() {
270 None
271 } else {
272 Some(SubFormatterString {
273 data: first,
274 control_deduplicate,
275 })
276 };
277 let rest = map_opt!(rest => map_res!(Self::parse_control(rest.remainder())));
278 Ok((first, rest))
279 }
280}
281
282pub type SubFormatterConstParseOneResult<'a> = ResultFormatterConst<
283 'a,
284 (
285 Option<SubFormatterString<'a>>,
286 Option<(SubFormatterConst<'a>, &'a str)>,
287 ),
288>;
289
290impl<'a> FormatterConst<'a> {
291 const INIT: Option<SubFormatterConst<'a>> = None;
292 pub const fn parse(full: &'a str) -> ResultFormatterConst<'a, Self> {
293 let mut s = full;
294 let mut bind_power = BindPowerPair::symmetric(DEFAULT_BIND_POWER);
295 if let Some(rest) = ConstOperations::strip_prefix(s, CONTROL_CHARACTER) {
296 let (left, rest) = map_opt!(
297 ConstOperations::split_first(rest, CONTROL_CHARACTER),
298 Err(ParseErrorConst::missing_control(rest, "$"))
299 );
300 let left = map_res!(ConstOperations::parse_u32(left));
301 bind_power.left = left;
302 s = rest;
303 }
304 if let Some(rest) = ConstOperations::strip_suffix(s, CONTROL_CHARACTER) {
305 let (right, rest) = map_opt!(
306 ConstOperations::split_last(rest, CONTROL_CHARACTER),
307 Err(ParseErrorConst::missing_control(rest, "$"))
308 );
309 let right = map_res!(ConstOperations::parse_u32(right));
310 bind_power.right = right;
311 s = rest;
312 }
313
314 let mut outputs = [Self::INIT; 64];
315 let mut idx = 0;
316 loop {
317 let (str, ctrl) = map_res!(SubFormatterConst::parse_one(s));
318 if let Some(str) = str {
319 outputs[idx] = Some(SubFormatterConst::String(str));
320 idx += 1;
321 }
322 let Some((ctrl, rest)) = ctrl else {
323 break;
324 };
325 outputs[idx] = Some(ctrl);
326 idx += 1;
327 s = rest;
328 }
329 Ok(Self {
330 bind_power,
331 outputs,
332 })
333 }
334}
335
336impl<'a> MatcherConst<'a> {
337 pub const fn parse(s: &'a str) -> ResultMatcherConst<'a, Self> {
338 let (s, children) = map_res!(Self::parse_children(s));
339 let regex = map_opt!(ConstOperations::strip_prefix(s, '/'), s => ConstOperations::strip_suffix(s, '/'), None);
340 let (data, kind) = if let Some(regex) = regex {
341 (regex, MatcherKindConst::Regex)
342 } else {
343 (s, MatcherKindConst::Exact)
344 };
345 Ok(Self {
346 data,
347 children,
348 kind,
349 })
350 }
351 pub const fn parse_children(
352 s: &'a str,
353 ) -> ResultMatcherConst<'a, (&'a str, Option<NonMaxU32>)> {
354 let mut has_bracket = true;
355 let s = map_opt!(ConstOperations::strip_prefix(s, '('), s => s, { has_bracket = false; s });
356 let mut s = match ConstOperations::strip_suffix(s, ')') {
357 Some(s) if has_bracket => s,
358 None if !has_bracket => return Ok((s, None)),
359 Some(s) => return Err(ParseErrorConst::invalid_children_spec(s)),
360 None => return Err(ParseErrorConst::invalid_children_spec(s)),
361 };
362 let mut children = NonMaxU32::ZERO;
363 while let Some(rest) = ConstOperations::strip_suffix(s, '_') {
364 let Some(rest) = ConstOperations::strip_suffix(rest, ' ') else {
365 break;
366 };
367 let new = NonMaxU32::new(children.get() + 1);
368 children = map_opt!(new, Err(ParseErrorConst::invalid_children_spec(s)));
369 s = rest;
370 }
371 Ok((s, Some(children)))
372 }
373}
374
375impl<'a> TermDisplayConst<'a> {
376 pub const fn parse(m: &'a str, f: &'a str) -> ResultConst<'a, Self> {
377 let matcher = map_res!(MatcherConst::parse(m), err => ParseErrorConst::matcher(err));
378 let formatter = map_res!(FormatterConst::parse(f), err => ParseErrorConst::formatter(err));
379 if matches!(matcher.kind, MatcherKindConst::Exact) && formatter.max_capture().is_some() {
380 return Err(ParseErrorConst::invalid_capture(m));
381 }
382 Ok(Self { matcher, formatter })
383 }
384}
385
386impl FromStr for ChildIndex {
389 type Err = FormatterParseError;
390 fn from_str(s: &str) -> Result<Self, Self::Err> {
391 Ok(Self::parse_single(s)?)
392 }
393}
394
395impl FromStr for ChildRange {
396 type Err = FormatterParseError;
397 fn from_str(s: &str) -> Result<Self, Self::Err> {
398 Ok(Self::parse(s)?)
399 }
400}
401
402impl FromStr for SubFormatterSingle {
403 type Err = FormatterParseError;
404 fn from_str(s: &str) -> Result<Self, Self::Err> {
405 Ok(Self::parse(s)?)
406 }
407}
408
409impl FromStr for SubFormatterRepeat {
410 type Err = FormatterParseError;
411 fn from_str(s: &str) -> Result<Self, Self::Err> {
412 let self_ = SubFormatterRepeatConst::parse(s)?;
413 self_.try_into()
414 }
415}
416
417impl FromStr for Formatter {
418 type Err = FormatterParseError;
419 fn from_str(s: &str) -> Result<Self, Self::Err> {
420 FormatterConst::parse(s)?.try_into()
421 }
422}
423
424impl FromStr for FallbackFormatter {
425 type Err = FallbackParseError;
426 fn from_str(s: &str) -> Result<Self, Self::Err> {
427 FallbackFormatter::new(s.parse().map_err(FallbackParseError::FormatterParseError)?)
428 }
429}
430
431impl FromStr for Matcher {
432 type Err = ConversionError;
433 fn from_str(s: &str) -> Result<Self, Self::Err> {
434 Ok(MatcherConst::parse(s)
435 .map_err(ParseError::from)?
436 .try_into()?)
437 }
438}
439
440#[derive(Debug, Clone, Copy)]
443pub(super) struct ConstSplit<'a, const N: usize>(&'a str, [u8; N]);
444
445struct Check<const SKIP_DOUBLE: bool, const N: usize>;
446impl<const SKIP_DOUBLE: bool, const N: usize> Check<SKIP_DOUBLE, N> {
447 #[allow(clippy::no_effect)]
448 const CHECK_N_SIZE: () = {
449 ["N must be 1 or 2"][!(N == 1 || N == 2) as usize];
450 ["N must be 1 when SKIP_DOUBLE"][!(N == 1 || !SKIP_DOUBLE) as usize];
451 };
452}
453
454impl<'a, const N: usize> ConstSplit<'a, N> {
455 #[allow(path_statements, clippy::no_effect)]
456 const fn next<const SKIP_DOUBLE: bool>(self) -> (bool, &'a str, Option<Self>) {
457 Check::<SKIP_DOUBLE, N>::CHECK_N_SIZE;
458
459 let full = self.0.as_bytes();
460 let mut s = full;
461 let mut skipped = false;
462 let mut idx = 0;
463 let reached_sep = loop {
464 match s {
465 [] => break None,
466 [b, n, r @ ..] if N == 1 && SKIP_DOUBLE && *b == self.1[0] && *n == self.1[0] => {
467 skipped = true;
468 idx += 2;
469 s = r;
470 }
471 [b, r @ ..] if N == 1 => {
472 s = r;
473 if *b == self.1[0] {
474 break Some(idx);
475 }
476 idx += 1;
477 }
478 [_] if N >= 2 => break None,
479 [b1, r @ ..] if N >= 2 => {
480 s = r;
481 if *b1 == self.1[0] {
482 let [b2, r @ ..] = r else { panic!() };
483 if *b2 == self.1[1] {
484 s = r;
485 break Some(idx);
486 }
487 }
488 idx += 1;
489 }
490 _ => panic!(),
491 }
492 };
493 match reached_sep {
494 Some(reached_sep) => {
495 let (part, _) = full.split_at(reached_sep);
496 let part = unsafe { std::str::from_utf8_unchecked(part) };
497 let rest = unsafe { std::str::from_utf8_unchecked(s) };
498 (skipped, part, Some(ConstSplit(rest, self.1)))
499 }
500 None => (skipped, self.0, None),
501 }
502 }
503 #[allow(path_statements, clippy::no_effect)]
504 const fn prev<const SKIP_DOUBLE: bool>(self) -> (bool, &'a str, Option<Self>) {
505 Check::<SKIP_DOUBLE, N>::CHECK_N_SIZE;
506
507 let full = self.0.as_bytes();
508 let mut s = full;
509 let mut skipped = false;
510 let mut idx = s.len();
511 let reached_sep = loop {
512 match s {
513 [] => break None,
514 [r @ .., b, n] if N == 1 && SKIP_DOUBLE && *b == self.1[0] && *n == self.1[0] => {
515 skipped = true;
516 idx -= 2;
517 s = r;
518 }
519 [r @ .., b] if N == 1 => {
520 s = r;
521 if *b == self.1[0] {
522 break Some(idx);
523 }
524 idx -= 1;
525 }
526 [_] if N >= 2 => break None,
527 [r @ .., b2] if N >= 2 => {
528 s = r;
529 if *b2 == self.1[1] {
530 let [r @ .., b1] = r else { panic!() };
531 if *b1 == self.1[1] {
532 s = r;
533 break Some(idx);
534 }
535 }
536 idx -= 1;
537 }
538 _ => panic!(),
539 }
540 };
541 match reached_sep {
542 Some(reached_sep) => {
543 let (_, part) = full.split_at(reached_sep);
544 let part = unsafe { std::str::from_utf8_unchecked(part) };
545 let rest = unsafe { std::str::from_utf8_unchecked(s) };
546 (skipped, part, Some(ConstSplit(rest, self.1)))
547 }
548 None => (skipped, self.0, None),
549 }
550 }
551 pub(super) const fn remainder(self) -> &'a str {
552 self.0
553 }
554}
555impl ConstSplit<'_, 1> {
556 pub(super) const fn control(self) -> char {
557 self.1[0] as char
558 }
559}
560
561struct ConstOperations;
562impl ConstOperations {
563 #[allow(clippy::unnecessary_operation)]
564 const fn char_as_ascii(c: char) -> u8 {
565 ["Character must be an ASCII byte"][!c.is_ascii() as usize];
566 c as u8
567 }
568
569 const fn strip_prefix(s: &str, prefix: char) -> Option<&str> {
570 let prefix = Self::char_as_ascii(prefix);
571 match s.as_bytes() {
572 [b, s @ ..] if *b == prefix => Some(unsafe { std::str::from_utf8_unchecked(s) }),
573 _ => None,
574 }
575 }
576 const fn strip_suffix(s: &str, suffix: char) -> Option<&str> {
577 let suffix = Self::char_as_ascii(suffix);
578 match s.as_bytes() {
579 [s @ .., b] if *b == suffix => Some(unsafe { std::str::from_utf8_unchecked(s) }),
580 _ => None,
581 }
582 }
583
584 const fn split(s: &str, sep: char) -> ConstSplit<'_, 1> {
585 let sep = Self::char_as_ascii(sep);
586 ConstSplit(s, [sep])
587 }
588 const fn split_2(s: &str, sep1: char, sep2: char) -> ConstSplit<'_, 2> {
589 let sep1 = Self::char_as_ascii(sep1);
590 let sep2 = Self::char_as_ascii(sep2);
591 ConstSplit(s, [sep1, sep2])
592 }
593
594 const fn split_more<const N: usize>(
595 s: Option<ConstSplit<'_, N>>,
596 ) -> (Option<&str>, Option<ConstSplit<'_, N>>) {
597 map_opt!(s => {
598 let (_, part, split) = s.next::<false>();
599 (Some(part), split)
600 }, (None, None))
601 }
602 const fn split_first(s: &'_ str, sep: char) -> Option<(&'_ str, &'_ str)> {
603 let split = Self::split(s, sep);
604 let (_, first, split) = split.next::<false>();
605 map_opt!(split => (first, split.remainder()))
606 }
607 const fn split_last(s: &'_ str, sep: char) -> Option<(&'_ str, &'_ str)> {
608 let split = Self::split(s, sep);
609 let (_, last, split) = split.prev::<false>();
610 map_opt!(split => (last, split.remainder()))
611 }
612 const fn split_2_first(s: &'_ str, sep1: char, sep2: char) -> Option<(&'_ str, &'_ str)> {
613 let split = Self::split_2(s, sep1, sep2);
614 let (_, first, split) = split.next::<false>();
615 map_opt!(split => (first, split.remainder()))
616 }
617
618 const fn parse_i32(full: &str) -> ResultFormatterConst<'_, i32> {
619 let neg = Self::strip_prefix(full, '-');
620 let is_neg = neg.is_some();
621 let s = map_opt!(neg => neg, full);
622 if s.is_empty() {
623 return Err(ParseErrorConst::invalid_number(full));
624 }
625 let leading_zero = Self::strip_prefix(s, '0');
626 if let Some(leading_zero) = leading_zero {
627 return if is_neg || !leading_zero.is_empty() {
628 Err(ParseErrorConst::invalid_number(s))
629 } else {
630 Ok(0)
631 };
632 }
633 let mut s = s.as_bytes();
634
635 let mut num = 0;
636 while !s.is_empty() {
637 match s {
638 [b @ b'0'..=b'9', r @ ..] => {
639 num *= 10;
640 let delta = (*b - b'0') as i32;
641 if is_neg {
642 num -= delta;
643 } else {
644 num += delta;
645 }
646 s = r;
647 }
648 _ => {
649 let s = unsafe { std::str::from_utf8_unchecked(s) };
650 return Err(ParseErrorConst::invalid_number(s));
651 }
652 }
653 }
654 Ok(num)
655 }
656 const fn parse_u32(full: &str) -> ResultFormatterConst<'_, u32> {
657 let data = map_res!(Self::parse_i32(full));
658 Ok(data as u32)
659 }
660}