1use serde::Deserialize;
2use serde::Serialize;
3use std::fmt::Display;
4use std::fmt::Formatter;
5use std::fmt::Result as FmtResult;
6
7#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
10#[serde(untagged)]
11pub enum JsonInteger {
12 Positive(u64),
13 Negative(i64),
14}
15
16impl JsonInteger {
17 pub(crate) fn gt<O>(self, other: O) -> bool
18 where
19 O: Into<JsonInteger>,
20 {
21 let other_json = other.into();
22 match (self, other_json) {
23 (Self::Positive(l), Self::Positive(r)) => l > r,
24 (Self::Positive(l), Self::Negative(r)) => {
25 if r < 0 {
26 return true;
27 }
28
29 l > (r as u64)
30 }
31 (Self::Negative(l), Self::Negative(r)) => l > r,
32 (Self::Negative(l), Self::Positive(r)) => {
33 if l < 0 {
34 return false;
35 }
36
37 (l as u64) > r
38 }
39 }
40 }
41
42 pub(crate) fn ge<O>(self, other: O) -> bool
43 where
44 O: Into<JsonInteger>,
45 {
46 let other_json = other.into();
47 match (self, other_json) {
48 (Self::Positive(l), Self::Positive(r)) => l >= r,
49 (Self::Positive(l), Self::Negative(r)) => {
50 if r < 0 {
51 return true;
52 }
53
54 l >= (r as u64)
55 }
56 (Self::Negative(l), Self::Negative(r)) => l >= r,
57 (Self::Negative(l), Self::Positive(r)) => {
58 if l < 0 {
59 return false;
60 }
61
62 (l as u64) >= r
63 }
64 }
65 }
66
67 pub(crate) fn lt<O>(self, other: O) -> bool
68 where
69 O: Into<JsonInteger>,
70 {
71 let other_json = other.into();
72 match (self, other_json) {
73 (Self::Positive(l), Self::Positive(r)) => l < r,
74 (Self::Positive(l), Self::Negative(r)) => {
75 if r < 0 {
76 return false;
77 }
78
79 l < (r as u64)
80 }
81 (Self::Negative(l), Self::Negative(r)) => l < r,
82 (Self::Negative(l), Self::Positive(r)) => {
83 if l < 0 {
84 return true;
85 }
86
87 (l as u64) < r
88 }
89 }
90 }
91
92 pub(crate) fn le<O>(self, other: O) -> bool
93 where
94 O: Into<JsonInteger>,
95 {
96 let other_json = other.into();
97 match (self, other_json) {
98 (Self::Positive(l), Self::Positive(r)) => l <= r,
99 (Self::Positive(l), Self::Negative(r)) => {
100 if r < 0 {
101 return false;
102 }
103
104 l <= (r as u64)
105 }
106 (Self::Negative(l), Self::Negative(r)) => l <= r,
107 (Self::Negative(l), Self::Positive(r)) => {
108 if l < 0 {
109 return true;
110 }
111
112 (l as u64) <= r
113 }
114 }
115 }
116}
117
118impl Display for JsonInteger {
119 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
120 match *self {
121 Self::Positive(n) => write!(f, "{n}"),
122 Self::Negative(n) => write!(f, "{n}"),
123 }
124 }
125}
126
127impl From<u8> for JsonInteger {
128 fn from(n: u8) -> Self {
129 Self::Positive(n as u64)
130 }
131}
132
133impl From<i8> for JsonInteger {
134 fn from(n: i8) -> Self {
135 Self::Negative(n as i64)
136 }
137}
138
139impl From<u16> for JsonInteger {
140 fn from(n: u16) -> Self {
141 Self::Positive(n as u64)
142 }
143}
144
145impl From<i16> for JsonInteger {
146 fn from(n: i16) -> Self {
147 Self::Negative(n as i64)
148 }
149}
150
151impl From<u32> for JsonInteger {
152 fn from(n: u32) -> Self {
153 Self::Positive(n as u64)
154 }
155}
156
157impl From<i32> for JsonInteger {
158 fn from(n: i32) -> Self {
159 Self::Negative(n as i64)
160 }
161}
162
163impl From<u64> for JsonInteger {
164 fn from(n: u64) -> Self {
165 Self::Positive(n)
166 }
167}
168
169impl From<i64> for JsonInteger {
170 fn from(n: i64) -> Self {
171 Self::Negative(n)
172 }
173}
174
175impl From<usize> for JsonInteger {
176 fn from(n: usize) -> Self {
177 Self::Positive(n as u64)
178 }
179}
180
181impl From<isize> for JsonInteger {
182 fn from(n: isize) -> Self {
183 Self::Negative(n as i64)
184 }
185}
186
187#[cfg(test)]
188mod test_from {
189 use super::*;
190 use pretty_assertions::assert_eq;
191
192 #[test]
193 fn it_should_contain_value_from_i8() {
194 let output = JsonInteger::from(-123_i8);
195 assert_eq!(output, JsonInteger::Negative(-123));
196 }
197
198 #[test]
199 fn it_should_contain_value_from_u8() {
200 let output = JsonInteger::from(123_u8);
201 assert_eq!(output, JsonInteger::Positive(123));
202 }
203
204 #[test]
205 fn it_should_contain_value_from_i16() {
206 let output = JsonInteger::from(-123_i16);
207 assert_eq!(output, JsonInteger::Negative(-123));
208 }
209
210 #[test]
211 fn it_should_contain_value_from_u16() {
212 let output = JsonInteger::from(123_u16);
213 assert_eq!(output, JsonInteger::Positive(123));
214 }
215
216 #[test]
217 fn it_should_contain_value_from_i32() {
218 let output = JsonInteger::from(-123_i32);
219 assert_eq!(output, JsonInteger::Negative(-123));
220 }
221
222 #[test]
223 fn it_should_contain_value_from_u32() {
224 let output = JsonInteger::from(123_u32);
225 assert_eq!(output, JsonInteger::Positive(123));
226 }
227
228 #[test]
229 fn it_should_contain_value_from_i64() {
230 let output = JsonInteger::from(-123_i64);
231 assert_eq!(output, JsonInteger::Negative(-123));
232 }
233
234 #[test]
235 fn it_should_contain_value_from_u64() {
236 let output = JsonInteger::from(123_u64);
237 assert_eq!(output, JsonInteger::Positive(123));
238 }
239
240 #[test]
241 fn it_should_contain_value_from_isize() {
242 let output = JsonInteger::from(-123_isize);
243 assert_eq!(output, JsonInteger::Negative(-123));
244 }
245
246 #[test]
247 fn it_should_contain_value_from_usize() {
248 let output = JsonInteger::from(123_usize);
249 assert_eq!(output, JsonInteger::Positive(123));
250 }
251}
252
253#[cfg(test)]
254mod test_fmt {
255 use super::*;
256
257 #[test]
258 fn it_should_print_positive_numbers_as_themselves() {
259 let num = JsonInteger::Positive(123);
260 let output = num.to_string();
261
262 assert_eq!(output, "123")
263 }
264
265 #[test]
266 fn it_should_print_negative_numbers_as_themselves() {
267 let num = JsonInteger::Negative(-123);
268 let output = num.to_string();
269
270 assert_eq!(output, "-123")
271 }
272}
273
274#[cfg(test)]
275mod test_lt {
276 use super::*;
277 use rstest::rstest;
278
279 #[rstest]
280 #[case(101, 100, false)]
281 #[case(100, 100, false)]
282 #[case(99, 100, true)]
283 fn it_should_handle_u64_to_u64_correctly(
284 #[case] l_num: u64,
285 #[case] r_num: u64,
286 #[case] expected: bool,
287 ) {
288 let l = JsonInteger::from(l_num);
289 let r = JsonInteger::from(r_num);
290 assert_eq!(
291 l.lt(r),
292 expected,
293 "{l_num} < {r_num} was expected to be {expected}"
294 );
295 }
296
297 #[rstest]
298 #[case(101, 100, false)]
299 #[case(100, 100, false)]
300 #[case(99, 100, true)]
301 #[case(-101, -100, true)]
302 #[case(-100, -100, false)]
303 #[case(-99, -100, false)]
304 fn it_should_handle_i64_to_i64_correctly(
305 #[case] l_num: i64,
306 #[case] r_num: i64,
307 #[case] expected: bool,
308 ) {
309 let l = JsonInteger::from(l_num);
310 let r = JsonInteger::from(r_num);
311 assert_eq!(
312 l.lt(r),
313 expected,
314 "{l_num} < {r_num} was expected to be {expected}"
315 );
316 }
317
318 #[rstest]
319 #[case(101, 100, false)]
320 #[case(100, 100, false)]
321 #[case(99, 100, true)]
322 #[case(0, 0, false)]
323 #[case(-0, 0, false)]
324 #[case(-1, 0, true)]
325 fn it_should_handle_i64_to_u64_correctly(
326 #[case] l_num: i64,
327 #[case] r_num: u64,
328 #[case] expected: bool,
329 ) {
330 let l = JsonInteger::from(l_num);
331 let r = JsonInteger::from(r_num);
332 assert_eq!(
333 l.lt(r),
334 expected,
335 "{l_num} < {r_num} was expected to be {expected}"
336 );
337 }
338
339 #[rstest]
340 #[case(101, 100, false)]
341 #[case(100, 100, false)]
342 #[case(99, 100, true)]
343 #[case(0, 0, false)]
344 #[case(0, -0, false)]
345 #[case(0, -1, false)]
346 fn it_should_handle_u64_to_i64_correctly(
347 #[case] l_num: u64,
348 #[case] r_num: i64,
349 #[case] expected: bool,
350 ) {
351 let l = JsonInteger::from(l_num);
352 let r = JsonInteger::from(r_num);
353 assert_eq!(
354 l.lt(r),
355 expected,
356 "{l_num} < {r_num} was expected to be {expected}"
357 );
358 }
359}
360
361#[cfg(test)]
362mod test_le {
363 use super::*;
364 use rstest::rstest;
365
366 #[rstest]
367 #[case(101, 100, false)]
368 #[case(100, 100, true)]
369 #[case(99, 100, true)]
370 fn it_should_handle_u64_to_u64_correctly(
371 #[case] l_num: u64,
372 #[case] r_num: u64,
373 #[case] expected: bool,
374 ) {
375 let l = JsonInteger::from(l_num);
376 let r = JsonInteger::from(r_num);
377 assert_eq!(
378 l.le(r),
379 expected,
380 "{l_num} <= {r_num} was expected to be {expected}"
381 );
382 }
383
384 #[rstest]
385 #[case(101, 100, false)]
386 #[case(100, 100, true)]
387 #[case(99, 100, true)]
388 #[case(-101, -100, true)]
389 #[case(-100, -100, true)]
390 #[case(-99, -100, false)]
391 fn it_should_handle_i64_to_i64_correctly(
392 #[case] l_num: i64,
393 #[case] r_num: i64,
394 #[case] expected: bool,
395 ) {
396 let l = JsonInteger::from(l_num);
397 let r = JsonInteger::from(r_num);
398 assert_eq!(
399 l.le(r),
400 expected,
401 "{l_num} <= {r_num} was expected to be {expected}"
402 );
403 }
404
405 #[rstest]
406 #[case(101, 100, false)]
407 #[case(100, 100, true)]
408 #[case(99, 100, true)]
409 #[case(0, 0, true)]
410 #[case(-0, 0, true)]
411 #[case(-1, 0, true)]
412 fn it_should_handle_i64_to_u64_correctly(
413 #[case] l_num: i64,
414 #[case] r_num: u64,
415 #[case] expected: bool,
416 ) {
417 let l = JsonInteger::from(l_num);
418 let r = JsonInteger::from(r_num);
419 assert_eq!(
420 l.le(r),
421 expected,
422 "{l_num} <= {r_num} was expected to be {expected}"
423 );
424 }
425
426 #[rstest]
427 #[case(101, 100, false)]
428 #[case(100, 100, true)]
429 #[case(99, 100, true)]
430 #[case(0, 0, true)]
431 #[case(0, -0, true)]
432 #[case(0, -1, false)]
433 fn it_should_handle_u64_to_i64_correctly(
434 #[case] l_num: u64,
435 #[case] r_num: i64,
436 #[case] expected: bool,
437 ) {
438 let l = JsonInteger::from(l_num);
439 let r = JsonInteger::from(r_num);
440 assert_eq!(
441 l.le(r),
442 expected,
443 "{l_num} <= {r_num} was expected to be {expected}"
444 );
445 }
446}
447
448#[cfg(test)]
449mod test_gt {
450 use super::*;
451 use rstest::rstest;
452
453 #[rstest]
454 #[case(101, 100, true)]
455 #[case(100, 100, false)]
456 #[case(99, 100, false)]
457 fn it_should_handle_u64_to_u64_correctly(
458 #[case] l_num: u64,
459 #[case] r_num: u64,
460 #[case] expected: bool,
461 ) {
462 let l = JsonInteger::from(l_num);
463 let r = JsonInteger::from(r_num);
464 assert_eq!(
465 l.gt(r),
466 expected,
467 "{l_num} > {r_num} was expected to be {expected}"
468 );
469 }
470
471 #[rstest]
472 #[case(101, 100, true)]
473 #[case(100, 100, false)]
474 #[case(99, 100, false)]
475 #[case(-101, -100, false)]
476 #[case(-100, -100, false)]
477 #[case(-99, -100, true)]
478 fn it_should_handle_i64_to_i64_correctly(
479 #[case] l_num: i64,
480 #[case] r_num: i64,
481 #[case] expected: bool,
482 ) {
483 let l = JsonInteger::from(l_num);
484 let r = JsonInteger::from(r_num);
485 assert_eq!(
486 l.gt(r),
487 expected,
488 "{l_num} > {r_num} was expected to be {expected}"
489 );
490 }
491
492 #[rstest]
493 #[case(101, 100, true)]
494 #[case(100, 100, false)]
495 #[case(99, 100, false)]
496 #[case(0, 0, false)]
497 #[case(-0, 0, false)]
498 #[case(-1, 0, false)]
499 fn it_should_handle_i64_to_u64_correctly(
500 #[case] l_num: i64,
501 #[case] r_num: u64,
502 #[case] expected: bool,
503 ) {
504 let l = JsonInteger::from(l_num);
505 let r = JsonInteger::from(r_num);
506 assert_eq!(
507 l.gt(r),
508 expected,
509 "{l_num} > {r_num} was expected to be {expected}"
510 );
511 }
512
513 #[rstest]
514 #[case(101, 100, true)]
515 #[case(100, 100, false)]
516 #[case(99, 100, false)]
517 #[case(0, 0, false)]
518 #[case(0, -0, false)]
519 #[case(0, -1, true)]
520 fn it_should_handle_u64_to_i64_correctly(
521 #[case] l_num: u64,
522 #[case] r_num: i64,
523 #[case] expected: bool,
524 ) {
525 let l = JsonInteger::from(l_num);
526 let r = JsonInteger::from(r_num);
527 assert_eq!(
528 l.gt(r),
529 expected,
530 "{l_num} > {r_num} was expected to be {expected}"
531 );
532 }
533}
534
535#[cfg(test)]
536mod test_ge {
537 use super::*;
538 use rstest::rstest;
539
540 #[rstest]
541 #[case(101, 100, true)]
542 #[case(100, 100, true)]
543 #[case(99, 100, false)]
544 fn it_should_handle_u64_to_u64_correctly(
545 #[case] l_num: u64,
546 #[case] r_num: u64,
547 #[case] expected: bool,
548 ) {
549 let l = JsonInteger::from(l_num);
550 let r = JsonInteger::from(r_num);
551 assert_eq!(
552 l.ge(r),
553 expected,
554 "{l_num} >= {r_num} was expected to be {expected}"
555 );
556 }
557
558 #[rstest]
559 #[case(101, 100, true)]
560 #[case(100, 100, true)]
561 #[case(99, 100, false)]
562 #[case(-101, -100, false)]
563 #[case(-100, -100, true)]
564 #[case(-99, -100, true)]
565 fn it_should_handle_i64_to_i64_correctly(
566 #[case] l_num: i64,
567 #[case] r_num: i64,
568 #[case] expected: bool,
569 ) {
570 let l = JsonInteger::from(l_num);
571 let r = JsonInteger::from(r_num);
572 assert_eq!(
573 l.ge(r),
574 expected,
575 "{l_num} >= {r_num} was expected to be {expected}"
576 );
577 }
578
579 #[rstest]
580 #[case(101, 100, true)]
581 #[case(100, 100, true)]
582 #[case(99, 100, false)]
583 #[case(0, 0, true)]
584 #[case(-0, 0, true)]
585 #[case(-1, 0, false)]
586 fn it_should_handle_i64_to_u64_correctly(
587 #[case] l_num: i64,
588 #[case] r_num: u64,
589 #[case] expected: bool,
590 ) {
591 let l = JsonInteger::from(l_num);
592 let r = JsonInteger::from(r_num);
593 assert_eq!(
594 l.ge(r),
595 expected,
596 "{l_num} >= {r_num} was expected to be {expected}"
597 );
598 }
599
600 #[rstest]
601 #[case(101, 100, true)]
602 #[case(100, 100, true)]
603 #[case(99, 100, false)]
604 #[case(0, 0, true)]
605 #[case(0, -0, true)]
606 #[case(0, -1, true)]
607 fn it_should_handle_u64_to_i64_correctly(
608 #[case] l_num: u64,
609 #[case] r_num: i64,
610 #[case] expected: bool,
611 ) {
612 let l = JsonInteger::from(l_num);
613 let r = JsonInteger::from(r_num);
614 assert_eq!(
615 l.ge(r),
616 expected,
617 "{l_num} >= {r_num} was expected to be {expected}"
618 );
619 }
620}