1use crate::expect_core::Context;
2use crate::expect_core::ExpectOp;
3use crate::internals::objects::ArrayObject;
4use crate::internals::objects::FloatObject;
5use crate::internals::objects::IntegerObject;
6use crate::internals::objects::ValueObject;
7use crate::internals::objects::ValueTypeObject;
8use crate::internals::ExpectOpMeta;
9use crate::ExpectJsonError;
10use crate::JsonType;
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 expect::array() error at {context},
81 expected array to contain all unique values.
82 found duplicate {duplicate}
83 received full array {received_array}"
84 )]
85 ArrayContainsDuplicate {
86 context: Context<'static>,
87 duplicate: ValueObject,
88 received_array: ArrayObject,
89 },
90
91 #[error(
92 "{error}
93 received full array {received_full_array}"
94 )]
95 ArrayAllEqual {
96 #[source]
97 error: Box<ExpectJsonError>,
98 received_full_array: ArrayObject,
99 },
100
101 #[error(
102 "Json expect::integer() error at {context}, is zero:
103 expected non-zero integer
104 received {received}"
105 )]
106 IntegerIsZero {
107 context: Context<'static>,
108 received: IntegerObject,
109 },
110
111 #[error(
112 "Json expect::integer() error at {context}, is not zero:
113 expected 0
114 received {received}"
115 )]
116 IntegerIsNotZero {
117 context: Context<'static>,
118 received: IntegerObject,
119 },
120
121 #[error(
122 "Json expect::float() error at {context}, is zero:
123 expected non-zero float
124 received {received}"
125 )]
126 FloatIsZero {
127 context: Context<'static>,
128 received: FloatObject,
129 },
130
131 #[error(
132 "Json expect::float() error at {context}, is not zero:
133 expected 0.0
134 received {received}"
135 )]
136 FloatIsNotZero {
137 context: Context<'static>,
138 received: FloatObject,
139 },
140
141 #[error(
142 "Json expect::{}() error at {context}:
143 {message},
144 {error}",
145 expected_operation.name,
146 )]
147 UnknownError {
148 #[source]
149 error: Box<dyn StdError>,
150 context: Context<'static>,
151 message: String,
152 expected_operation: ExpectOpMeta,
153 },
154
155 #[error(
156 "Json expect::{}() error at {context}:
157 {message}",
158 expected_operation.name,
159 )]
160 UnknownErrorMessage {
161 context: Context<'static>,
162 message: String,
163 expected_operation: ExpectOpMeta,
164 },
165
166 #[error("{error}")]
167 ExpectJsonError {
168 #[source]
169 error: Box<ExpectJsonError>,
170 },
171}
172
173impl ExpectOpError {
174 pub fn custom<O, S>(expect_op: &O, context: &Context<'_>, message: S) -> Self
175 where
176 O: ExpectOp + ?Sized,
177 S: Into<String>,
178 {
179 Self::UnknownErrorMessage {
180 context: context.to_static(),
181 message: message.into(),
182 expected_operation: ExpectOpMeta::new(expect_op),
183 }
184 }
185
186 pub fn custom_error<O, S, E>(expect_op: &O, context: &Context<'_>, message: S, error: E) -> Self
187 where
188 O: ExpectOp + ?Sized,
189 S: Into<String>,
190 E: StdError + 'static,
191 {
192 Self::UnknownError {
193 context: context.to_static(),
194 error: Box::new(error),
195 message: message.into(),
196 expected_operation: ExpectOpMeta::new(expect_op),
197 }
198 }
199
200 pub fn unsupported_operation_type<O, V>(
201 context: &Context<'_>,
202 expect_op: &O,
203 received: V,
204 ) -> Self
205 where
206 O: ExpectOp + ?Sized,
207 V: Into<ValueTypeObject>,
208 {
209 Self::UnsupportedOperation {
210 context: context.to_static(),
211 received: received.into(),
212 expected_operation: ExpectOpMeta::new(expect_op),
213 }
214 }
215}
216
217impl From<ExpectJsonError> for ExpectOpError {
218 fn from(error: ExpectJsonError) -> Self {
219 Self::ExpectJsonError {
220 error: Box::new(error),
221 }
222 }
223}
224
225fn format_expected_operation_types(expected_operation: &ExpectOpMeta) -> String {
226 let types = expected_operation.types;
227 if types.is_empty() {
228 return "no supported types listed (need to implement ExpectOp::supported_types)"
229 .to_string();
230 }
231
232 types.join(", ")
233}