1use std::fmt::{self, Display};
3use thiserror::Error;
4
5pub(crate) const FEATURE_REQUEST_URL: &str =
6 "https://github.com/V0ldek/rsonpath/issues/new?template=feature_request.md";
7pub(crate) const BUG_REPORT_URL: &str = "https://github.com/V0ldek/rsonpath/issues/new?template=bug_report.md";
8
9#[derive(Error, Debug)]
13pub struct InternalRsonpathError {
14 details: &'static str,
15 #[source]
16 source: Option<InternalErrorSource>,
17}
18
19#[derive(Error, Debug)]
21pub enum DepthError {
22 #[error("Maximum depth of {0} exceeded.")]
25 AboveLimit(usize),
26 #[error("Depth fell below zero.")]
29 BelowZero,
30}
31
32struct InternalErrorSource(Box<dyn std::error::Error + Send + Sync>);
33
34impl fmt::Debug for InternalErrorSource {
35 #[inline(always)]
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 fmt::Debug::fmt(&self.0, f)
38 }
39}
40
41impl Display for InternalErrorSource {
42 #[inline(always)]
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 fmt::Display::fmt(&self.0, f)
45 }
46}
47
48impl std::error::Error for InternalErrorSource {
49 #[inline(always)]
50 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
51 self.0.source()
52 }
53}
54
55impl InternalRsonpathError {
56 #[allow(unused)]
57 pub(crate) fn from_expectation(details: &'static str) -> Self {
58 Self { details, source: None }
59 }
60
61 #[allow(unused)]
62 pub(crate) fn from_error<E: std::error::Error + Send + Sync + 'static>(err: E, details: &'static str) -> Self {
63 Self {
64 details,
65 source: Some(InternalErrorSource(Box::new(err))),
66 }
67 }
68}
69
70impl Display for InternalRsonpathError {
71 #[inline]
72 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73 let details_are_enabled = std::env::var("RUST_BACKTRACE").unwrap_or_default() == "0";
74 write!(
75 f,
76 "an internal error has occurred; this is a bug, please report it at {BUG_REPORT_URL}"
77 )?;
78
79 if details_are_enabled {
80 writeln!(f, "; the error details follow")?;
81 write!(f, "{}", self.details)?;
82 if let Some(source) = &self.source {
83 write!(f, "; source: {}", source)?;
84 }
85 }
86
87 Ok(())
88 }
89}
90
91#[derive(Error, Debug)]
95pub struct UnsupportedFeatureError {
96 issue: Option<usize>,
97 feature: &'static str,
98}
99
100impl UnsupportedFeatureError {
101 #[must_use]
102 #[allow(dead_code)]
103 #[inline(always)]
104 fn tracked(issue: usize, feature: &'static str) -> Self {
105 Self {
106 issue: Some(issue),
107 feature,
108 }
109 }
110
111 #[must_use]
112 #[inline(always)]
113 fn untracked(feature: &'static str) -> Self {
114 Self { issue: None, feature }
115 }
116
117 #[must_use]
120 #[inline(always)]
121 pub fn large_json_depths() -> Self {
122 Self::untracked("Large JSON Depths")
123 }
124
125 #[must_use]
128 #[inline(always)]
129 pub fn large_automaton_queries() -> Self {
130 Self::untracked("Large Automaton Queries")
131 }
132
133 #[must_use]
136 #[inline(always)]
137 pub fn multiple_selectors() -> Self {
138 Self::untracked("Multiple Selector per Segment")
139 }
140
141 #[must_use]
144 #[inline(always)]
145 pub fn indexing_from_end() -> Self {
146 Self::untracked("Indexing from End")
147 }
148
149 #[must_use]
152 #[inline(always)]
153 pub fn slice_selector() -> Self {
154 Self::tracked(152, "Slice Selector")
155 }
156
157 #[must_use]
160 #[inline(always)]
161 pub fn slice_with_backward_step() -> Self {
162 Self::untracked("Slice with Backward Step")
163 }
164
165 #[must_use]
168 #[inline(always)]
169 pub fn filter_selector() -> Self {
170 Self::tracked(154, "Filter Selector")
171 }
172
173 #[must_use]
176 #[inline(always)]
177 pub fn issue(&self) -> Option<usize> {
178 self.issue
179 }
180
181 #[must_use]
183 #[inline(always)]
184 pub fn feature(&self) -> &str {
185 self.feature
186 }
187
188 #[must_use]
190 #[inline(always)]
191 pub fn is_planned(&self) -> bool {
192 self.issue.is_some()
193 }
194}
195
196impl Display for UnsupportedFeatureError {
197 #[inline]
198 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
199 match self.issue {
200 Some(issue) => {
201 write!(
202 f,
203 "the feature {} (#{}) is not supported yet; it is being tracked and discussed at \
204 https://github.com/V0ldek/rsonpath/issues/{}",
205 self.feature, issue, issue
206 )
207 }
208 None => {
209 write!(
210 f,
211 "the feature {} is not supported, and is not planned; \
212 if you would like to see it introduced to rsonpath, please raise a feature request at \
213 {FEATURE_REQUEST_URL}",
214 self.feature
215 )
216 }
217 }
218 }
219}