1use crate::ExpectJsonError;
2use crate::JsonType;
3use crate::expect_core::Context;
4use crate::expect_core::ExpectOp;
5use crate::internals::ExpectOpMeta;
6use crate::internals::objects::ArrayObject;
7use crate::internals::objects::FloatObject;
8use crate::internals::objects::IntegerObject;
9use crate::internals::objects::ValueObject;
10use crate::internals::objects::ValueTypeObject;
11use std::error::Error as StdError;
12use thiserror::Error;
13
14pub type ExpectOpResult<V> = Result<V, ExpectOpError>;
15
16#[derive(Debug, Error)]
17pub enum ExpectOpError {
18 #[error(
21 "Json expect::{}() at {context}, received wrong type:
22 expected {}
23 received {received}",
24 expected_operation.name,
25 format_expected_operation_types(expected_operation),
26 )]
27 UnsupportedOperation {
28 context: Context<'static>,
29 received: ValueTypeObject,
30 expected_operation: ExpectOpMeta,
31 },
32
33 #[error(
34 "Json object at {context} is missing key for {}:
35 expected field '{expected_key}',
36 but it was not found",
37 expected_operation.name
38 )]
39 ObjectKeyMissingForExpectOp {
40 context: Context<'static>,
41 expected_key: String,
42 expected_operation: ExpectOpMeta,
43 },
44
45 #[error(
46 "Json at {context} has key with value, expecting either key not present or different value.
47 received {received}"
48 )]
49 ObjectKeyValueIsEqual {
50 context: Context<'static>,
51 received: ValueObject,
52 expected_operation: ExpectOpMeta,
53 },
54
55 #[error(
56 "Json {json_type} at {context} contains value was expecting to not be there:
57 expected {json_type} to not contain {expected}, but it was found.
58 received {received}"
59 )]
60 ContainsFound {
61 context: Context<'static>,
62 json_type: JsonType,
63 expected: ValueObject,
64 received: ValueObject,
65 },
66
67 #[error(
68 "Json {json_type} at {context} does not contain expected value:
69 expected {json_type} to contain {expected}, but it was not found.
70 received {received}"
71 )]
72 ContainsNotFound {
73 context: Context<'static>,
74 json_type: JsonType,
75 expected: ValueObject,
76 received: ValueObject,
77 },
78
79 #[error(
80 "Json {json_type} error at {context}, regex did not match:
81 expected {json_type} to match regex pattern '{pattern}',
82 received {received}"
83 )]
84 RegexNoMatch {
85 context: Context<'static>,
86 json_type: JsonType,
87 pattern: String,
88 received: ValueObject,
89 },
90
91 #[error(
92 "Json expect::array() error at {context},
93 expected array to contain all unique values.
94 found duplicate {duplicate}
95 received full array {received_array}"
96 )]
97 ArrayContainsDuplicate {
98 context: Context<'static>,
99 duplicate: ValueObject,
100 received_array: ArrayObject,
101 },
102
103 #[error(
104 "{error}
105 received full array {received_full_array}"
106 )]
107 ArrayAllEqual {
108 #[source]
109 error: Box<ExpectJsonError>,
110 received_full_array: ArrayObject,
111 },
112
113 #[error(
114 "Json expect::array() error at {context}, mismatch:
115 expected array (up to order): {expected_array},
116 received array: {received_array}"
117 )]
118 ArrayUnorderedMismatch {
119 context: Context<'static>,
120 expected_array: ArrayObject,
121 received_array: ArrayObject,
122 },
123
124 #[error(
125 "Json expect::integer() error at {context}, is zero:
126 expected non-zero integer
127 received {received}"
128 )]
129 IntegerIsZero {
130 context: Context<'static>,
131 received: IntegerObject,
132 },
133
134 #[error(
135 "Json expect::integer() error at {context}, is not zero:
136 expected 0
137 received {received}"
138 )]
139 IntegerIsNotZero {
140 context: Context<'static>,
141 received: IntegerObject,
142 },
143
144 #[error(
145 "Json expect::float() error at {context}, is zero:
146 expected non-zero float
147 received {received}"
148 )]
149 FloatIsZero {
150 context: Context<'static>,
151 received: FloatObject,
152 },
153
154 #[error(
155 "Json expect::float() error at {context}, is not zero:
156 expected 0.0
157 received {received}"
158 )]
159 FloatIsNotZero {
160 context: Context<'static>,
161 received: FloatObject,
162 },
163
164 #[error(
165 "Json expect::{}() error at {context}:
166 {message},
167 {error}",
168 expected_operation.name,
169 )]
170 UnknownError {
171 #[source]
172 error: Box<dyn StdError>,
173 context: Context<'static>,
174 message: String,
175 expected_operation: ExpectOpMeta,
176 },
177
178 #[error(
179 "Json expect::{}() error at {context}:
180 {message}",
181 expected_operation.name,
182 )]
183 UnknownErrorMessage {
184 context: Context<'static>,
185 message: String,
186 expected_operation: ExpectOpMeta,
187 },
188
189 #[error("{error}")]
190 ExpectJsonError {
191 #[source]
192 error: Box<ExpectJsonError>,
193 },
194}
195
196impl ExpectOpError {
197 pub fn custom<O, S>(expect_op: &O, context: &Context<'_>, message: S) -> Self
198 where
199 O: ExpectOp + ?Sized,
200 S: Into<String>,
201 {
202 Self::UnknownErrorMessage {
203 context: context.to_static(),
204 message: message.into(),
205 expected_operation: ExpectOpMeta::new(expect_op),
206 }
207 }
208
209 pub fn custom_error<O, S, E>(expect_op: &O, context: &Context<'_>, message: S, error: E) -> Self
210 where
211 O: ExpectOp + ?Sized,
212 S: Into<String>,
213 E: StdError + 'static,
214 {
215 Self::UnknownError {
216 context: context.to_static(),
217 error: Box::new(error),
218 message: message.into(),
219 expected_operation: ExpectOpMeta::new(expect_op),
220 }
221 }
222
223 pub fn unsupported_operation_type<O, V>(
224 context: &Context<'_>,
225 expect_op: &O,
226 received: V,
227 ) -> Self
228 where
229 O: ExpectOp + ?Sized,
230 V: Into<ValueTypeObject>,
231 {
232 Self::UnsupportedOperation {
233 context: context.to_static(),
234 received: received.into(),
235 expected_operation: ExpectOpMeta::new(expect_op),
236 }
237 }
238}
239
240impl From<ExpectJsonError> for ExpectOpError {
241 fn from(error: ExpectJsonError) -> Self {
242 Self::ExpectJsonError {
243 error: Box::new(error),
244 }
245 }
246}
247
248fn format_expected_operation_types(expected_operation: &ExpectOpMeta) -> String {
249 let types = expected_operation.types;
250 if types.is_empty() {
251 return "no supported types listed (need to implement ExpectOp::supported_types)"
252 .to_string();
253 }
254
255 types.join(", ")
256}