1use std::rc::Rc;
2
3#[derive(Debug, Clone)]
5pub struct ParsedSpan {
6 input: Rc<str>,
7 start: usize,
11 end: usize,
15}
16
17#[derive(Debug, Clone)]
18pub enum Span {
19 Parsed(ParsedSpan),
21 DuplicateRecordFieldsSugar(Box<Span>, Box<Span>),
23 DottedFieldSugar,
24 RecordPunSugar,
25 Decoded,
27 Artificial,
29}
30
31impl ParsedSpan {
32 pub fn to_input(&self) -> String {
33 self.input.to_string()
34 }
35 pub fn as_char_range(&self) -> (usize, usize) {
38 (
39 char_idx_from_byte_idx(&self.input, self.start),
40 char_idx_from_byte_idx(&self.input, self.end),
41 )
42 }
43}
44
45impl Span {
46 pub fn make(input: Rc<str>, sp: pest::Span) -> Self {
47 Span::Parsed(ParsedSpan {
48 input,
49 start: sp.start(),
50 end: sp.end(),
51 })
52 }
53
54 pub fn union(&self, other: &Span) -> Self {
58 use std::cmp::{max, min};
59 use Span::*;
60 match (self, other) {
61 (Parsed(x), Parsed(y)) if Rc::ptr_eq(&x.input, &y.input) => {
62 Parsed(ParsedSpan {
63 input: x.input.clone(),
64 start: min(x.start, y.start),
65 end: max(x.end, y.end),
66 })
67 }
68 (Parsed(_), Parsed(_)) => panic!(
69 "Tried to union incompatible spans: {:?} and {:?}",
70 self, other
71 ),
72 (Parsed(x), _) => Parsed(x.clone()),
73 (_, Parsed(x)) => Parsed(x.clone()),
74 _ => panic!(
75 "Tried to union incompatible spans: {:?} and {:?}",
76 self, other
77 ),
78 }
79 }
80}
81
82fn char_idx_from_byte_idx(input: &str, idx: usize) -> usize {
85 use std::iter::once;
86 input
87 .char_indices()
88 .map(|(byte_i, _)| byte_i) .chain(once(input.len())) .enumerate()
91 .find(|(_, byte_i)| *byte_i == idx)
92 .map(|(char_i, _)| char_i)
93 .unwrap()
94}