1pub fn parse_span<S: std::fmt::Debug + Copy>(
2 span: S,
3) -> std::result::Result<(usize, usize), String> {
4 let mut parser = SpanDebugParser {
5 during: None,
6 curr: '\0',
7 };
8 match parser.parse(span) {
9 Some(found) => Ok(found),
10 None => Err(format!(
11 "failed to parse bytes of span ({:?}) error during: {:?}, last char: {:?}",
12 span, parser.during, parser.curr,
13 )),
14 }
15}
16
17struct SpanDebugParser {
18 curr: char,
20 during: Option<&'static str>,
21}
22
23impl SpanDebugParser {
24 fn parse<S: std::fmt::Debug>(&mut self, span: S) -> Option<(usize, usize)> {
27 self.during = Some("start");
28 let dbg_span = format!("{span:?}");
29 let mut chs = dbg_span.chars().peekable();
30 self.during = Some("skipping opener");
31 loop {
32 self.curr = chs.next()?;
33 if self.curr == '(' {
34 break;
35 }
36 }
37 self.during = Some("parsing first byte");
38 let mut start_byte = String::new();
39 let start_at = loop {
40 self.curr = chs.next()?;
41 if self.curr == '.' {
42 self.during = Some("found .");
43 break start_byte.parse::<usize>().ok()?;
44 }
45 if let '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' = self.curr {
46 start_byte.push(self.curr);
47 } else {
48 self.during = Some("start_byte non-digit");
49 return None;
50 }
51 };
52
53 if chs.next()? != '.' {
54 self.during = Some("expected second .");
55 return None;
56 }
57 self.during = Some("parsing second byte index");
58 let mut end_byte = String::new();
59 let end_at = loop {
60 self.curr = chs.next()?;
61 if self.curr == ')' {
62 self.during = Some("parsing end bytes");
63 break end_byte.parse::<usize>().ok()?;
64 }
65 if let '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' = self.curr {
66 end_byte.push(self.curr);
67 } else {
68 self.during = Some("end_byte non-digit");
69 return None;
70 }
71 };
72
73 Some((start_at, end_at))
74 }
75}