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 pub(crate) fn from_error<E: std::error::Error + Send + Sync + 'static>(err: E, details: &'static str) -> Self {
57 Self {
58 details,
59 source: Some(InternalErrorSource(Box::new(err))),
60 }
61 }
62}
63
64impl Display for InternalRsonpathError {
65 #[inline]
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 let details_are_enabled = std::env::var("RUST_BACKTRACE").unwrap_or_default() == "0";
68 write!(
69 f,
70 "an internal error has occurred; this is a bug, please report it at {BUG_REPORT_URL}"
71 )?;
72
73 if details_are_enabled {
74 writeln!(f, "; the error details follow")?;
75 write!(f, "{}", self.details)?;
76 if let Some(source) = &self.source {
77 write!(f, "; source: {source}")?;
78 }
79 }
80
81 Ok(())
82 }
83}
84
85#[derive(Error, Debug)]
89pub struct UnsupportedFeatureError {
90 issue: Option<usize>,
91 feature: &'static str,
92}
93
94impl UnsupportedFeatureError {
95 #[must_use]
96 #[allow(
97 dead_code,
98 reason = "we might not have any tracked issues but the function should be available"
99 )]
100 #[inline(always)]
101 fn tracked(issue: usize, feature: &'static str) -> Self {
102 Self {
103 issue: Some(issue),
104 feature,
105 }
106 }
107
108 #[must_use]
109 #[inline(always)]
110 fn untracked(feature: &'static str) -> Self {
111 Self { issue: None, feature }
112 }
113
114 #[must_use]
117 #[inline(always)]
118 pub fn large_json_depths() -> Self {
119 Self::untracked("Large JSON Depths")
120 }
121
122 #[must_use]
125 #[inline(always)]
126 pub fn large_automaton_queries() -> Self {
127 Self::untracked("Large Automaton Queries")
128 }
129
130 #[must_use]
133 #[inline(always)]
134 pub fn multiple_selectors() -> Self {
135 Self::untracked("Multiple Selector per Segment")
136 }
137
138 #[must_use]
141 #[inline(always)]
142 pub fn indexing_from_end() -> Self {
143 Self::untracked("Indexing from End")
144 }
145
146 #[must_use]
149 #[inline(always)]
150 pub fn slice_selector() -> Self {
151 Self::tracked(152, "Slice Selector")
152 }
153
154 #[must_use]
157 #[inline(always)]
158 pub fn slice_with_backward_step() -> Self {
159 Self::untracked("Slice with Backward Step")
160 }
161
162 #[must_use]
165 #[inline(always)]
166 pub fn filter_selector() -> Self {
167 Self::tracked(154, "Filter Selector")
168 }
169
170 #[must_use]
173 #[inline(always)]
174 pub fn issue(&self) -> Option<usize> {
175 self.issue
176 }
177
178 #[must_use]
180 #[inline(always)]
181 pub fn feature(&self) -> &str {
182 self.feature
183 }
184
185 #[must_use]
187 #[inline(always)]
188 pub fn is_planned(&self) -> bool {
189 self.issue.is_some()
190 }
191}
192
193impl Display for UnsupportedFeatureError {
194 #[inline]
195 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
196 match self.issue {
197 Some(issue) => {
198 write!(
199 f,
200 "the feature {} (#{}) is not supported yet; it is being tracked and discussed at \
201 https://github.com/V0ldek/rsonpath/issues/{}",
202 self.feature, issue, issue
203 )
204 }
205 None => {
206 write!(
207 f,
208 "the feature {} is not supported, and is not planned; \
209 if you would like to see it introduced to rsonpath, please raise a feature request at \
210 {FEATURE_REQUEST_URL}",
211 self.feature
212 )
213 }
214 }
215 }
216}