Skip to main content

substrate_data/forms/text/
doc.rs

1//! [`Doc`]: a parsed document and where each of its parts is.
2
3use super::{LineCol, Spans};
4use crate::model::value::{Path, Seg, Value};
5
6/// A parsed document: the value and where each of its parts is.
7#[derive(Debug, Clone, PartialEq)]
8pub struct Doc {
9    /// The value parsed.
10    pub value: Value,
11    /// Where each of its parts is.
12    pub spans: Spans,
13}
14
15impl Doc {
16    /// The spans of the value at `path` — the closest existing parent's if
17    /// the path goes further than the document.
18    pub fn spans_at(&self, path: &Path) -> &Spans {
19        let mut v = &self.value;
20        let mut s = &self.spans;
21        for seg in path.segments() {
22            let i = match (seg, v) {
23                (Seg::Key(k), Value::Map(m)) => m.index_of(k),
24                (Seg::Index(i), Value::List(l)) if *i < l.len() => Some(*i),
25                _ => None,
26            };
27            let Some(i) = i else { break };
28            let Some(child) = s.children.get(i) else {
29                break;
30            };
31            v = match v {
32                Value::Map(m) => m.value_at(i).unwrap_or(v),
33                Value::List(l) => &l[i],
34                _ => v,
35            };
36            s = child;
37        }
38        s
39    }
40
41    /// The line and column of the value at `path` in `text` (the source this was parsed from).
42    pub fn locate(&self, text: &str, path: &Path) -> LineCol {
43        LineCol::of(text, self.spans_at(path).span.start as usize)
44    }
45}