Skip to main content

inspect_core/
path.rs

1//! Path navigation for inspected values.
2
3#[cfg(not(feature = "std"))]
4use alloc::{string::String, vec::Vec};
5
6/// A segment in an inspection path.
7#[derive(Debug, Clone, PartialEq, Eq, Hash)]
8pub enum PathSegment {
9    /// A named field access (e.g., `.name`).
10    Field(String),
11
12    /// An indexed access (e.g., `[0]`).
13    Index(usize),
14}
15
16/// A path through an inspected value tree.
17///
18/// Paths represent navigation from a root value to a specific nested value,
19/// using field names and indices.
20///
21/// # Examples
22///
23/// ```
24/// use inspect_core::{InspectPath, PathSegment};
25///
26/// let path = InspectPath::new()
27///     .field("users")
28///     .index(2)
29///     .field("name");
30///
31/// assert_eq!(path.to_string(), "users[2].name");
32/// ```
33#[derive(Debug, Clone, Default, PartialEq, Eq)]
34pub struct InspectPath {
35    segments: Vec<PathSegment>,
36}
37
38impl InspectPath {
39    /// Create a new empty path.
40    pub fn new() -> Self {
41        Self { segments: Vec::new() }
42    }
43
44    /// Append a field access to this path.
45    pub fn field(mut self, name: impl Into<String>) -> Self {
46        self.segments.push(PathSegment::Field(name.into()));
47        self
48    }
49
50    /// Append an index access to this path.
51    pub fn index(mut self, idx: usize) -> Self {
52        self.segments.push(PathSegment::Index(idx));
53        self
54    }
55
56    /// Get the segments in this path.
57    pub fn segments(&self) -> &[PathSegment] {
58        &self.segments
59    }
60
61    /// Check if this path is empty (refers to root).
62    pub fn is_empty(&self) -> bool {
63        self.segments.is_empty()
64    }
65
66    /// Get the length of this path.
67    pub fn len(&self) -> usize {
68        self.segments.len()
69    }
70}
71
72impl core::fmt::Display for InspectPath {
73    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
74        for (i, segment) in self.segments.iter().enumerate() {
75            match segment {
76                PathSegment::Field(name) => {
77                    if i > 0 {
78                        write!(f, ".")?;
79                    }
80                    write!(f, "{}", name)?;
81                }
82                PathSegment::Index(idx) => {
83                    write!(f, "[{}]", idx)?;
84                }
85            }
86        }
87        Ok(())
88    }
89}