1use std::fmt::{Debug, Display};
27
28use rust_decimal::Decimal;
29
30use crate::collections::{MapLike, SetLike};
31
32pub const FAILED: &str = "Condition failed";
38
39#[inline(always)]
45pub fn check_predicate_true(predicate: bool, fail_msg: &str) -> anyhow::Result<()> {
46 if !predicate {
47 anyhow::bail!("{fail_msg}")
48 }
49 Ok(())
50}
51
52#[inline(always)]
58pub fn check_predicate_false(predicate: bool, fail_msg: &str) -> anyhow::Result<()> {
59 if predicate {
60 anyhow::bail!("{fail_msg}")
61 }
62 Ok(())
63}
64
65#[inline(always)]
74pub fn check_nonempty_string<T: AsRef<str>>(s: T, param: &str) -> anyhow::Result<()> {
75 if s.as_ref().is_empty() {
76 anyhow::bail!("invalid string for '{param}', was empty");
77 }
78 Ok(())
79}
80
81#[inline(always)]
90pub fn check_valid_string_ascii<T: AsRef<str>>(s: T, param: &str) -> anyhow::Result<()> {
91 let s = s.as_ref();
92
93 if s.is_empty() {
94 anyhow::bail!("invalid string for '{param}', was empty");
95 }
96
97 let mut has_non_whitespace = false;
99 for c in s.chars() {
100 if !c.is_whitespace() {
101 has_non_whitespace = true;
102 }
103 if !c.is_ascii() {
104 anyhow::bail!("invalid string for '{param}' contained a non-ASCII char, was '{s}'");
105 }
106 }
107
108 if !has_non_whitespace {
109 anyhow::bail!("invalid string for '{param}', was all whitespace");
110 }
111
112 Ok(())
113}
114
115#[inline(always)]
126pub fn check_valid_string_utf8<T: AsRef<str>>(s: T, param: &str) -> anyhow::Result<()> {
127 let s = s.as_ref();
128
129 if s.is_empty() {
130 anyhow::bail!("invalid string for '{param}', was empty");
131 }
132
133 let has_non_whitespace = s.chars().any(|c| !c.is_whitespace());
134
135 if !has_non_whitespace {
136 anyhow::bail!("invalid string for '{param}', was all whitespace");
137 }
138
139 Ok(())
140}
141
142#[inline(always)]
151pub fn check_valid_string_ascii_optional<T: AsRef<str>>(
152 s: Option<T>,
153 param: &str,
154) -> anyhow::Result<()> {
155 if let Some(s) = s {
156 check_valid_string_ascii(s, param)?;
157 }
158 Ok(())
159}
160
161#[inline(always)]
167pub fn check_string_contains<T: AsRef<str>>(s: T, pat: &str, param: &str) -> anyhow::Result<()> {
168 let s = s.as_ref();
169 if !s.contains(pat) {
170 anyhow::bail!("invalid string for '{param}' did not contain '{pat}', was '{s}'")
171 }
172 Ok(())
173}
174
175#[inline(always)]
181pub fn check_equal<T: PartialEq + Debug + Display>(
182 lhs: &T,
183 rhs: &T,
184 lhs_param: &str,
185 rhs_param: &str,
186) -> anyhow::Result<()> {
187 if lhs != rhs {
188 anyhow::bail!("'{lhs_param}' value of {lhs} was not equal to '{rhs_param}' value of {rhs}");
189 }
190 Ok(())
191}
192
193#[inline(always)]
199pub fn check_equal_u8(lhs: u8, rhs: u8, lhs_param: &str, rhs_param: &str) -> anyhow::Result<()> {
200 if lhs != rhs {
201 anyhow::bail!("'{lhs_param}' u8 of {lhs} was not equal to '{rhs_param}' u8 of {rhs}")
202 }
203 Ok(())
204}
205
206#[inline(always)]
212pub fn check_equal_usize(
213 lhs: usize,
214 rhs: usize,
215 lhs_param: &str,
216 rhs_param: &str,
217) -> anyhow::Result<()> {
218 if lhs != rhs {
219 anyhow::bail!("'{lhs_param}' usize of {lhs} was not equal to '{rhs_param}' usize of {rhs}")
220 }
221 Ok(())
222}
223
224#[inline(always)]
230pub fn check_positive_u64(value: u64, param: &str) -> anyhow::Result<()> {
231 if value == 0 {
232 anyhow::bail!("invalid u64 for '{param}' not positive, was {value}")
233 }
234 Ok(())
235}
236
237#[inline(always)]
243pub fn check_positive_u128(value: u128, param: &str) -> anyhow::Result<()> {
244 if value == 0 {
245 anyhow::bail!("invalid u128 for '{param}' not positive, was {value}")
246 }
247 Ok(())
248}
249
250#[inline(always)]
256pub fn check_positive_i64(value: i64, param: &str) -> anyhow::Result<()> {
257 if value <= 0 {
258 anyhow::bail!("invalid i64 for '{param}' not positive, was {value}")
259 }
260 Ok(())
261}
262
263#[inline(always)]
269pub fn check_positive_i128(value: i128, param: &str) -> anyhow::Result<()> {
270 if value <= 0 {
271 anyhow::bail!("invalid i128 for '{param}' not positive, was {value}")
272 }
273 Ok(())
274}
275
276#[inline(always)]
282pub fn check_non_negative_f64(value: f64, param: &str) -> anyhow::Result<()> {
283 if value.is_nan() || value.is_infinite() {
284 anyhow::bail!("invalid f64 for '{param}', was {value}")
285 }
286 if value < 0.0 {
287 anyhow::bail!("invalid f64 for '{param}' negative, was {value}")
288 }
289 Ok(())
290}
291
292#[inline(always)]
298pub fn check_in_range_inclusive_u8(value: u8, l: u8, r: u8, param: &str) -> anyhow::Result<()> {
299 if value < l || value > r {
300 anyhow::bail!("invalid u8 for '{param}' not in range [{l}, {r}], was {value}")
301 }
302 Ok(())
303}
304
305#[inline(always)]
311pub fn check_in_range_inclusive_u64(value: u64, l: u64, r: u64, param: &str) -> anyhow::Result<()> {
312 if value < l || value > r {
313 anyhow::bail!("invalid u64 for '{param}' not in range [{l}, {r}], was {value}")
314 }
315 Ok(())
316}
317
318#[inline(always)]
324pub fn check_in_range_inclusive_i64(value: i64, l: i64, r: i64, param: &str) -> anyhow::Result<()> {
325 if value < l || value > r {
326 anyhow::bail!("invalid i64 for '{param}' not in range [{l}, {r}], was {value}")
327 }
328 Ok(())
329}
330
331#[inline(always)]
337pub fn check_in_range_inclusive_f64(value: f64, l: f64, r: f64, param: &str) -> anyhow::Result<()> {
338 const EPSILON: f64 = 1e-15;
344
345 if value.is_nan() || value.is_infinite() {
346 anyhow::bail!("invalid f64 for '{param}', was {value}")
347 }
348 if value < l - EPSILON || value > r + EPSILON {
349 anyhow::bail!("invalid f64 for '{param}' not in range [{l}, {r}], was {value}")
350 }
351 Ok(())
352}
353
354#[inline(always)]
360pub fn check_in_range_inclusive_usize(
361 value: usize,
362 l: usize,
363 r: usize,
364 param: &str,
365) -> anyhow::Result<()> {
366 if value < l || value > r {
367 anyhow::bail!("invalid usize for '{param}' not in range [{l}, {r}], was {value}")
368 }
369 Ok(())
370}
371
372#[inline(always)]
378pub fn check_slice_empty<T>(slice: &[T], param: &str) -> anyhow::Result<()> {
379 if !slice.is_empty() {
380 anyhow::bail!(
381 "the '{param}' slice `&[{}]` was not empty",
382 std::any::type_name::<T>()
383 )
384 }
385 Ok(())
386}
387
388#[inline(always)]
394pub fn check_slice_not_empty<T>(slice: &[T], param: &str) -> anyhow::Result<()> {
395 if slice.is_empty() {
396 anyhow::bail!(
397 "the '{param}' slice `&[{}]` was empty",
398 std::any::type_name::<T>()
399 )
400 }
401 Ok(())
402}
403
404#[inline(always)]
410pub fn check_map_empty<M>(map: &M, param: &str) -> anyhow::Result<()>
411where
412 M: MapLike,
413{
414 if !map.is_empty() {
415 anyhow::bail!(
416 "the '{param}' map `&<{}, {}>` was not empty",
417 std::any::type_name::<M::Key>(),
418 std::any::type_name::<M::Value>(),
419 );
420 }
421 Ok(())
422}
423
424#[inline(always)]
430pub fn check_map_not_empty<M>(map: &M, param: &str) -> anyhow::Result<()>
431where
432 M: MapLike,
433{
434 if map.is_empty() {
435 anyhow::bail!(
436 "the '{param}' map `&<{}, {}>` was empty",
437 std::any::type_name::<M::Key>(),
438 std::any::type_name::<M::Value>(),
439 );
440 }
441 Ok(())
442}
443
444#[inline(always)]
450pub fn check_key_not_in_map<M>(
451 key: &M::Key,
452 map: &M,
453 key_name: &str,
454 map_name: &str,
455) -> anyhow::Result<()>
456where
457 M: MapLike,
458{
459 if map.contains_key(key) {
460 anyhow::bail!(
461 "the '{key_name}' key {key} was already in the '{map_name}' map `&<{}, {}>`",
462 std::any::type_name::<M::Key>(),
463 std::any::type_name::<M::Value>(),
464 );
465 }
466 Ok(())
467}
468
469#[inline(always)]
475pub fn check_key_in_map<M>(
476 key: &M::Key,
477 map: &M,
478 key_name: &str,
479 map_name: &str,
480) -> anyhow::Result<()>
481where
482 M: MapLike,
483{
484 if !map.contains_key(key) {
485 anyhow::bail!(
486 "the '{key_name}' key {key} was not in the '{map_name}' map `&<{}, {}>`",
487 std::any::type_name::<M::Key>(),
488 std::any::type_name::<M::Value>(),
489 );
490 }
491 Ok(())
492}
493
494#[inline(always)]
500pub fn check_member_not_in_set<S>(
501 member: &S::Item,
502 set: &S,
503 member_name: &str,
504 set_name: &str,
505) -> anyhow::Result<()>
506where
507 S: SetLike,
508{
509 if set.contains(member) {
510 anyhow::bail!(
511 "the '{member_name}' member was already in the '{set_name}' set `&<{}>`",
512 std::any::type_name::<S::Item>(),
513 );
514 }
515 Ok(())
516}
517
518#[inline(always)]
524pub fn check_member_in_set<S>(
525 member: &S::Item,
526 set: &S,
527 member_name: &str,
528 set_name: &str,
529) -> anyhow::Result<()>
530where
531 S: SetLike,
532{
533 if !set.contains(member) {
534 anyhow::bail!(
535 "the '{member_name}' member was not in the '{set_name}' set `&<{}>`",
536 std::any::type_name::<S::Item>(),
537 );
538 }
539 Ok(())
540}
541
542#[inline(always)]
548pub fn check_positive_decimal(value: Decimal, param: &str) -> anyhow::Result<()> {
549 if value <= Decimal::ZERO {
550 anyhow::bail!("invalid Decimal for '{param}' not positive, was {value}")
551 }
552 Ok(())
553}
554
555#[cfg(test)]
559mod tests {
560 use std::{
561 collections::{HashMap, HashSet},
562 fmt::Display,
563 str::FromStr,
564 };
565
566 use rstest::rstest;
567 use rust_decimal::Decimal;
568
569 use super::*;
570
571 #[rstest]
572 #[case(false, false)]
573 #[case(true, true)]
574 fn test_check_predicate_true(#[case] predicate: bool, #[case] expected: bool) {
575 let result = check_predicate_true(predicate, "the predicate was false").is_ok();
576 assert_eq!(result, expected);
577 }
578
579 #[rstest]
580 #[case(false, true)]
581 #[case(true, false)]
582 fn test_check_predicate_false(#[case] predicate: bool, #[case] expected: bool) {
583 let result = check_predicate_false(predicate, "the predicate was true").is_ok();
584 assert_eq!(result, expected);
585 }
586
587 #[rstest]
588 #[case("a")]
589 #[case(" ")] #[case(" ")] #[case("🦀")] #[case(" a")]
593 #[case("a ")]
594 #[case("abc")]
595 fn test_check_nonempty_string_with_valid_values(#[case] s: &str) {
596 assert!(check_nonempty_string(s, "value").is_ok());
597 }
598
599 #[rstest]
600 #[case("")] fn test_check_nonempty_string_with_invalid_values(#[case] s: &str) {
602 assert!(check_nonempty_string(s, "value").is_err());
603 }
604
605 #[rstest]
606 #[case(" a")]
607 #[case("a ")]
608 #[case("a a")]
609 #[case(" a ")]
610 #[case("abc")]
611 fn test_check_valid_string_ascii_with_valid_value(#[case] s: &str) {
612 assert!(check_valid_string_ascii(s, "value").is_ok());
613 }
614
615 #[rstest]
616 #[case("")] #[case(" ")] #[case(" ")] #[case("🦀")] fn test_check_valid_string_ascii_with_invalid_values(#[case] s: &str) {
621 assert!(check_valid_string_ascii(s, "value").is_err());
622 }
623
624 #[rstest]
625 #[case(" a")]
626 #[case("a ")]
627 #[case("abc")]
628 #[case("ETHUSDT")]
629 fn test_check_valid_string_utf8_with_valid_values(#[case] s: &str) {
630 assert!(check_valid_string_utf8(s, "value").is_ok());
631 }
632
633 #[rstest]
634 #[case("")] #[case(" ")] #[case(" ")] fn test_check_valid_string_utf8_with_invalid_values(#[case] s: &str) {
638 assert!(check_valid_string_utf8(s, "value").is_err());
639 }
640
641 #[rstest]
642 #[case(None)]
643 #[case(Some(" a"))]
644 #[case(Some("a "))]
645 #[case(Some("a a"))]
646 #[case(Some(" a "))]
647 #[case(Some("abc"))]
648 fn test_check_valid_string_ascii_optional_with_valid_value(#[case] s: Option<&str>) {
649 assert!(check_valid_string_ascii_optional(s, "value").is_ok());
650 }
651
652 #[rstest]
653 #[case("a", "a")]
654 fn test_check_string_contains_when_does_contain(#[case] s: &str, #[case] pat: &str) {
655 assert!(check_string_contains(s, pat, "value").is_ok());
656 }
657
658 #[rstest]
659 #[case("a", "b")]
660 fn test_check_string_contains_when_does_not_contain(#[case] s: &str, #[case] pat: &str) {
661 assert!(check_string_contains(s, pat, "value").is_err());
662 }
663
664 #[rstest]
665 #[case(0u8, 0u8, "left", "right", true)]
666 #[case(1u8, 1u8, "left", "right", true)]
667 #[case(0u8, 1u8, "left", "right", false)]
668 #[case(1u8, 0u8, "left", "right", false)]
669 #[case(10i32, 10i32, "left", "right", true)]
670 #[case(10i32, 20i32, "left", "right", false)]
671 #[case("hello", "hello", "left", "right", true)]
672 #[case("hello", "world", "left", "right", false)]
673 fn test_check_equal<T: PartialEq + Debug + Display>(
674 #[case] lhs: T,
675 #[case] rhs: T,
676 #[case] lhs_param: &str,
677 #[case] rhs_param: &str,
678 #[case] expected: bool,
679 ) {
680 let result = check_equal(&lhs, &rhs, lhs_param, rhs_param).is_ok();
681 assert_eq!(result, expected);
682 }
683
684 #[rstest]
685 #[case(0, 0, "left", "right", true)]
686 #[case(1, 1, "left", "right", true)]
687 #[case(0, 1, "left", "right", false)]
688 #[case(1, 0, "left", "right", false)]
689 fn test_check_equal_u8_when_equal(
690 #[case] lhs: u8,
691 #[case] rhs: u8,
692 #[case] lhs_param: &str,
693 #[case] rhs_param: &str,
694 #[case] expected: bool,
695 ) {
696 let result = check_equal_u8(lhs, rhs, lhs_param, rhs_param).is_ok();
697 assert_eq!(result, expected);
698 }
699
700 #[rstest]
701 #[case(0, 0, "left", "right", true)]
702 #[case(1, 1, "left", "right", true)]
703 #[case(0, 1, "left", "right", false)]
704 #[case(1, 0, "left", "right", false)]
705 fn test_check_equal_usize_when_equal(
706 #[case] lhs: usize,
707 #[case] rhs: usize,
708 #[case] lhs_param: &str,
709 #[case] rhs_param: &str,
710 #[case] expected: bool,
711 ) {
712 let result = check_equal_usize(lhs, rhs, lhs_param, rhs_param).is_ok();
713 assert_eq!(result, expected);
714 }
715
716 #[rstest]
717 #[case(1, "value")]
718 fn test_check_positive_u64_when_positive(#[case] value: u64, #[case] param: &str) {
719 assert!(check_positive_u64(value, param).is_ok());
720 }
721
722 #[rstest]
723 #[case(0, "value")]
724 fn test_check_positive_u64_when_not_positive(#[case] value: u64, #[case] param: &str) {
725 assert!(check_positive_u64(value, param).is_err());
726 }
727
728 #[rstest]
729 #[case(1, "value")]
730 fn test_check_positive_i64_when_positive(#[case] value: i64, #[case] param: &str) {
731 assert!(check_positive_i64(value, param).is_ok());
732 }
733
734 #[rstest]
735 #[case(0, "value")]
736 #[case(-1, "value")]
737 fn test_check_positive_i64_when_not_positive(#[case] value: i64, #[case] param: &str) {
738 assert!(check_positive_i64(value, param).is_err());
739 }
740
741 #[rstest]
742 #[case(0.0, "value")]
743 #[case(1.0, "value")]
744 fn test_check_non_negative_f64_when_not_negative(#[case] value: f64, #[case] param: &str) {
745 assert!(check_non_negative_f64(value, param).is_ok());
746 }
747
748 #[rstest]
749 #[case(f64::NAN, "value")]
750 #[case(f64::INFINITY, "value")]
751 #[case(f64::NEG_INFINITY, "value")]
752 #[case(-0.1, "value")]
753 fn test_check_non_negative_f64_when_negative(#[case] value: f64, #[case] param: &str) {
754 assert!(check_non_negative_f64(value, param).is_err());
755 }
756
757 #[rstest]
758 #[case(0, 0, 0, "value")]
759 #[case(0, 0, 1, "value")]
760 #[case(1, 0, 1, "value")]
761 fn test_check_in_range_inclusive_u8_when_in_range(
762 #[case] value: u8,
763 #[case] l: u8,
764 #[case] r: u8,
765 #[case] desc: &str,
766 ) {
767 assert!(check_in_range_inclusive_u8(value, l, r, desc).is_ok());
768 }
769
770 #[rstest]
771 #[case(0, 1, 2, "value")]
772 #[case(3, 1, 2, "value")]
773 fn test_check_in_range_inclusive_u8_when_out_of_range(
774 #[case] value: u8,
775 #[case] l: u8,
776 #[case] r: u8,
777 #[case] param: &str,
778 ) {
779 assert!(check_in_range_inclusive_u8(value, l, r, param).is_err());
780 }
781
782 #[rstest]
783 #[case(0, 0, 0, "value")]
784 #[case(0, 0, 1, "value")]
785 #[case(1, 0, 1, "value")]
786 fn test_check_in_range_inclusive_u64_when_in_range(
787 #[case] value: u64,
788 #[case] l: u64,
789 #[case] r: u64,
790 #[case] param: &str,
791 ) {
792 assert!(check_in_range_inclusive_u64(value, l, r, param).is_ok());
793 }
794
795 #[rstest]
796 #[case(0, 1, 2, "value")]
797 #[case(3, 1, 2, "value")]
798 fn test_check_in_range_inclusive_u64_when_out_of_range(
799 #[case] value: u64,
800 #[case] l: u64,
801 #[case] r: u64,
802 #[case] param: &str,
803 ) {
804 assert!(check_in_range_inclusive_u64(value, l, r, param).is_err());
805 }
806
807 #[rstest]
808 #[case(0, 0, 0, "value")]
809 #[case(0, 0, 1, "value")]
810 #[case(1, 0, 1, "value")]
811 fn test_check_in_range_inclusive_i64_when_in_range(
812 #[case] value: i64,
813 #[case] l: i64,
814 #[case] r: i64,
815 #[case] param: &str,
816 ) {
817 assert!(check_in_range_inclusive_i64(value, l, r, param).is_ok());
818 }
819
820 #[rstest]
821 #[case(0.0, 0.0, 0.0, "value")]
822 #[case(0.0, 0.0, 1.0, "value")]
823 #[case(1.0, 0.0, 1.0, "value")]
824 fn test_check_in_range_inclusive_f64_when_in_range(
825 #[case] value: f64,
826 #[case] l: f64,
827 #[case] r: f64,
828 #[case] param: &str,
829 ) {
830 assert!(check_in_range_inclusive_f64(value, l, r, param).is_ok());
831 }
832
833 #[rstest]
834 #[case(-1e16, 0.0, 0.0, "value")]
835 #[case(1.0 + 1e16, 0.0, 1.0, "value")]
836 fn test_check_in_range_inclusive_f64_when_out_of_range(
837 #[case] value: f64,
838 #[case] l: f64,
839 #[case] r: f64,
840 #[case] param: &str,
841 ) {
842 assert!(check_in_range_inclusive_f64(value, l, r, param).is_err());
843 }
844
845 #[rstest]
846 #[case(0, 1, 2, "value")]
847 #[case(3, 1, 2, "value")]
848 fn test_check_in_range_inclusive_i64_when_out_of_range(
849 #[case] value: i64,
850 #[case] l: i64,
851 #[case] r: i64,
852 #[case] param: &str,
853 ) {
854 assert!(check_in_range_inclusive_i64(value, l, r, param).is_err());
855 }
856
857 #[rstest]
858 #[case(0, 0, 0, "value")]
859 #[case(0, 0, 1, "value")]
860 #[case(1, 0, 1, "value")]
861 fn test_check_in_range_inclusive_usize_when_in_range(
862 #[case] value: usize,
863 #[case] l: usize,
864 #[case] r: usize,
865 #[case] param: &str,
866 ) {
867 assert!(check_in_range_inclusive_usize(value, l, r, param).is_ok());
868 }
869
870 #[rstest]
871 #[case(0, 1, 2, "value")]
872 #[case(3, 1, 2, "value")]
873 fn test_check_in_range_inclusive_usize_when_out_of_range(
874 #[case] value: usize,
875 #[case] l: usize,
876 #[case] r: usize,
877 #[case] param: &str,
878 ) {
879 assert!(check_in_range_inclusive_usize(value, l, r, param).is_err());
880 }
881
882 #[rstest]
883 #[case(vec![], true)]
884 #[case(vec![1_u8], false)]
885 fn test_check_slice_empty(#[case] collection: Vec<u8>, #[case] expected: bool) {
886 let result = check_slice_empty(collection.as_slice(), "param").is_ok();
887 assert_eq!(result, expected);
888 }
889
890 #[rstest]
891 #[case(vec![], false)]
892 #[case(vec![1_u8], true)]
893 fn test_check_slice_not_empty(#[case] collection: Vec<u8>, #[case] expected: bool) {
894 let result = check_slice_not_empty(collection.as_slice(), "param").is_ok();
895 assert_eq!(result, expected);
896 }
897
898 #[rstest]
899 #[case(HashMap::new(), true)]
900 #[case(HashMap::from([("A".to_string(), 1_u8)]), false)]
901 fn test_check_map_empty(#[case] map: HashMap<String, u8>, #[case] expected: bool) {
902 let result = check_map_empty(&map, "param").is_ok();
903 assert_eq!(result, expected);
904 }
905
906 #[rstest]
907 #[case(HashMap::new(), false)]
908 #[case(HashMap::from([("A".to_string(), 1_u8)]), true)]
909 fn test_check_map_not_empty(#[case] map: HashMap<String, u8>, #[case] expected: bool) {
910 let result = check_map_not_empty(&map, "param").is_ok();
911 assert_eq!(result, expected);
912 }
913
914 #[rstest]
915 #[case(&HashMap::<u32, u32>::new(), 5, "key", "map", true)] #[case(&HashMap::from([(1, 10), (2, 20)]), 1, "key", "map", false)] #[case(&HashMap::from([(1, 10), (2, 20)]), 5, "key", "map", true)] fn test_check_key_not_in_map(
919 #[case] map: &HashMap<u32, u32>,
920 #[case] key: u32,
921 #[case] key_name: &str,
922 #[case] map_name: &str,
923 #[case] expected: bool,
924 ) {
925 let result = check_key_not_in_map(&key, map, key_name, map_name).is_ok();
926 assert_eq!(result, expected);
927 }
928
929 #[rstest]
930 #[case(&HashMap::<u32, u32>::new(), 5, "key", "map", false)] #[case(&HashMap::from([(1, 10), (2, 20)]), 1, "key", "map", true)] #[case(&HashMap::from([(1, 10), (2, 20)]), 5, "key", "map", false)] fn test_check_key_in_map(
934 #[case] map: &HashMap<u32, u32>,
935 #[case] key: u32,
936 #[case] key_name: &str,
937 #[case] map_name: &str,
938 #[case] expected: bool,
939 ) {
940 let result = check_key_in_map(&key, map, key_name, map_name).is_ok();
941 assert_eq!(result, expected);
942 }
943
944 #[rstest]
945 #[case(&HashSet::<u32>::new(), 5, "member", "set", true)] #[case(&HashSet::from([1, 2]), 1, "member", "set", false)] #[case(&HashSet::from([1, 2]), 5, "member", "set", true)] fn test_check_member_not_in_set(
949 #[case] set: &HashSet<u32>,
950 #[case] member: u32,
951 #[case] member_name: &str,
952 #[case] set_name: &str,
953 #[case] expected: bool,
954 ) {
955 let result = check_member_not_in_set(&member, set, member_name, set_name).is_ok();
956 assert_eq!(result, expected);
957 }
958
959 #[rstest]
960 #[case(&HashSet::<u32>::new(), 5, "member", "set", false)] #[case(&HashSet::from([1, 2]), 1, "member", "set", true)] #[case(&HashSet::from([1, 2]), 5, "member", "set", false)] fn test_check_member_in_set(
964 #[case] set: &HashSet<u32>,
965 #[case] member: u32,
966 #[case] member_name: &str,
967 #[case] set_name: &str,
968 #[case] expected: bool,
969 ) {
970 let result = check_member_in_set(&member, set, member_name, set_name).is_ok();
971 assert_eq!(result, expected);
972 }
973
974 #[rstest]
975 #[case("1", true)] #[case("0.0000000000000000000000000001", true)] #[case("79228162514264337593543950335", true)] #[case("0", false)] #[case("-0.0000000000000000000000000001", false)] #[case("-1", false)] fn test_check_positive_decimal(#[case] raw: &str, #[case] expected: bool) {
982 let value = Decimal::from_str(raw).expect("valid decimal literal");
983 let result = super::check_positive_decimal(value, "param").is_ok();
984 assert_eq!(result, expected);
985 }
986}