1use crate::__private::ExpectOpExt;
2use crate::JsonType;
3use crate::expect_core::Context;
4use crate::expect_core::ExpectOpError;
5use crate::expect_core::ExpectOpResult;
6use crate::internals::objects::IntegerObject;
7use crate::internals::objects::NullObject;
8use crate::internals::objects::ValueObject;
9use serde_json::Map;
10use serde_json::Value;
11use std::fmt::Debug;
12
13pub trait ExpectOp: ExpectOpExt + Debug + Send + 'static {
76 fn on_any(&self, context: &mut Context<'_>, received: &Value) -> ExpectOpResult<()> {
77 context.without_propagated_contains().map(|context| {
78 match received {
79 Value::Null => self.on_null(context),
80 Value::Number(received_number) => {
81 let value_num = ValueObject::from(received_number.clone());
82 match value_num {
83 ValueObject::Float(received_float) => self.on_f64(context, received_float.into()),
84 ValueObject::Integer(IntegerObject::Positive(received_integer)) => self.on_u64(context, received_integer),
85 ValueObject::Integer(IntegerObject::Negative(received_integer)) => self.on_i64(context, received_integer),
86 _ => panic!("Unexpected non-number value, expected a float or an integer, found {value_num:?}. (This is a bug, please report at: https://github.com/JosephLenton/expect-json/issues)"),
87 }
88 }
89 Value::String(received_string) => self.on_string(context, received_string),
90 Value::Bool(received_boolean) => self.on_boolean(context, *received_boolean),
91 Value::Array(received_array) => self.on_array(context, received_array),
92 Value::Object(received_object) => self.on_object(context, received_object),
93 }
94 })
95 }
96
97 #[allow(unused_variables)]
98 fn on_null(&self, context: &mut Context<'_>) -> ExpectOpResult<()> {
99 Err(ExpectOpError::unsupported_operation_type(
100 context, self, NullObject,
101 ))
102 }
103
104 #[allow(unused_variables)]
105 fn on_f64(&self, context: &mut Context<'_>, received: f64) -> ExpectOpResult<()> {
106 Err(ExpectOpError::unsupported_operation_type(
107 context, self, received,
108 ))
109 }
110
111 #[allow(unused_variables)]
112 fn on_u64(&self, context: &mut Context<'_>, received: u64) -> ExpectOpResult<()> {
113 Err(ExpectOpError::unsupported_operation_type(
114 context, self, received,
115 ))
116 }
117
118 #[allow(unused_variables)]
119 fn on_i64(&self, context: &mut Context<'_>, received: i64) -> ExpectOpResult<()> {
120 Err(ExpectOpError::unsupported_operation_type(
121 context, self, received,
122 ))
123 }
124
125 #[allow(unused_variables)]
126 fn on_boolean(&self, context: &mut Context<'_>, received: bool) -> ExpectOpResult<()> {
127 Err(ExpectOpError::unsupported_operation_type(
128 context, self, received,
129 ))
130 }
131
132 #[allow(unused_variables)]
133 fn on_string(&self, context: &mut Context<'_>, received: &str) -> ExpectOpResult<()> {
134 Err(ExpectOpError::unsupported_operation_type(
135 context,
136 self,
137 received.to_owned(),
138 ))
139 }
140
141 #[allow(unused_variables)]
142 fn on_array(&self, context: &mut Context<'_>, received: &[Value]) -> ExpectOpResult<()> {
143 Err(ExpectOpError::unsupported_operation_type(
144 context,
145 self,
146 received.to_owned(),
147 ))
148 }
149
150 #[allow(unused_variables)]
151 fn on_object(
152 &self,
153 context: &mut Context<'_>,
154 received: &Map<String, Value>,
155 ) -> ExpectOpResult<()> {
156 Err(ExpectOpError::unsupported_operation_type(
157 context,
158 self,
159 received.to_owned(),
160 ))
161 }
162
163 fn debug_supported_types(&self) -> &'static [JsonType] {
167 &[]
168 }
169}
170
171#[cfg(test)]
172mod test_on_any {
173 use super::*;
174 use crate::internals::ExpectOpMeta;
175 use crate::internals::objects::ArrayObject;
176 use crate::internals::objects::BooleanObject;
177 use crate::internals::objects::FloatObject;
178 use crate::internals::objects::ObjectObject;
179 use crate::internals::objects::StringObject;
180 use crate::internals::objects::ValueTypeObject;
181 use serde_json::json;
182
183 #[crate::expect_core::expect_op(internal)]
185 #[derive(Debug, Clone)]
186 struct TestJsonExpectOp;
187
188 impl ExpectOp for TestJsonExpectOp {}
189
190 #[test]
191 fn it_should_error_by_default_against_json_null() {
192 let mut outer_context = Context::new();
193 let received = json!(null);
194 let output = TestJsonExpectOp
195 .on_any(&mut outer_context, &received)
196 .unwrap_err();
197 assert!(matches!(
198 output,
199 ExpectOpError::UnsupportedOperation {
200 context,
201 received: ValueTypeObject(ValueObject::Null(NullObject)),
202 expected_operation: ExpectOpMeta {
203 name: "TestJsonExpectOp",
204 types: &[],
205 },
206 } if context == outer_context.to_static()
207 ));
208 }
209
210 #[test]
211 fn it_should_error_by_default_against_json_boolean() {
212 let mut outer_context = Context::new();
213 let received = json!(true);
214 let output = TestJsonExpectOp
215 .on_any(&mut outer_context, &received)
216 .unwrap_err();
217 assert!(matches!(
218 output,
219 ExpectOpError::UnsupportedOperation {
220 context,
221 received: ValueTypeObject(ValueObject::Boolean(BooleanObject(true))),
222 expected_operation: ExpectOpMeta {
223 name: "TestJsonExpectOp",
224 types: &[],
225 },
226 } if context == outer_context.to_static()
227 ));
228 }
229
230 #[test]
231 fn it_should_error_by_default_against_json_positive_integer() {
232 let mut outer_context = Context::new();
233 let received = json!(123);
234 let output = TestJsonExpectOp
235 .on_any(&mut outer_context, &received)
236 .unwrap_err();
237 assert!(matches!(
238 output,
239 ExpectOpError::UnsupportedOperation {
240 context,
241 received: ValueTypeObject(ValueObject::Integer(IntegerObject::Positive(123))),
242 expected_operation: ExpectOpMeta {
243 name: "TestJsonExpectOp",
244 types: &[],
245 },
246 } if context == outer_context.to_static()
247 ));
248 }
249
250 #[test]
251 fn it_should_error_by_default_against_json_negative_integer() {
252 let mut outer_context = Context::new();
253 let received = json!(-123);
254 let output = TestJsonExpectOp
255 .on_any(&mut outer_context, &received)
256 .unwrap_err();
257 assert!(matches!(
258 output,
259 ExpectOpError::UnsupportedOperation {
260 context,
261 received: ValueTypeObject(ValueObject::Integer(IntegerObject::Negative(-123))),
262 expected_operation: ExpectOpMeta {
263 name: "TestJsonExpectOp",
264 types: &[],
265 },
266 } if context == outer_context.to_static()
267 ));
268 }
269
270 #[test]
271 fn it_should_error_by_default_against_json_float() {
272 let mut outer_context = Context::new();
273 let received = json!(123.456);
274 let output = TestJsonExpectOp
275 .on_any(&mut outer_context, &received)
276 .unwrap_err();
277 assert!(matches!(
278 output,
279 ExpectOpError::UnsupportedOperation {
280 context,
281 received: ValueTypeObject(ValueObject::Float(FloatObject(123.456))),
282 expected_operation: ExpectOpMeta {
283 name: "TestJsonExpectOp",
284 types: &[],
285 },
286 } if context == outer_context.to_static()
287 ));
288 }
289
290 #[test]
291 fn it_should_error_by_default_against_json_string() {
292 let mut outer_context = Context::new();
293 let received = json!("🦊");
294 let output = TestJsonExpectOp
295 .on_any(&mut outer_context, &received)
296 .unwrap_err();
297 assert!(matches!(
298 output,
299 ExpectOpError::UnsupportedOperation {
300 context,
301 received,
302 expected_operation: ExpectOpMeta {
303 name: "TestJsonExpectOp",
304 types: &[],
305 },
306 } if context == outer_context.to_static()
307 && received == ValueTypeObject(ValueObject::String(StringObject("🦊".to_string())))
308 ));
309 }
310
311 #[test]
312 fn it_should_error_by_default_against_json_array() {
313 let mut outer_context = Context::new();
314 let received = json!([]);
315 let output = TestJsonExpectOp
316 .on_any(&mut outer_context, &received)
317 .unwrap_err();
318 assert!(matches!(
319 output,
320 ExpectOpError::UnsupportedOperation {
321 context,
322 received,
323 expected_operation: ExpectOpMeta {
324 name: "TestJsonExpectOp",
325 types: &[],
326 },
327 } if context == outer_context.to_static()
328 && received == ValueTypeObject(ValueObject::Array(ArrayObject(vec![])))
329 ));
330 }
331
332 #[test]
333 fn it_should_error_by_default_against_json_object() {
334 let mut outer_context = Context::new();
335 let received = json!({});
336 let output = TestJsonExpectOp
337 .on_any(&mut outer_context, &received)
338 .unwrap_err();
339 assert!(matches!(
340 output,
341 ExpectOpError::UnsupportedOperation {
342 context,
343 received,
344 expected_operation: ExpectOpMeta {
345 name: "TestJsonExpectOp",
346 types: &[],
347 },
348 } if context == outer_context.to_static()
349 && received == ValueTypeObject(ValueObject::Object(ObjectObject(Map::new())))
350 ));
351 }
352}