Skip to main content

facet_path/
access.rs

1//! Error types for path-based value access.
2
3use facet_core::Shape;
4
5use crate::PathStep;
6
7/// Error returned when navigating a value using a [`Path`](crate::Path).
8///
9/// Each variant captures enough context for a caller to produce
10/// a meaningful diagnostic without re-walking the path.
11#[derive(Debug, Clone)]
12#[non_exhaustive]
13pub enum PathAccessError {
14    /// The root shape of the path doesn't match the value being navigated.
15    RootShapeMismatch {
16        /// The shape recorded in the path.
17        expected: &'static Shape,
18        /// The shape of the value we tried to navigate.
19        actual: &'static Shape,
20    },
21
22    /// The step kind doesn't apply to the current shape.
23    ///
24    /// For example, `PathStep::Field` on a scalar, or `PathStep::Index` on a struct.
25    WrongStepKind {
26        /// The step that didn't apply.
27        step: PathStep,
28        /// Index of this step in the path (0-based).
29        step_index: usize,
30        /// The shape at the point where the step was attempted.
31        shape: &'static Shape,
32    },
33
34    /// A field or list index is out of bounds.
35    IndexOutOfBounds {
36        /// The step that contained the out-of-bounds index.
37        step: PathStep,
38        /// Index of this step in the path (0-based).
39        step_index: usize,
40        /// The shape of the container.
41        shape: &'static Shape,
42        /// The index that was requested.
43        index: usize,
44        /// The number of available items (fields, elements, variants, etc.).
45        bound: usize,
46    },
47
48    /// The path says we should be at variant X, but the live value is variant Y.
49    VariantMismatch {
50        /// Index of this step in the path (0-based).
51        step_index: usize,
52        /// The enum shape.
53        shape: &'static Shape,
54        /// The variant index the path expected.
55        expected_variant: usize,
56        /// The variant index found at runtime.
57        actual_variant: usize,
58    },
59
60    /// A `Deref`, `Inner`, or `Proxy` step has no target.
61    ///
62    /// This can happen when a smart pointer has no `borrow_fn`,
63    /// or the shape has no `inner`, or no proxy definition.
64    MissingTarget {
65        /// The step that required a target.
66        step: PathStep,
67        /// Index of this step in the path (0-based).
68        step_index: usize,
69        /// The shape that was expected to provide a target.
70        shape: &'static Shape,
71    },
72
73    /// An `OptionSome` step was encountered but the value is `None`.
74    OptionIsNone {
75        /// Index of this step in the path (0-based).
76        step_index: usize,
77        /// The option shape.
78        shape: &'static Shape,
79    },
80}
81
82impl core::fmt::Display for PathAccessError {
83    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
84        match self {
85            PathAccessError::RootShapeMismatch { expected, actual } => {
86                write!(
87                    f,
88                    "root shape mismatch: path expects {expected}, value is {actual}"
89                )
90            }
91            PathAccessError::WrongStepKind {
92                step,
93                step_index,
94                shape,
95            } => {
96                write!(
97                    f,
98                    "step {step_index} ({step:?}) does not apply to shape {shape}"
99                )
100            }
101            PathAccessError::IndexOutOfBounds {
102                step,
103                step_index,
104                shape,
105                index,
106                bound,
107            } => {
108                write!(
109                    f,
110                    "step {step_index} ({step:?}): index {index} out of bounds for {shape} (has {bound})"
111                )
112            }
113            PathAccessError::VariantMismatch {
114                step_index,
115                shape,
116                expected_variant,
117                actual_variant,
118            } => {
119                write!(
120                    f,
121                    "step {step_index}: variant mismatch on {shape}: path expects variant {expected_variant}, value has variant {actual_variant}"
122                )
123            }
124            PathAccessError::MissingTarget {
125                step,
126                step_index,
127                shape,
128            } => {
129                write!(
130                    f,
131                    "step {step_index} ({step:?}): no target available for {shape}"
132                )
133            }
134            PathAccessError::OptionIsNone { step_index, shape } => {
135                write!(
136                    f,
137                    "step {step_index}: option {shape} is None, cannot navigate into Some"
138                )
139            }
140        }
141    }
142}
143
144impl core::error::Error for PathAccessError {}