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::integer() error at {context}, is zero:
115 expected non-zero integer
116 received {received}"
117 )]
118 IntegerIsZero {
119 context: Context<'static>,
120 received: IntegerObject,
121 },
122
123 #[error(
124 "Json expect::integer() error at {context}, is not zero:
125 expected 0
126 received {received}"
127 )]
128 IntegerIsNotZero {
129 context: Context<'static>,
130 received: IntegerObject,
131 },
132
133 #[error(
134 "Json expect::float() error at {context}, is zero:
135 expected non-zero float
136 received {received}"
137 )]
138 FloatIsZero {
139 context: Context<'static>,
140 received: FloatObject,
141 },
142
143 #[error(
144 "Json expect::float() error at {context}, is not zero:
145 expected 0.0
146 received {received}"
147 )]
148 FloatIsNotZero {
149 context: Context<'static>,
150 received: FloatObject,
151 },
152
153 #[error(
154 "Json expect::{}() error at {context}:
155 {message},
156 {error}",
157 expected_operation.name,
158 )]
159 UnknownError {
160 #[source]
161 error: Box<dyn StdError>,
162 context: Context<'static>,
163 message: String,
164 expected_operation: ExpectOpMeta,
165 },
166
167 #[error(
168 "Json expect::{}() error at {context}:
169 {message}",
170 expected_operation.name,
171 )]
172 UnknownErrorMessage {
173 context: Context<'static>,
174 message: String,
175 expected_operation: ExpectOpMeta,
176 },
177
178 #[error("{error}")]
179 ExpectJsonError {
180 #[source]
181 error: Box<ExpectJsonError>,
182 },
183}
184
185impl ExpectOpError {
186 pub fn custom<O, S>(expect_op: &O, context: &Context<'_>, message: S) -> Self
187 where
188 O: ExpectOp + ?Sized,
189 S: Into<String>,
190 {
191 Self::UnknownErrorMessage {
192 context: context.to_static(),
193 message: message.into(),
194 expected_operation: ExpectOpMeta::new(expect_op),
195 }
196 }
197
198 pub fn custom_error<O, S, E>(expect_op: &O, context: &Context<'_>, message: S, error: E) -> Self
199 where
200 O: ExpectOp + ?Sized,
201 S: Into<String>,
202 E: StdError + 'static,
203 {
204 Self::UnknownError {
205 context: context.to_static(),
206 error: Box::new(error),
207 message: message.into(),
208 expected_operation: ExpectOpMeta::new(expect_op),
209 }
210 }
211
212 pub fn unsupported_operation_type<O, V>(
213 context: &Context<'_>,
214 expect_op: &O,
215 received: V,
216 ) -> Self
217 where
218 O: ExpectOp + ?Sized,
219 V: Into<ValueTypeObject>,
220 {
221 Self::UnsupportedOperation {
222 context: context.to_static(),
223 received: received.into(),
224 expected_operation: ExpectOpMeta::new(expect_op),
225 }
226 }
227}
228
229impl From<ExpectJsonError> for ExpectOpError {
230 fn from(error: ExpectJsonError) -> Self {
231 Self::ExpectJsonError {
232 error: Box::new(error),
233 }
234 }
235}
236
237fn format_expected_operation_types(expected_operation: &ExpectOpMeta) -> String {
238 let types = expected_operation.types;
239 if types.is_empty() {
240 return "no supported types listed (need to implement ExpectOp::supported_types)"
241 .to_string();
242 }
243
244 types.join(", ")
245}