use std::rc::Rc;
use smallvec::SmallVec;
use smol_str::SmolStr;
use crate::types::{GValue, STEP_LABEL_INLINE};
#[derive(Debug, Clone)]
pub struct Traverser {
pub value: GValue,
pub parent: Option<Rc<Traverser>>,
#[allow(dead_code)]
pub labels: Option<SmallVec<[SmolStr; STEP_LABEL_INLINE]>>,
}
impl Traverser {
#[inline]
pub fn new(value: GValue) -> Self {
Self { value, labels: None, parent: None }
}
#[inline]
pub fn new_rc(value: GValue) -> Rc<Self> {
Rc::new(Self::new(value))
}
#[inline]
pub fn new_rc_conditional(value: GValue, parent: &Rc<Traverser>, track_path: bool) -> Rc<Self> {
if track_path {
Rc::new(Self { value, labels: None, parent: Some(Rc::clone(parent)) })
} else {
Rc::new(Self { value, labels: None, parent: None })
}
}
pub fn collect_path(&self) -> Vec<(GValue, Option<SmallVec<[SmolStr; STEP_LABEL_INLINE]>>)> {
let mut entries: Vec<(GValue, Option<SmallVec<[SmolStr; STEP_LABEL_INLINE]>>)> =
vec![(self.value.clone(), self.labels.clone())];
let mut cur = self.parent.as_deref();
while let Some(ancestor) = cur {
entries.push((ancestor.value.clone(), ancestor.labels.clone()));
cur = ancestor.parent.as_deref();
}
entries.reverse();
entries
}
}