Skip to main content

moxy_token/source/
map.rs

1use std::cell::RefCell;
2
3use super::Source;
4use crate::span::fallback::Span;
5
6thread_local! {
7    static GLOBAL: RefCell<SourceMap> = RefCell::new(SourceMap::new());
8}
9
10#[derive(Debug, Default)]
11pub struct SourceMap(Vec<Source>);
12
13impl SourceMap {
14    pub fn new() -> Self {
15        Self(vec![])
16    }
17
18    pub fn with<R>(f: impl FnOnce(&Self) -> R) -> R {
19        GLOBAL.with(|sm| f(&sm.borrow()))
20    }
21
22    pub fn with_mut<R>(f: impl FnOnce(&mut Self) -> R) -> R {
23        GLOBAL.with(|sm| f(&mut sm.borrow_mut()))
24    }
25
26    pub fn as_slice(&self) -> &[Source] {
27        &self.0
28    }
29
30    pub fn len(&self) -> usize {
31        self.0.len()
32    }
33
34    pub fn is_empty(&self) -> bool {
35        self.0.is_empty()
36    }
37
38    pub fn find(&self, span: Span) -> Option<&Source> {
39        match self.find_index(span) {
40            None => None,
41            Some(i) => Some(&self.0[i]),
42        }
43    }
44
45    pub fn find_mut(&mut self, span: Span) -> Option<&mut Source> {
46        match self.find_index(span) {
47            None => None,
48            Some(i) => Some(&mut self.0[i]),
49        }
50    }
51
52    pub fn find_path(&self, span: Span) -> Option<String> {
53        if let Some(i) = self.find_index(span) {
54            return if i == 0 {
55                Some("<unspecified>".to_owned())
56            } else {
57                Some(format!("<parsed string {}>", i))
58            };
59        }
60
61        None
62    }
63
64    pub fn find_index(&self, span: Span) -> Option<usize> {
65        let sr = span.byte_range();
66        self.0
67            .binary_search_by(|src| {
68                let fr = src.span().byte_range();
69
70                if fr.end < sr.start {
71                    std::cmp::Ordering::Less
72                } else if fr.start > sr.end {
73                    std::cmp::Ordering::Greater
74                } else {
75                    std::cmp::Ordering::Equal
76                }
77            })
78            .ok()
79    }
80
81    pub fn push(&mut self, src: impl Into<String>) -> Span {
82        let start = self.0.last().map(|src| src.span().byte_range().end).unwrap_or(0);
83        let src = Source::new(start, src);
84        let span = src.span();
85        self.0.push(src);
86        span
87    }
88}