1use core::range::Range;
2
3use visitor::AstVisitor;
4
5use crate::{Result, tokens::TokenStream, traverse::parse_tokens};
6
7#[derive(Debug, Clone, Default, PartialEq, Eq)]
8pub struct ObjectEntries(pub(crate) Vec<(Range<usize>, Value)>);
9
10impl ObjectEntries {
11 pub(crate) fn new() -> Self {
12 Self(Vec::new())
13 }
14
15 pub(crate) fn push(&mut self, key_range: Range<usize>, v: Value) {
16 self.0.push((key_range, v));
17 }
18
19 pub(crate) fn is_empty(&self) -> bool {
20 self.0.is_empty()
21 }
22
23 pub(crate) fn find<'a>(&'a self, source: &str, key: &str) -> Option<&'a Value> {
24 self.0
25 .iter()
26 .find(|(kr, _)| &source[*kr] == key)
27 .map(|(_, v)| v)
28 }
29}
30
31#[derive(Debug, PartialEq, Eq, Clone)]
32pub enum Value {
33 Null(Range<usize>),
34 String(Range<usize>),
36 Number {
37 mantissa: Range<usize>,
38 exponent: Option<Range<usize>>,
39 },
40 Object(Range<usize>, ObjectEntries),
41 Array(Range<usize>, Vec<Value>),
42 Boolean(Range<usize>, bool),
43}
44
45impl Value {
46 pub fn range(&self) -> Range<usize> {
47 match self {
48 Value::Null(r)
49 | Value::String(r)
50 | Value::Boolean(r, _)
51 | Value::Object(r, _)
52 | Value::Array(r, _) => *r,
53 Value::Number { mantissa, exponent } => {
54 mantissa.start..exponent.map_or(mantissa.end, |e| e.end)
55 }
56 }
57 }
58
59 pub(crate) fn to_f64(&self, source: &str) -> Option<f64> {
60 let Value::Number { mantissa, exponent } = self else {
61 return None;
62 };
63 let m = &source[*mantissa];
64 if let Some(exponent) = exponent {
65 let e = &source[*exponent];
66 format!("{m}e{e}").parse().ok()
67 } else {
68 m.parse().ok()
69 }
70 }
71}
72
73#[derive(Debug, Clone, PartialEq, Eq)]
74pub struct Document<S> {
75 pub(crate) source: S,
76 pub(crate) root: Value,
77}
78
79impl<S: AsRef<str>> Document<S> {
80 pub fn parse(source: S) -> Result<Self> {
81 let root = {
82 let text = source.as_ref();
83 parse_at(text, 0..text.len())?.root
84 };
85 Ok(Self { source, root })
86 }
87
88 pub fn root(&self) -> &Value {
89 &self.root
90 }
91
92 pub fn slice(&self, range: Range<usize>) -> &str {
93 &self.source.as_ref()[range]
94 }
95
96 pub fn get_object_value<'a>(&self, entries: &'a ObjectEntries, key: &str) -> Option<&'a Value> {
97 entries.find(self.source.as_ref(), key)
98 }
99
100 pub fn as_str<'a>(&'a self, value: &Value) -> Option<&'a str> {
101 match value {
102 Value::String(r) => Some(self.slice(*r)),
103 _ => None,
104 }
105 }
106
107 pub fn parse_f64(&self, value: &Value) -> Option<f64> {
108 value.to_f64(self.source.as_ref())
109 }
110}
111
112pub(crate) fn parse_at(full_source: &str, range: Range<usize>) -> Result<Document<&str>> {
113 let mut ast = AstVisitor::new();
114 parse_tokens(
115 &mut TokenStream::new_at_range(full_source, range),
116 full_source,
117 true,
118 &mut ast,
119 )?;
120 let root = ast
121 .finish()
122 .expect("visitor should error if empty or unfinished");
123 Ok(Document {
124 source: full_source,
125 root,
126 })
127}
128
129mod visitor {
130 use core::range::Range;
131
132 use crate::{
133 ast::{ObjectEntries, Value},
134 traverse::Visitor,
135 };
136
137 #[derive(Debug, Default)]
138 pub struct AstVisitor {
139 stack: Vec<AstFrame>,
140 result: Option<Value>,
141 }
142
143 #[derive(Debug)]
144 enum AstFrame {
145 Object {
146 open_range: Range<usize>,
147 entries: ObjectEntries,
148 current_key: Option<Range<usize>>,
149 },
150 Array {
151 open_range: Range<usize>,
152 items: Vec<Value>,
153 },
154 }
155
156 impl AstVisitor {
157 pub fn new() -> Self {
158 Self {
159 stack: Vec::new(),
160 result: None,
161 }
162 }
163
164 fn last_emitted_mut(&mut self) -> &mut Value {
165 match self.stack.last_mut() {
166 None => self.result.as_mut().expect("must have emitted a value"),
167 Some(AstFrame::Array { items, .. }) => items.last_mut().expect("must have item"),
168 Some(AstFrame::Object { entries, .. }) => {
169 &mut entries.0.last_mut().expect("must have entry").1
170 }
171 }
172 }
173
174 fn emit_value(&mut self, value: Value) {
175 match self.stack.last_mut() {
176 None => {
177 self.result = Some(value);
178 }
179 Some(frame) => match frame {
180 AstFrame::Array { items, .. } => items.push(value),
181 AstFrame::Object {
182 entries,
183 current_key,
184 ..
185 } => {
186 let k = current_key
187 .take()
188 .expect("the traverser should not emit a value before the key");
189 entries.push(k, value);
190 }
191 },
192 }
193 }
194
195 pub fn finish(self) -> Option<Value> {
196 self.result
197 }
198 }
199
200 impl<'a> Visitor<'a> for AstVisitor {
201 fn on_object_open(&mut self, range: Range<usize>) {
202 self.stack.push(AstFrame::Object {
203 open_range: range,
204 entries: ObjectEntries::new(),
205 current_key: None,
206 });
207 }
208
209 fn on_object_key(&mut self, range: Range<usize>, _key: &'a str) {
210 if let Some(AstFrame::Object { current_key, .. }) = self.stack.last_mut() {
211 *current_key = Some(range);
212 } else {
213 unreachable!("must be in object for object key")
214 }
215 }
216
217 fn on_object_close(&mut self, close_range: Range<usize>) {
218 let frame = self
219 .stack
220 .pop()
221 .expect("traverser will not emit unbalanced brackets");
222 if let AstFrame::Object {
223 open_range,
224 entries,
225 ..
226 } = frame
227 {
228 self.emit_value(Value::Object(open_range.start..close_range.end, entries));
229 } else {
230 unreachable!("must be an object to close object")
231 }
232 }
233
234 fn on_array_open(&mut self, range: Range<usize>) {
235 self.stack.push(AstFrame::Array {
236 open_range: range,
237 items: Vec::new(),
238 });
239 }
240
241 fn on_array_close(&mut self, close_range: Range<usize>) {
242 let frame = self
243 .stack
244 .pop()
245 .expect("traverser will not emit unbalanced brackets");
246 if let AstFrame::Array { open_range, items } = frame {
247 self.emit_value(Value::Array(open_range.start..close_range.end, items));
248 } else {
249 unreachable!("must be an array to close array")
250 }
251 }
252
253 fn on_null(&mut self, range: Range<usize>) {
254 self.emit_value(Value::Null(range));
255 }
256
257 fn on_string(&mut self, range: Range<usize>, _s: &'a str) {
258 self.emit_value(Value::String(range));
259 }
260
261 fn on_mantissa(&mut self, range: Range<usize>, _mantissa: &'a str) {
262 self.emit_value(Value::Number {
263 mantissa: range,
264 exponent: None,
265 });
266 }
267
268 fn on_exponent(&mut self, range: Range<usize>, _exponent: &'a str) {
269 let Value::Number { exponent, .. } = self.last_emitted_mut() else {
270 unreachable!("exponent must follow mantissa")
271 };
272 *exponent = Some(range);
273 }
274
275 fn on_boolean(&mut self, range: Range<usize>, b: bool) {
276 self.emit_value(Value::Boolean(range, b));
277 }
278
279 fn on_object_key_val_delim(&mut self) {}
280 fn on_item_delim(&mut self) {}
281 }
282}
283
284#[cfg(test)]
285mod tests {
286 use super::*;
287
288 fn range_of(source: &str, needle: &str) -> Range<usize> {
289 let start = source.find(needle).expect("needle in source");
290 start..start + needle.len()
291 }
292
293 fn make_obj(entries: Vec<(&str, Value)>, source: &str) -> Value {
294 let entries = entries
295 .into_iter()
296 .map(|(k, v)| (range_of(source, k), v))
297 .collect::<Vec<_>>();
298 Value::Object(0..source.len(), ObjectEntries(entries))
299 }
300
301 #[test]
302 fn empty_object() {
303 let doc = Document::parse("{}").unwrap();
304 assert_eq!(doc.root(), &Value::Object(0..2, ObjectEntries::new()));
305 }
306
307 #[test]
308 fn one_key_value_pair() {
309 let json = r#"{"hi":"bye"}"#;
310 let doc = Document::parse(json).unwrap();
311 assert_eq!(
312 doc.root(),
313 &make_obj(vec![("hi", Value::String(range_of(json, "bye")))], json)
314 );
315 }
316
317 #[rstest_reuse::template]
318 #[rstest::rstest]
319 #[case("null", |s: &str| Value::Null(range_of(s, "null")))]
320 #[case("true", |s: &str| Value::Boolean(range_of(s, "true"), true))]
321 #[case("false", |s: &str| Value::Boolean(range_of(s, "false"), false))]
322 #[case("\"burger\"", |s: &str| Value::String(range_of(s, "burger")))]
323 fn primitive_template(#[case] primitive: &str, #[case] expected: fn(&str) -> Value) {}
324
325 #[rstest_reuse::apply(primitive_template)]
326 fn primitive_object_value(#[case] primitive: &str, #[case] expected: fn(&str) -> Value) {
327 let json = format!(
328 r#"{{
329 "rust": {primitive}
330 }}"#
331 );
332 let doc = Document::parse(&json).unwrap();
333 let want = make_obj(vec![("rust", expected(&json))], &json);
334 assert_eq!(doc.root(), &want);
335 }
336
337 #[rstest_reuse::apply(primitive_template)]
338 fn primitives(#[case] json: &str, #[case] expected: fn(&str) -> Value) {
339 let doc = Document::parse(json).unwrap();
340 assert_eq!(doc.root(), &expected(json));
341 }
342}