1use std::rc::Rc;
2
3pub mod table;
4pub mod resolver;
5pub mod errors;
6
7pub use table::{ChunkSymbols, DebugSymbolTable};
8pub use resolver::{DebugSymbolResolver, ResolvedSymbolTable};
9
10
11pub type TokenIndex = u32;
14pub type TokenLength = u16;
15
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
22pub struct DebugSymbol {
23 start: TokenIndex,
24 length: TokenLength,
25}
26
27impl TryFrom<(TokenIndex, TokenIndex)> for DebugSymbol {
28 type Error = (TokenIndex, TokenIndex);
29 fn try_from(tuple: (TokenIndex, TokenIndex)) -> Result<Self, Self::Error> {
30 let (start, end) = tuple;
31 if let Ok(length) = TokenLength::try_from(end - start) {
32 Ok(DebugSymbol { start, length })
33 } else {
34 Err((start, end))
35 }
36 }
37}
38
39impl DebugSymbol {
40 pub fn new(start: TokenIndex, length: TokenLength) -> Self {
41 Self { start, length }
42 }
43
44 pub fn start(&self) -> TokenIndex { self.start }
45 pub fn end(&self) -> TokenIndex { self.start + TokenIndex::from(self.length) }
46 pub fn len(&self) -> TokenLength { self.length }
47 pub fn is_empty(&self) -> bool { self.length == 0 } }
49
50
51
52#[derive(Debug, Clone)]
55pub struct ResolvedSymbol {
56 lines: Vec<Rc<String>>,
57 lineno: usize, start: usize, end: usize,
60}
61
62impl ResolvedSymbol {
63 pub fn new(lines: Vec<Rc<String>>, lineno: usize, start: usize, end: usize) -> Self {
64 ResolvedSymbol { lines, lineno, start, end }
65 }
66
67 pub fn is_multiline(&self) -> bool { self.lines.len() > 1 }
68 pub fn line_count(&self) -> usize { self.lines.len() }
69
70 pub fn lineno(&self) -> usize { self.lineno }
71 pub fn start(&self) -> usize { self.start }
72 pub fn end(&self) -> usize { self.end }
73
74 pub fn start_col(&self) -> usize { self.start }
75 pub fn end_col(&self) -> usize {
76 let offset = self.lines.iter()
77 .take(self.lines.len() - 1)
78 .map(|line| line.len())
79 .reduce(|acc, n| acc + n)
80 .unwrap_or(0);
81
82 self.end - offset }
84
85 pub fn iter_whole_lines(&self) -> impl Iterator<Item=&str> {
86 self.lines.iter().map(|s| s.as_str())
87 }
88
89 pub fn iter_lines(&self) -> impl Iterator<Item=&str> {
91 self.lines.iter().scan(0, |cur_line_start, line| {
92 let cur_line_end = *cur_line_start + line.len();
93
94 let result;
95 if (*cur_line_start <= self.start) && (self.start < cur_line_end) {
96 let start = self.start - *cur_line_start;
97 result = &line[start..];
98 } else if (*cur_line_start <= self.end) && (self.end < cur_line_end) {
99 let end = self.end - *cur_line_start;
100 result = &line[..end];
101 } else {
102 result = line;
103 };
104
105 *cur_line_start = cur_line_end;
106 Some(result)
107 })
108 }
109
110}