1use core::fmt;
2use std::{borrow::Borrow, ops::Deref};
3
4use locspan::Span;
5
6#[derive(Debug, Default, Clone)]
8pub struct CodeMap(Vec<Entry>);
9
10impl CodeMap {
11 pub fn as_slice(&self) -> &[Entry] {
12 &self.0
13 }
14
15 pub(crate) fn reserve(&mut self, position: usize) -> usize {
16 let i = self.0.len();
17 self.0.push(Entry {
18 span: Span::new(position, position),
19 volume: 0,
20 });
21 i
22 }
23
24 pub(crate) fn get_mut(&mut self, i: usize) -> Option<&mut Entry> {
25 self.0.get_mut(i)
26 }
27
28 pub fn iter(&self) -> Iter {
29 self.0.iter().enumerate()
30 }
31}
32
33impl Deref for CodeMap {
34 type Target = [Entry];
35
36 fn deref(&self) -> &Self::Target {
37 self.as_slice()
38 }
39}
40
41impl AsRef<[Entry]> for CodeMap {
42 fn as_ref(&self) -> &[Entry] {
43 self.as_slice()
44 }
45}
46
47impl Borrow<[Entry]> for CodeMap {
48 fn borrow(&self) -> &[Entry] {
49 self.as_slice()
50 }
51}
52
53pub type Iter<'a> = std::iter::Enumerate<std::slice::Iter<'a, Entry>>;
54
55pub type IntoIter = std::iter::Enumerate<std::vec::IntoIter<Entry>>;
56
57impl<'a> IntoIterator for &'a CodeMap {
58 type IntoIter = Iter<'a>;
59 type Item = (usize, &'a Entry);
60
61 fn into_iter(self) -> Self::IntoIter {
62 self.iter()
63 }
64}
65
66impl IntoIterator for CodeMap {
67 type IntoIter = IntoIter;
68 type Item = (usize, Entry);
69
70 fn into_iter(self) -> Self::IntoIter {
71 self.0.into_iter().enumerate()
72 }
73}
74
75#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
79pub struct Entry {
80 pub span: Span,
82
83 pub volume: usize,
85}
86
87impl Entry {
88 pub fn new(span: Span, volume: usize) -> Self {
89 Self { span, volume }
90 }
91}
92
93#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
94pub struct Mapped<T> {
95 pub offset: usize,
96 pub value: T,
97}
98
99impl<T> Mapped<T> {
100 pub fn new(offset: usize, value: T) -> Self {
101 Self { offset, value }
102 }
103}
104
105impl<T: fmt::Display> fmt::Display for Mapped<T> {
106 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
107 self.value.fmt(f)
108 }
109}
110
111impl<T: 'static + std::error::Error> std::error::Error for Mapped<T> {
112 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
113 Some(&self.value)
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use super::Entry;
120 use crate::{Parse, Value};
121 use locspan::Span;
122
123 #[test]
124 fn code_map_t1() {
125 let (value, code_map) = Value::parse_str(r#"{ "a": 0, "b": [1, 2] }"#).unwrap();
126 let expected = [
127 Entry::new(Span::new(0, 23), 9), Entry::new(Span::new(2, 8), 3), Entry::new(Span::new(2, 5), 1), Entry::new(Span::new(7, 8), 1), Entry::new(Span::new(10, 21), 5), Entry::new(Span::new(10, 13), 1), Entry::new(Span::new(15, 21), 3), Entry::new(Span::new(16, 17), 1), Entry::new(Span::new(19, 20), 1), ];
137
138 assert_eq!(code_map.len(), expected.len());
139 assert_eq!(value.traverse().count(), expected.len());
140 for (i, entry) in code_map {
141 assert_eq!(entry, expected[i])
142 }
143 }
144
145 #[test]
146 fn code_map_t2() {
147 let (value, code_map) =
148 Value::parse_str(r#"{ "a": 0, "b": { "c": 1, "d": [2, 3] }, "e": [4, [5, 6]] }"#)
149 .unwrap();
150 let expected = [
151 Entry::new(Span::new(0, 58), 22), Entry::new(Span::new(2, 8), 3), Entry::new(Span::new(2, 5), 1), Entry::new(Span::new(7, 8), 1), Entry::new(Span::new(10, 38), 11), Entry::new(Span::new(10, 13), 1), Entry::new(Span::new(15, 38), 9), Entry::new(Span::new(17, 23), 3), Entry::new(Span::new(17, 20), 1), Entry::new(Span::new(22, 23), 1), Entry::new(Span::new(25, 36), 5), Entry::new(Span::new(25, 28), 1), Entry::new(Span::new(30, 36), 3), Entry::new(Span::new(31, 32), 1), Entry::new(Span::new(34, 35), 1), Entry::new(Span::new(40, 56), 7), Entry::new(Span::new(40, 43), 1), Entry::new(Span::new(45, 56), 5), Entry::new(Span::new(46, 47), 1), Entry::new(Span::new(49, 55), 3), Entry::new(Span::new(50, 51), 1), Entry::new(Span::new(53, 54), 1), ];
174
175 assert_eq!(code_map.len(), expected.len());
176 assert_eq!(value.traverse().count(), expected.len());
177 for (i, entry) in code_map {
178 assert_eq!(entry, expected[i])
179 }
180 }
181}