use super::{LineCol, Spans};
use crate::model::value::{Path, Seg, Value};
#[derive(Debug, Clone, PartialEq)]
pub struct Doc {
pub value: Value,
pub spans: Spans,
}
impl Doc {
pub fn spans_at(&self, path: &Path) -> &Spans {
let mut v = &self.value;
let mut s = &self.spans;
for seg in path.segments() {
let i = match (seg, v) {
(Seg::Key(k), Value::Map(m)) => m.index_of(k),
(Seg::Index(i), Value::List(l)) if *i < l.len() => Some(*i),
_ => None,
};
let Some(i) = i else { break };
let Some(child) = s.children.get(i) else {
break;
};
v = match v {
Value::Map(m) => m.value_at(i).unwrap_or(v),
Value::List(l) => &l[i],
_ => v,
};
s = child;
}
s
}
pub fn locate(&self, text: &str, path: &Path) -> LineCol {
LineCol::of(text, self.spans_at(path).span.start as usize)
}
}