1use crate::__private::ExpectOpExt;
2use crate::expect_op::Context;
3use crate::expect_op::ExpectOpError;
4use crate::expect_op::ExpectOpResult;
5use crate::internals::objects::IntegerObject;
6use crate::internals::objects::NullObject;
7use crate::internals::objects::ValueObject;
8use crate::JsonType;
9use serde_json::Map;
10use serde_json::Value;
11use std::fmt::Debug;
12
13pub trait ExpectOp: ExpectOpExt + Debug + Send + 'static {
14 fn on_any(&self, context: &mut Context<'_>, received: &Value) -> ExpectOpResult<()> {
15 match received {
16 Value::Null => self.on_null(context),
17 Value::Number(received_number) => {
18 let value_num = ValueObject::from(received_number.clone());
19 match value_num {
20 ValueObject::Float(received_float) => self.on_f64(context, received_float.into()),
21 ValueObject::Integer(IntegerObject::Positive(received_integer)) => self.on_u64(context, received_integer),
22 ValueObject::Integer(IntegerObject::Negative(received_integer)) => self.on_i64(context, received_integer),
23 _ => 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)"),
24 }
25 }
26 Value::String(received_string) => self.on_string(context, received_string),
27 Value::Bool(received_boolean) => self.on_boolean(context, *received_boolean),
28 Value::Array(received_array) => self.on_array(context, received_array),
29 Value::Object(received_object) => self.on_object(context, received_object),
30 }
31 }
32
33 #[allow(unused_variables)]
34 fn on_null(&self, context: &mut Context<'_>) -> ExpectOpResult<()> {
35 Err(ExpectOpError::unsupported_operation_type(
36 context, self, NullObject,
37 ))
38 }
39
40 #[allow(unused_variables)]
41 fn on_f64(&self, context: &mut Context<'_>, received: f64) -> ExpectOpResult<()> {
42 Err(ExpectOpError::unsupported_operation_type(
43 context, self, received,
44 ))
45 }
46
47 #[allow(unused_variables)]
48 fn on_u64(&self, context: &mut Context<'_>, received: u64) -> ExpectOpResult<()> {
49 Err(ExpectOpError::unsupported_operation_type(
50 context, self, received,
51 ))
52 }
53
54 #[allow(unused_variables)]
55 fn on_i64(&self, context: &mut Context<'_>, received: i64) -> ExpectOpResult<()> {
56 Err(ExpectOpError::unsupported_operation_type(
57 context, self, received,
58 ))
59 }
60
61 #[allow(unused_variables)]
62 fn on_boolean(&self, context: &mut Context<'_>, received: bool) -> ExpectOpResult<()> {
63 Err(ExpectOpError::unsupported_operation_type(
64 context, self, received,
65 ))
66 }
67
68 #[allow(unused_variables)]
69 fn on_string(&self, context: &mut Context<'_>, received: &str) -> ExpectOpResult<()> {
70 Err(ExpectOpError::unsupported_operation_type(
71 context,
72 self,
73 received.to_owned(),
74 ))
75 }
76
77 #[allow(unused_variables)]
78 fn on_array(&self, context: &mut Context<'_>, received: &[Value]) -> ExpectOpResult<()> {
79 Err(ExpectOpError::unsupported_operation_type(
80 context,
81 self,
82 received.to_owned(),
83 ))
84 }
85
86 #[allow(unused_variables)]
87 fn on_object(
88 &self,
89 context: &mut Context<'_>,
90 received: &Map<String, Value>,
91 ) -> ExpectOpResult<()> {
92 Err(ExpectOpError::unsupported_operation_type(
93 context,
94 self,
95 received.to_owned(),
96 ))
97 }
98
99 fn supported_types(&self) -> &'static [JsonType] {
100 &[]
101 }
102}
103
104#[cfg(test)]
105mod test_on_any {
106 use super::*;
107 use crate::internals::objects::ArrayObject;
108 use crate::internals::objects::BooleanObject;
109 use crate::internals::objects::FloatObject;
110 use crate::internals::objects::ObjectObject;
111 use crate::internals::objects::StringObject;
112 use crate::internals::objects::ValueTypeObject;
113 use crate::internals::ExpectOpMeta;
114 use serde_json::json;
115
116 #[crate::expect_op(internal)]
118 #[derive(Debug, Clone)]
119 struct TestJsonExpectOp;
120
121 impl ExpectOp for TestJsonExpectOp {}
122
123 #[test]
124 fn it_should_error_by_default_against_json_null() {
125 let mut outer_context = Context::new();
126 let received = json!(null);
127 let output = TestJsonExpectOp
128 .on_any(&mut outer_context, &received)
129 .unwrap_err();
130 assert!(matches!(
131 output,
132 ExpectOpError::UnsupportedOperation {
133 context,
134 received: ValueTypeObject(ValueObject::Null(NullObject)),
135 expected_operation: ExpectOpMeta {
136 name: "TestJsonExpectOp",
137 types: &[],
138 },
139 } if context == outer_context.to_static()
140 ));
141 }
142
143 #[test]
144 fn it_should_error_by_default_against_json_boolean() {
145 let mut outer_context = Context::new();
146 let received = json!(true);
147 let output = TestJsonExpectOp
148 .on_any(&mut outer_context, &received)
149 .unwrap_err();
150 assert!(matches!(
151 output,
152 ExpectOpError::UnsupportedOperation {
153 context,
154 received: ValueTypeObject(ValueObject::Boolean(BooleanObject(true))),
155 expected_operation: ExpectOpMeta {
156 name: "TestJsonExpectOp",
157 types: &[],
158 },
159 } if context == outer_context.to_static()
160 ));
161 }
162
163 #[test]
164 fn it_should_error_by_default_against_json_positive_integer() {
165 let mut outer_context = Context::new();
166 let received = json!(123);
167 let output = TestJsonExpectOp
168 .on_any(&mut outer_context, &received)
169 .unwrap_err();
170 assert!(matches!(
171 output,
172 ExpectOpError::UnsupportedOperation {
173 context,
174 received: ValueTypeObject(ValueObject::Integer(IntegerObject::Positive(123))),
175 expected_operation: ExpectOpMeta {
176 name: "TestJsonExpectOp",
177 types: &[],
178 },
179 } if context == outer_context.to_static()
180 ));
181 }
182
183 #[test]
184 fn it_should_error_by_default_against_json_negative_integer() {
185 let mut outer_context = Context::new();
186 let received = json!(-123);
187 let output = TestJsonExpectOp
188 .on_any(&mut outer_context, &received)
189 .unwrap_err();
190 assert!(matches!(
191 output,
192 ExpectOpError::UnsupportedOperation {
193 context,
194 received: ValueTypeObject(ValueObject::Integer(IntegerObject::Negative(-123))),
195 expected_operation: ExpectOpMeta {
196 name: "TestJsonExpectOp",
197 types: &[],
198 },
199 } if context == outer_context.to_static()
200 ));
201 }
202
203 #[test]
204 fn it_should_error_by_default_against_json_float() {
205 let mut outer_context = Context::new();
206 let received = json!(123.456);
207 let output = TestJsonExpectOp
208 .on_any(&mut outer_context, &received)
209 .unwrap_err();
210 assert!(matches!(
211 output,
212 ExpectOpError::UnsupportedOperation {
213 context,
214 received: ValueTypeObject(ValueObject::Float(FloatObject(123.456))),
215 expected_operation: ExpectOpMeta {
216 name: "TestJsonExpectOp",
217 types: &[],
218 },
219 } if context == outer_context.to_static()
220 ));
221 }
222
223 #[test]
224 fn it_should_error_by_default_against_json_string() {
225 let mut outer_context = Context::new();
226 let received = json!("🦊");
227 let output = TestJsonExpectOp
228 .on_any(&mut outer_context, &received)
229 .unwrap_err();
230 assert!(matches!(
231 output,
232 ExpectOpError::UnsupportedOperation {
233 context,
234 received,
235 expected_operation: ExpectOpMeta {
236 name: "TestJsonExpectOp",
237 types: &[],
238 },
239 } if context == outer_context.to_static()
240 && received == ValueTypeObject(ValueObject::String(StringObject("🦊".to_string())))
241 ));
242 }
243
244 #[test]
245 fn it_should_error_by_default_against_json_array() {
246 let mut outer_context = Context::new();
247 let received = json!([]);
248 let output = TestJsonExpectOp
249 .on_any(&mut outer_context, &received)
250 .unwrap_err();
251 assert!(matches!(
252 output,
253 ExpectOpError::UnsupportedOperation {
254 context,
255 received,
256 expected_operation: ExpectOpMeta {
257 name: "TestJsonExpectOp",
258 types: &[],
259 },
260 } if context == outer_context.to_static()
261 && received == ValueTypeObject(ValueObject::Array(ArrayObject(vec![])))
262 ));
263 }
264
265 #[test]
266 fn it_should_error_by_default_against_json_object() {
267 let mut outer_context = Context::new();
268 let received = json!({});
269 let output = TestJsonExpectOp
270 .on_any(&mut outer_context, &received)
271 .unwrap_err();
272 assert!(matches!(
273 output,
274 ExpectOpError::UnsupportedOperation {
275 context,
276 received,
277 expected_operation: ExpectOpMeta {
278 name: "TestJsonExpectOp",
279 types: &[],
280 },
281 } if context == outer_context.to_static()
282 && received == ValueTypeObject(ValueObject::Object(ObjectObject(Map::new())))
283 ));
284 }
285}