i_codegen_code/
utils.rs

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    // idx: usize,
19    curr: char,
20    during: Option<&'static str>,
21}
22
23impl SpanDebugParser {
24    // TODO: Make this less gross
25    // Expects something like `"#0 bytes(2000..2030)"`
26    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}