json_matcher/matchers/
number.rs1use serde_json::Value;
2
3use crate::{JsonMatcher, JsonMatcherError};
4
5pub struct IntegerMatcher {
6 value: i64,
7}
8
9impl IntegerMatcher {
10 pub fn new(value: i64) -> Self {
11 Self { value }
12 }
13}
14
15impl JsonMatcher for IntegerMatcher {
16 fn json_matches(&self, value: &Value) -> Vec<JsonMatcherError> {
17 match value {
18 Value::Number(num) => {
19 let Some(actual) = num.as_i64() else {
20 return vec![JsonMatcherError::at_root(format!(
21 "Expected integer {} but got float {}",
22 self.value, num
23 ))];
24 };
25 if actual == self.value {
26 vec![]
27 } else {
28 vec![JsonMatcherError::at_root(format!(
29 "Expected integer {} but got {}",
30 self.value, actual
31 ))]
32 }
33 }
34 _ => vec![JsonMatcherError::at_root("Value is not an integer")],
35 }
36 }
37}
38
39impl JsonMatcher for i8 {
40 fn json_matches(&self, value: &Value) -> Vec<JsonMatcherError> {
41 IntegerMatcher::new(*self as i64).json_matches(value)
42 }
43}
44
45impl JsonMatcher for i16 {
46 fn json_matches(&self, value: &Value) -> Vec<JsonMatcherError> {
47 IntegerMatcher::new(*self as i64).json_matches(value)
48 }
49}
50
51impl JsonMatcher for i32 {
52 fn json_matches(&self, value: &Value) -> Vec<JsonMatcherError> {
53 IntegerMatcher::new(*self as i64).json_matches(value)
54 }
55}
56
57impl JsonMatcher for i64 {
58 fn json_matches(&self, value: &Value) -> Vec<JsonMatcherError> {
59 IntegerMatcher::new(*self).json_matches(value)
60 }
61}
62
63impl JsonMatcher for u8 {
64 fn json_matches(&self, value: &Value) -> Vec<JsonMatcherError> {
65 IntegerMatcher::new(*self as i64).json_matches(value)
66 }
67}
68
69impl JsonMatcher for u16 {
70 fn json_matches(&self, value: &Value) -> Vec<JsonMatcherError> {
71 IntegerMatcher::new(*self as i64).json_matches(value)
72 }
73}
74
75impl JsonMatcher for u32 {
76 fn json_matches(&self, value: &Value) -> Vec<JsonMatcherError> {
77 IntegerMatcher::new(*self as i64).json_matches(value)
78 }
79}
80
81pub struct NumberMatcher {
82 number: f64,
83}
84
85impl NumberMatcher {
86 pub fn new(value: f64) -> Self {
87 Self { number: value }
88 }
89}
90
91impl JsonMatcher for NumberMatcher {
92 fn json_matches(&self, value: &Value) -> Vec<JsonMatcherError> {
93 match value {
94 Value::Number(num) => {
95 let Some(actual) = num.as_f64() else {
96 return vec![JsonMatcherError::at_root(format!(
97 "Expected float {} but got integer {}",
98 self.number, num
99 ))];
100 };
101 if actual == self.number {
102 vec![]
103 } else {
104 vec![JsonMatcherError::at_root(format!(
105 "Expected float {} but got {}",
106 self.number, actual
107 ))]
108 }
109 }
110 _ => vec![JsonMatcherError::at_root("Value is not a float")],
111 }
112 }
113}
114
115impl JsonMatcher for f32 {
116 fn json_matches(&self, value: &Value) -> Vec<JsonMatcherError> {
117 NumberMatcher::new(*self as f64).json_matches(value)
118 }
119}
120
121impl JsonMatcher for f64 {
122 fn json_matches(&self, value: &Value) -> Vec<JsonMatcherError> {
123 NumberMatcher::new(*self).json_matches(value)
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use serde_json::Number;
130
131 use crate::assert_jm;
132
133 use crate::test::catch_string_panic;
134
135 use super::*;
136
137 #[test]
138 fn test_integer_matcher() {
139 let get_matcher = || IntegerMatcher::new(4);
140 assert_jm!(Value::Number(4.into()), get_matcher());
141 assert_eq!(
143 catch_string_panic(|| assert_jm!(Value::String("bloop".to_string()), get_matcher())),
144 r#"
145Json matcher failed:
146 - $: Value is not an integer
147
148Actual:
149"bloop""#
150 );
151 assert_eq!(
153 catch_string_panic(|| assert_jm!(
154 Value::Number(Number::from_f64(2.2).unwrap()),
155 get_matcher()
156 )),
157 r#"
158Json matcher failed:
159 - $: Expected integer 4 but got float 2.2
160
161Actual:
1622.2"#
163 );
164 assert_eq!(
166 catch_string_panic(|| assert_jm!(Value::Number(2.into()), get_matcher())),
167 r#"
168Json matcher failed:
169 - $: Expected integer 4 but got 2
170
171Actual:
1722"#
173 );
174 }
175
176 #[test]
177 fn test_number_matcher() {
178 let get_matcher = || NumberMatcher::new(4.0);
179 assert_jm!(Value::Number(Number::from_f64(4.0).unwrap()), get_matcher());
181 assert_jm!(Value::Number(4i64.into()), get_matcher());
183 assert_eq!(
185 catch_string_panic(|| assert_jm!(Value::String("bloop".to_string()), get_matcher())),
186 r#"
187Json matcher failed:
188 - $: Value is not a float
189
190Actual:
191"bloop""#
192 );
193 assert_eq!(
195 catch_string_panic(|| assert_jm!(
196 Value::Number(Number::from_f64(7.2).unwrap()),
197 get_matcher()
198 )),
199 r#"
200Json matcher failed:
201 - $: Expected float 4 but got 7.2
202
203Actual:
2047.2"#
205 );
206 }
207
208 #[test]
209 fn test_raw_implementations() {
210 assert_eq!(4i8.json_matches(&Value::Number(4.into())), vec![]);
212 assert_eq!(
213 4i8.json_matches(&Value::Number(5.into()))
214 .into_iter()
215 .map(|e| e.to_string())
216 .collect::<String>(),
217 "$: Expected integer 4 but got 5"
218 );
219 assert_eq!(4i16.json_matches(&Value::Number(4.into())), vec![]);
221 assert_eq!(
222 4i16.json_matches(&Value::Number(5.into()))
223 .into_iter()
224 .map(|e| e.to_string())
225 .collect::<String>(),
226 "$: Expected integer 4 but got 5"
227 );
228 assert_eq!(4i32.json_matches(&Value::Number(4.into())), vec![]);
230 assert_eq!(
231 4i32.json_matches(&Value::Number(5.into()))
232 .into_iter()
233 .map(|e| e.to_string())
234 .collect::<String>(),
235 "$: Expected integer 4 but got 5"
236 );
237 assert_eq!(4i64.json_matches(&Value::Number(4.into())), vec![]);
239 assert_eq!(
240 4i64.json_matches(&Value::Number(5.into()))
241 .into_iter()
242 .map(|e| e.to_string())
243 .collect::<String>(),
244 "$: Expected integer 4 but got 5"
245 );
246 assert_eq!(4u8.json_matches(&Value::Number(4.into())), vec![]);
248 assert_eq!(
249 4u8.json_matches(&Value::Number(5.into()))
250 .into_iter()
251 .map(|e| e.to_string())
252 .collect::<String>(),
253 "$: Expected integer 4 but got 5"
254 );
255 assert_eq!(4u16.json_matches(&Value::Number(4.into())), vec![]);
257 assert_eq!(
258 4u16.json_matches(&Value::Number(5.into()))
259 .into_iter()
260 .map(|e| e.to_string())
261 .collect::<String>(),
262 "$: Expected integer 4 but got 5"
263 );
264 assert_eq!(4u32.json_matches(&Value::Number(4.into())), vec![]);
266 assert_eq!(
267 4u32.json_matches(&Value::Number(5.into()))
268 .into_iter()
269 .map(|e| e.to_string())
270 .collect::<String>(),
271 "$: Expected integer 4 but got 5"
272 );
273 assert_eq!(4f32.json_matches(&Value::Number(4.into())), vec![]);
275 assert_eq!(
276 4f32.json_matches(&Value::Number(5.into()))
277 .into_iter()
278 .map(|e| e.to_string())
279 .collect::<String>(),
280 "$: Expected float 4 but got 5"
281 );
282 assert_eq!(4f64.json_matches(&Value::Number(4.into())), vec![]);
284 assert_eq!(
285 4f64.json_matches(&Value::Number(5.into()))
286 .into_iter()
287 .map(|e| e.to_string())
288 .collect::<String>(),
289 "$: Expected float 4 but got 5"
290 );
291 }
292}