1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
pub fn parse_span<S: std::fmt::Debug + Copy>(
    span: S,
) -> std::result::Result<(usize, usize), String> {
    let mut parser = SpanDebugParser {
        during: None,
        curr: '\0',
    };
    match parser.parse(span) {
        Some(found) => Ok(found),
        None => Err(format!(
            "failed to parse bytes of span ({:?}) error during: {:?}, last char: {:?}",
            span, parser.during, parser.curr,
        )),
    }
}

struct SpanDebugParser {
    // idx: usize,
    curr: char,
    during: Option<&'static str>,
}

impl SpanDebugParser {
    // TODO: Make this less gross
    // Expects something like `"#0 bytes(2000..2030)"`
    fn parse<S: std::fmt::Debug>(&mut self, span: S) -> Option<(usize, usize)> {
        self.during = Some("start");
        let dbg_span = format!("{span:?}");
        let mut chs = dbg_span.chars().peekable();
        self.during = Some("skipping opener");
        loop {
            self.curr = chs.next()?;
            if self.curr == '(' {
                break;
            }
        }
        self.during = Some("parsing first byte");
        let mut start_byte = String::new();
        let start_at = loop {
            self.curr = chs.next()?;
            if self.curr == '.' {
                self.during = Some("found .");
                break start_byte.parse::<usize>().ok()?;
            }
            if let '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' = self.curr {
                start_byte.push(self.curr);
            } else {
                self.during = Some("start_byte non-digit");
                return None;
            }
        };

        if chs.next()? != '.' {
            self.during = Some("expected second .");
            return None;
        }
        self.during = Some("parsing second byte index");
        let mut end_byte = String::new();
        let end_at = loop {
            self.curr = chs.next()?;
            if self.curr == ')' {
                self.during = Some("parsing end bytes");
                break end_byte.parse::<usize>().ok()?;
            }
            if let '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' = self.curr {
                end_byte.push(self.curr);
            } else {
                self.during = Some("end_byte non-digit");
                return None;
            }
        };

        Some((start_at, end_at))
    }
}