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)]
556mod tests {
557 use std::{
558 collections::{HashMap, HashSet},
559 fmt::Display,
560 str::FromStr,
561 };
562
563 use rstest::rstest;
564 use rust_decimal::Decimal;
565
566 use super::*;
567
568 #[rstest]
569 #[case(false, false)]
570 #[case(true, true)]
571 fn test_check_predicate_true(#[case] predicate: bool, #[case] expected: bool) {
572 let result = check_predicate_true(predicate, "the predicate was false").is_ok();
573 assert_eq!(result, expected);
574 }
575
576 #[rstest]
577 #[case(false, true)]
578 #[case(true, false)]
579 fn test_check_predicate_false(#[case] predicate: bool, #[case] expected: bool) {
580 let result = check_predicate_false(predicate, "the predicate was true").is_ok();
581 assert_eq!(result, expected);
582 }
583
584 #[rstest]
585 #[case("a")]
586 #[case(" ")] #[case(" ")] #[case("🦀")] #[case(" a")]
590 #[case("a ")]
591 #[case("abc")]
592 fn test_check_nonempty_string_with_valid_values(#[case] s: &str) {
593 assert!(check_nonempty_string(s, "value").is_ok());
594 }
595
596 #[rstest]
597 #[case("")] fn test_check_nonempty_string_with_invalid_values(#[case] s: &str) {
599 assert!(check_nonempty_string(s, "value").is_err());
600 }
601
602 #[rstest]
603 #[case(" a")]
604 #[case("a ")]
605 #[case("a a")]
606 #[case(" a ")]
607 #[case("abc")]
608 fn test_check_valid_string_ascii_with_valid_value(#[case] s: &str) {
609 assert!(check_valid_string_ascii(s, "value").is_ok());
610 }
611
612 #[rstest]
613 #[case("")] #[case(" ")] #[case(" ")] #[case("🦀")] fn test_check_valid_string_ascii_with_invalid_values(#[case] s: &str) {
618 assert!(check_valid_string_ascii(s, "value").is_err());
619 }
620
621 #[rstest]
622 #[case(" a")]
623 #[case("a ")]
624 #[case("abc")]
625 #[case("ETHUSDT")]
626 fn test_check_valid_string_utf8_with_valid_values(#[case] s: &str) {
627 assert!(check_valid_string_utf8(s, "value").is_ok());
628 }
629
630 #[rstest]
631 #[case("")] #[case(" ")] #[case(" ")] fn test_check_valid_string_utf8_with_invalid_values(#[case] s: &str) {
635 assert!(check_valid_string_utf8(s, "value").is_err());
636 }
637
638 #[rstest]
639 #[case(None)]
640 #[case(Some(" a"))]
641 #[case(Some("a "))]
642 #[case(Some("a a"))]
643 #[case(Some(" a "))]
644 #[case(Some("abc"))]
645 fn test_check_valid_string_ascii_optional_with_valid_value(#[case] s: Option<&str>) {
646 assert!(check_valid_string_ascii_optional(s, "value").is_ok());
647 }
648
649 #[rstest]
650 #[case("a", "a")]
651 fn test_check_string_contains_when_does_contain(#[case] s: &str, #[case] pat: &str) {
652 assert!(check_string_contains(s, pat, "value").is_ok());
653 }
654
655 #[rstest]
656 #[case("a", "b")]
657 fn test_check_string_contains_when_does_not_contain(#[case] s: &str, #[case] pat: &str) {
658 assert!(check_string_contains(s, pat, "value").is_err());
659 }
660
661 #[rstest]
662 #[case(0u8, 0u8, "left", "right", true)]
663 #[case(1u8, 1u8, "left", "right", true)]
664 #[case(0u8, 1u8, "left", "right", false)]
665 #[case(1u8, 0u8, "left", "right", false)]
666 #[case(10i32, 10i32, "left", "right", true)]
667 #[case(10i32, 20i32, "left", "right", false)]
668 #[case("hello", "hello", "left", "right", true)]
669 #[case("hello", "world", "left", "right", false)]
670 fn test_check_equal<T: PartialEq + Debug + Display>(
671 #[case] lhs: T,
672 #[case] rhs: T,
673 #[case] lhs_param: &str,
674 #[case] rhs_param: &str,
675 #[case] expected: bool,
676 ) {
677 let result = check_equal(&lhs, &rhs, lhs_param, rhs_param).is_ok();
678 assert_eq!(result, expected);
679 }
680
681 #[rstest]
682 #[case(0, 0, "left", "right", true)]
683 #[case(1, 1, "left", "right", true)]
684 #[case(0, 1, "left", "right", false)]
685 #[case(1, 0, "left", "right", false)]
686 fn test_check_equal_u8_when_equal(
687 #[case] lhs: u8,
688 #[case] rhs: u8,
689 #[case] lhs_param: &str,
690 #[case] rhs_param: &str,
691 #[case] expected: bool,
692 ) {
693 let result = check_equal_u8(lhs, rhs, lhs_param, rhs_param).is_ok();
694 assert_eq!(result, expected);
695 }
696
697 #[rstest]
698 #[case(0, 0, "left", "right", true)]
699 #[case(1, 1, "left", "right", true)]
700 #[case(0, 1, "left", "right", false)]
701 #[case(1, 0, "left", "right", false)]
702 fn test_check_equal_usize_when_equal(
703 #[case] lhs: usize,
704 #[case] rhs: usize,
705 #[case] lhs_param: &str,
706 #[case] rhs_param: &str,
707 #[case] expected: bool,
708 ) {
709 let result = check_equal_usize(lhs, rhs, lhs_param, rhs_param).is_ok();
710 assert_eq!(result, expected);
711 }
712
713 #[rstest]
714 #[case(1, "value")]
715 fn test_check_positive_u64_when_positive(#[case] value: u64, #[case] param: &str) {
716 assert!(check_positive_u64(value, param).is_ok());
717 }
718
719 #[rstest]
720 #[case(0, "value")]
721 fn test_check_positive_u64_when_not_positive(#[case] value: u64, #[case] param: &str) {
722 assert!(check_positive_u64(value, param).is_err());
723 }
724
725 #[rstest]
726 #[case(1, "value")]
727 fn test_check_positive_i64_when_positive(#[case] value: i64, #[case] param: &str) {
728 assert!(check_positive_i64(value, param).is_ok());
729 }
730
731 #[rstest]
732 #[case(0, "value")]
733 #[case(-1, "value")]
734 fn test_check_positive_i64_when_not_positive(#[case] value: i64, #[case] param: &str) {
735 assert!(check_positive_i64(value, param).is_err());
736 }
737
738 #[rstest]
739 #[case(0.0, "value")]
740 #[case(1.0, "value")]
741 fn test_check_non_negative_f64_when_not_negative(#[case] value: f64, #[case] param: &str) {
742 assert!(check_non_negative_f64(value, param).is_ok());
743 }
744
745 #[rstest]
746 #[case(f64::NAN, "value")]
747 #[case(f64::INFINITY, "value")]
748 #[case(f64::NEG_INFINITY, "value")]
749 #[case(-0.1, "value")]
750 fn test_check_non_negative_f64_when_negative(#[case] value: f64, #[case] param: &str) {
751 assert!(check_non_negative_f64(value, param).is_err());
752 }
753
754 #[rstest]
755 #[case(0, 0, 0, "value")]
756 #[case(0, 0, 1, "value")]
757 #[case(1, 0, 1, "value")]
758 fn test_check_in_range_inclusive_u8_when_in_range(
759 #[case] value: u8,
760 #[case] l: u8,
761 #[case] r: u8,
762 #[case] desc: &str,
763 ) {
764 assert!(check_in_range_inclusive_u8(value, l, r, desc).is_ok());
765 }
766
767 #[rstest]
768 #[case(0, 1, 2, "value")]
769 #[case(3, 1, 2, "value")]
770 fn test_check_in_range_inclusive_u8_when_out_of_range(
771 #[case] value: u8,
772 #[case] l: u8,
773 #[case] r: u8,
774 #[case] param: &str,
775 ) {
776 assert!(check_in_range_inclusive_u8(value, l, r, param).is_err());
777 }
778
779 #[rstest]
780 #[case(0, 0, 0, "value")]
781 #[case(0, 0, 1, "value")]
782 #[case(1, 0, 1, "value")]
783 fn test_check_in_range_inclusive_u64_when_in_range(
784 #[case] value: u64,
785 #[case] l: u64,
786 #[case] r: u64,
787 #[case] param: &str,
788 ) {
789 assert!(check_in_range_inclusive_u64(value, l, r, param).is_ok());
790 }
791
792 #[rstest]
793 #[case(0, 1, 2, "value")]
794 #[case(3, 1, 2, "value")]
795 fn test_check_in_range_inclusive_u64_when_out_of_range(
796 #[case] value: u64,
797 #[case] l: u64,
798 #[case] r: u64,
799 #[case] param: &str,
800 ) {
801 assert!(check_in_range_inclusive_u64(value, l, r, param).is_err());
802 }
803
804 #[rstest]
805 #[case(0, 0, 0, "value")]
806 #[case(0, 0, 1, "value")]
807 #[case(1, 0, 1, "value")]
808 fn test_check_in_range_inclusive_i64_when_in_range(
809 #[case] value: i64,
810 #[case] l: i64,
811 #[case] r: i64,
812 #[case] param: &str,
813 ) {
814 assert!(check_in_range_inclusive_i64(value, l, r, param).is_ok());
815 }
816
817 #[rstest]
818 #[case(0.0, 0.0, 0.0, "value")]
819 #[case(0.0, 0.0, 1.0, "value")]
820 #[case(1.0, 0.0, 1.0, "value")]
821 fn test_check_in_range_inclusive_f64_when_in_range(
822 #[case] value: f64,
823 #[case] l: f64,
824 #[case] r: f64,
825 #[case] param: &str,
826 ) {
827 assert!(check_in_range_inclusive_f64(value, l, r, param).is_ok());
828 }
829
830 #[rstest]
831 #[case(-1e16, 0.0, 0.0, "value")]
832 #[case(1.0 + 1e16, 0.0, 1.0, "value")]
833 fn test_check_in_range_inclusive_f64_when_out_of_range(
834 #[case] value: f64,
835 #[case] l: f64,
836 #[case] r: f64,
837 #[case] param: &str,
838 ) {
839 assert!(check_in_range_inclusive_f64(value, l, r, param).is_err());
840 }
841
842 #[rstest]
843 #[case(0, 1, 2, "value")]
844 #[case(3, 1, 2, "value")]
845 fn test_check_in_range_inclusive_i64_when_out_of_range(
846 #[case] value: i64,
847 #[case] l: i64,
848 #[case] r: i64,
849 #[case] param: &str,
850 ) {
851 assert!(check_in_range_inclusive_i64(value, l, r, param).is_err());
852 }
853
854 #[rstest]
855 #[case(0, 0, 0, "value")]
856 #[case(0, 0, 1, "value")]
857 #[case(1, 0, 1, "value")]
858 fn test_check_in_range_inclusive_usize_when_in_range(
859 #[case] value: usize,
860 #[case] l: usize,
861 #[case] r: usize,
862 #[case] param: &str,
863 ) {
864 assert!(check_in_range_inclusive_usize(value, l, r, param).is_ok());
865 }
866
867 #[rstest]
868 #[case(0, 1, 2, "value")]
869 #[case(3, 1, 2, "value")]
870 fn test_check_in_range_inclusive_usize_when_out_of_range(
871 #[case] value: usize,
872 #[case] l: usize,
873 #[case] r: usize,
874 #[case] param: &str,
875 ) {
876 assert!(check_in_range_inclusive_usize(value, l, r, param).is_err());
877 }
878
879 #[rstest]
880 #[case(vec![], true)]
881 #[case(vec![1_u8], false)]
882 fn test_check_slice_empty(#[case] collection: Vec<u8>, #[case] expected: bool) {
883 let result = check_slice_empty(collection.as_slice(), "param").is_ok();
884 assert_eq!(result, expected);
885 }
886
887 #[rstest]
888 #[case(vec![], false)]
889 #[case(vec![1_u8], true)]
890 fn test_check_slice_not_empty(#[case] collection: Vec<u8>, #[case] expected: bool) {
891 let result = check_slice_not_empty(collection.as_slice(), "param").is_ok();
892 assert_eq!(result, expected);
893 }
894
895 #[rstest]
896 #[case(HashMap::new(), true)]
897 #[case(HashMap::from([("A".to_string(), 1_u8)]), false)]
898 fn test_check_map_empty(#[case] map: HashMap<String, u8>, #[case] expected: bool) {
899 let result = check_map_empty(&map, "param").is_ok();
900 assert_eq!(result, expected);
901 }
902
903 #[rstest]
904 #[case(HashMap::new(), false)]
905 #[case(HashMap::from([("A".to_string(), 1_u8)]), true)]
906 fn test_check_map_not_empty(#[case] map: HashMap<String, u8>, #[case] expected: bool) {
907 let result = check_map_not_empty(&map, "param").is_ok();
908 assert_eq!(result, expected);
909 }
910
911 #[rstest]
912 #[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(
916 #[case] map: &HashMap<u32, u32>,
917 #[case] key: u32,
918 #[case] key_name: &str,
919 #[case] map_name: &str,
920 #[case] expected: bool,
921 ) {
922 let result = check_key_not_in_map(&key, map, key_name, map_name).is_ok();
923 assert_eq!(result, expected);
924 }
925
926 #[rstest]
927 #[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(
931 #[case] map: &HashMap<u32, u32>,
932 #[case] key: u32,
933 #[case] key_name: &str,
934 #[case] map_name: &str,
935 #[case] expected: bool,
936 ) {
937 let result = check_key_in_map(&key, map, key_name, map_name).is_ok();
938 assert_eq!(result, expected);
939 }
940
941 #[rstest]
942 #[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(
946 #[case] set: &HashSet<u32>,
947 #[case] member: u32,
948 #[case] member_name: &str,
949 #[case] set_name: &str,
950 #[case] expected: bool,
951 ) {
952 let result = check_member_not_in_set(&member, set, member_name, set_name).is_ok();
953 assert_eq!(result, expected);
954 }
955
956 #[rstest]
957 #[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(
961 #[case] set: &HashSet<u32>,
962 #[case] member: u32,
963 #[case] member_name: &str,
964 #[case] set_name: &str,
965 #[case] expected: bool,
966 ) {
967 let result = check_member_in_set(&member, set, member_name, set_name).is_ok();
968 assert_eq!(result, expected);
969 }
970
971 #[rstest]
972 #[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) {
979 let value = Decimal::from_str(raw).expect("valid decimal literal");
980 let result = super::check_positive_decimal(value, "param").is_ok();
981 assert_eq!(result, expected);
982 }
983}