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<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)]
124pub fn check_valid_string_optional<T: AsRef<str>>(s: Option<T>, param: &str) -> anyhow::Result<()> {
125 if let Some(s) = s {
126 check_valid_string(s, param)?;
127 }
128 Ok(())
129}
130
131#[inline(always)]
137pub fn check_string_contains<T: AsRef<str>>(s: T, pat: &str, param: &str) -> anyhow::Result<()> {
138 let s = s.as_ref();
139 if !s.contains(pat) {
140 anyhow::bail!("invalid string for '{param}' did not contain '{pat}', was '{s}'")
141 }
142 Ok(())
143}
144
145#[inline(always)]
151pub fn check_equal<T: PartialEq + Debug + Display>(
152 lhs: &T,
153 rhs: &T,
154 lhs_param: &str,
155 rhs_param: &str,
156) -> anyhow::Result<()> {
157 if lhs != rhs {
158 anyhow::bail!("'{lhs_param}' value of {lhs} was not equal to '{rhs_param}' value of {rhs}");
159 }
160 Ok(())
161}
162
163#[inline(always)]
169pub fn check_equal_u8(lhs: u8, rhs: u8, lhs_param: &str, rhs_param: &str) -> anyhow::Result<()> {
170 if lhs != rhs {
171 anyhow::bail!("'{lhs_param}' u8 of {lhs} was not equal to '{rhs_param}' u8 of {rhs}")
172 }
173 Ok(())
174}
175
176#[inline(always)]
182pub fn check_equal_usize(
183 lhs: usize,
184 rhs: usize,
185 lhs_param: &str,
186 rhs_param: &str,
187) -> anyhow::Result<()> {
188 if lhs != rhs {
189 anyhow::bail!("'{lhs_param}' usize of {lhs} was not equal to '{rhs_param}' usize of {rhs}")
190 }
191 Ok(())
192}
193
194#[inline(always)]
200pub fn check_positive_u64(value: u64, param: &str) -> anyhow::Result<()> {
201 if value == 0 {
202 anyhow::bail!("invalid u64 for '{param}' not positive, was {value}")
203 }
204 Ok(())
205}
206
207#[inline(always)]
213pub fn check_positive_u128(value: u128, param: &str) -> anyhow::Result<()> {
214 if value == 0 {
215 anyhow::bail!("invalid u128 for '{param}' not positive, was {value}")
216 }
217 Ok(())
218}
219
220#[inline(always)]
226pub fn check_positive_i64(value: i64, param: &str) -> anyhow::Result<()> {
227 if value <= 0 {
228 anyhow::bail!("invalid i64 for '{param}' not positive, was {value}")
229 }
230 Ok(())
231}
232
233#[inline(always)]
239pub fn check_positive_i128(value: i128, param: &str) -> anyhow::Result<()> {
240 if value <= 0 {
241 anyhow::bail!("invalid i128 for '{param}' not positive, was {value}")
242 }
243 Ok(())
244}
245
246#[inline(always)]
252pub fn check_non_negative_f64(value: f64, param: &str) -> anyhow::Result<()> {
253 if value.is_nan() || value.is_infinite() {
254 anyhow::bail!("invalid f64 for '{param}', was {value}")
255 }
256 if value < 0.0 {
257 anyhow::bail!("invalid f64 for '{param}' negative, was {value}")
258 }
259 Ok(())
260}
261
262#[inline(always)]
268pub fn check_in_range_inclusive_u8(value: u8, l: u8, r: u8, param: &str) -> anyhow::Result<()> {
269 if value < l || value > r {
270 anyhow::bail!("invalid u8 for '{param}' not in range [{l}, {r}], was {value}")
271 }
272 Ok(())
273}
274
275#[inline(always)]
281pub fn check_in_range_inclusive_u64(value: u64, l: u64, r: u64, param: &str) -> anyhow::Result<()> {
282 if value < l || value > r {
283 anyhow::bail!("invalid u64 for '{param}' not in range [{l}, {r}], was {value}")
284 }
285 Ok(())
286}
287
288#[inline(always)]
294pub fn check_in_range_inclusive_i64(value: i64, l: i64, r: i64, param: &str) -> anyhow::Result<()> {
295 if value < l || value > r {
296 anyhow::bail!("invalid i64 for '{param}' not in range [{l}, {r}], was {value}")
297 }
298 Ok(())
299}
300
301#[inline(always)]
307pub fn check_in_range_inclusive_f64(value: f64, l: f64, r: f64, param: &str) -> anyhow::Result<()> {
308 const EPSILON: f64 = 1e-15;
314
315 if value.is_nan() || value.is_infinite() {
316 anyhow::bail!("invalid f64 for '{param}', was {value}")
317 }
318 if value < l - EPSILON || value > r + EPSILON {
319 anyhow::bail!("invalid f64 for '{param}' not in range [{l}, {r}], was {value}")
320 }
321 Ok(())
322}
323
324#[inline(always)]
330pub fn check_in_range_inclusive_usize(
331 value: usize,
332 l: usize,
333 r: usize,
334 param: &str,
335) -> anyhow::Result<()> {
336 if value < l || value > r {
337 anyhow::bail!("invalid usize for '{param}' not in range [{l}, {r}], was {value}")
338 }
339 Ok(())
340}
341
342#[inline(always)]
348pub fn check_slice_empty<T>(slice: &[T], param: &str) -> anyhow::Result<()> {
349 if !slice.is_empty() {
350 anyhow::bail!(
351 "the '{param}' slice `&[{}]` was not empty",
352 std::any::type_name::<T>()
353 )
354 }
355 Ok(())
356}
357
358#[inline(always)]
364pub fn check_slice_not_empty<T>(slice: &[T], param: &str) -> anyhow::Result<()> {
365 if slice.is_empty() {
366 anyhow::bail!(
367 "the '{param}' slice `&[{}]` was empty",
368 std::any::type_name::<T>()
369 )
370 }
371 Ok(())
372}
373
374#[inline(always)]
380pub fn check_map_empty<M>(map: &M, param: &str) -> anyhow::Result<()>
381where
382 M: MapLike,
383{
384 if !map.is_empty() {
385 anyhow::bail!(
386 "the '{param}' map `&<{}, {}>` was not empty",
387 std::any::type_name::<M::Key>(),
388 std::any::type_name::<M::Value>(),
389 );
390 }
391 Ok(())
392}
393
394#[inline(always)]
400pub fn check_map_not_empty<M>(map: &M, param: &str) -> anyhow::Result<()>
401where
402 M: MapLike,
403{
404 if map.is_empty() {
405 anyhow::bail!(
406 "the '{param}' map `&<{}, {}>` was empty",
407 std::any::type_name::<M::Key>(),
408 std::any::type_name::<M::Value>(),
409 );
410 }
411 Ok(())
412}
413
414#[inline(always)]
420pub fn check_key_not_in_map<M>(
421 key: &M::Key,
422 map: &M,
423 key_name: &str,
424 map_name: &str,
425) -> anyhow::Result<()>
426where
427 M: MapLike,
428{
429 if map.contains_key(key) {
430 anyhow::bail!(
431 "the '{key_name}' key {key} was already in the '{map_name}' map `&<{}, {}>`",
432 std::any::type_name::<M::Key>(),
433 std::any::type_name::<M::Value>(),
434 );
435 }
436 Ok(())
437}
438
439#[inline(always)]
445pub fn check_key_in_map<M>(
446 key: &M::Key,
447 map: &M,
448 key_name: &str,
449 map_name: &str,
450) -> anyhow::Result<()>
451where
452 M: MapLike,
453{
454 if !map.contains_key(key) {
455 anyhow::bail!(
456 "the '{key_name}' key {key} was not in the '{map_name}' map `&<{}, {}>`",
457 std::any::type_name::<M::Key>(),
458 std::any::type_name::<M::Value>(),
459 );
460 }
461 Ok(())
462}
463
464#[inline(always)]
470pub fn check_member_not_in_set<S>(
471 member: &S::Item,
472 set: &S,
473 member_name: &str,
474 set_name: &str,
475) -> anyhow::Result<()>
476where
477 S: SetLike,
478{
479 if set.contains(member) {
480 anyhow::bail!(
481 "the '{member_name}' member was already in the '{set_name}' set `&<{}>`",
482 std::any::type_name::<S::Item>(),
483 );
484 }
485 Ok(())
486}
487
488#[inline(always)]
494pub fn check_member_in_set<S>(
495 member: &S::Item,
496 set: &S,
497 member_name: &str,
498 set_name: &str,
499) -> anyhow::Result<()>
500where
501 S: SetLike,
502{
503 if !set.contains(member) {
504 anyhow::bail!(
505 "the '{member_name}' member was not in the '{set_name}' set `&<{}>`",
506 std::any::type_name::<S::Item>(),
507 );
508 }
509 Ok(())
510}
511
512#[inline(always)]
518pub fn check_positive_decimal(value: Decimal, param: &str) -> anyhow::Result<()> {
519 if value <= Decimal::ZERO {
520 anyhow::bail!("invalid Decimal for '{param}' not positive, was {value}")
521 }
522 Ok(())
523}
524
525#[cfg(test)]
529mod tests {
530 use std::{
531 collections::{HashMap, HashSet},
532 fmt::Display,
533 str::FromStr,
534 };
535
536 use rstest::rstest;
537 use rust_decimal::Decimal;
538
539 use super::*;
540
541 #[rstest]
542 #[case(false, false)]
543 #[case(true, true)]
544 fn test_check_predicate_true(#[case] predicate: bool, #[case] expected: bool) {
545 let result = check_predicate_true(predicate, "the predicate was false").is_ok();
546 assert_eq!(result, expected);
547 }
548
549 #[rstest]
550 #[case(false, true)]
551 #[case(true, false)]
552 fn test_check_predicate_false(#[case] predicate: bool, #[case] expected: bool) {
553 let result = check_predicate_false(predicate, "the predicate was true").is_ok();
554 assert_eq!(result, expected);
555 }
556
557 #[rstest]
558 #[case("a")]
559 #[case(" ")] #[case(" ")] #[case("🦀")] #[case(" a")]
563 #[case("a ")]
564 #[case("abc")]
565 fn test_check_nonempty_string_with_valid_values(#[case] s: &str) {
566 assert!(check_nonempty_string(s, "value").is_ok());
567 }
568
569 #[rstest]
570 #[case("")] fn test_check_nonempty_string_with_invalid_values(#[case] s: &str) {
572 assert!(check_nonempty_string(s, "value").is_err());
573 }
574
575 #[rstest]
576 #[case(" a")]
577 #[case("a ")]
578 #[case("a a")]
579 #[case(" a ")]
580 #[case("abc")]
581 fn test_check_valid_string_with_valid_value(#[case] s: &str) {
582 assert!(check_valid_string(s, "value").is_ok());
583 }
584
585 #[rstest]
586 #[case("")] #[case(" ")] #[case(" ")] #[case("🦀")] fn test_check_valid_string_with_invalid_values(#[case] s: &str) {
591 assert!(check_valid_string(s, "value").is_err());
592 }
593
594 #[rstest]
595 #[case(None)]
596 #[case(Some(" a"))]
597 #[case(Some("a "))]
598 #[case(Some("a a"))]
599 #[case(Some(" a "))]
600 #[case(Some("abc"))]
601 fn test_check_valid_string_optional_with_valid_value(#[case] s: Option<&str>) {
602 assert!(check_valid_string_optional(s, "value").is_ok());
603 }
604
605 #[rstest]
606 #[case("a", "a")]
607 fn test_check_string_contains_when_does_contain(#[case] s: &str, #[case] pat: &str) {
608 assert!(check_string_contains(s, pat, "value").is_ok());
609 }
610
611 #[rstest]
612 #[case("a", "b")]
613 fn test_check_string_contains_when_does_not_contain(#[case] s: &str, #[case] pat: &str) {
614 assert!(check_string_contains(s, pat, "value").is_err());
615 }
616
617 #[rstest]
618 #[case(0u8, 0u8, "left", "right", true)]
619 #[case(1u8, 1u8, "left", "right", true)]
620 #[case(0u8, 1u8, "left", "right", false)]
621 #[case(1u8, 0u8, "left", "right", false)]
622 #[case(10i32, 10i32, "left", "right", true)]
623 #[case(10i32, 20i32, "left", "right", false)]
624 #[case("hello", "hello", "left", "right", true)]
625 #[case("hello", "world", "left", "right", false)]
626 fn test_check_equal<T: PartialEq + Debug + Display>(
627 #[case] lhs: T,
628 #[case] rhs: T,
629 #[case] lhs_param: &str,
630 #[case] rhs_param: &str,
631 #[case] expected: bool,
632 ) {
633 let result = check_equal(&lhs, &rhs, lhs_param, rhs_param).is_ok();
634 assert_eq!(result, expected);
635 }
636
637 #[rstest]
638 #[case(0, 0, "left", "right", true)]
639 #[case(1, 1, "left", "right", true)]
640 #[case(0, 1, "left", "right", false)]
641 #[case(1, 0, "left", "right", false)]
642 fn test_check_equal_u8_when_equal(
643 #[case] lhs: u8,
644 #[case] rhs: u8,
645 #[case] lhs_param: &str,
646 #[case] rhs_param: &str,
647 #[case] expected: bool,
648 ) {
649 let result = check_equal_u8(lhs, rhs, lhs_param, rhs_param).is_ok();
650 assert_eq!(result, expected);
651 }
652
653 #[rstest]
654 #[case(0, 0, "left", "right", true)]
655 #[case(1, 1, "left", "right", true)]
656 #[case(0, 1, "left", "right", false)]
657 #[case(1, 0, "left", "right", false)]
658 fn test_check_equal_usize_when_equal(
659 #[case] lhs: usize,
660 #[case] rhs: usize,
661 #[case] lhs_param: &str,
662 #[case] rhs_param: &str,
663 #[case] expected: bool,
664 ) {
665 let result = check_equal_usize(lhs, rhs, lhs_param, rhs_param).is_ok();
666 assert_eq!(result, expected);
667 }
668
669 #[rstest]
670 #[case(1, "value")]
671 fn test_check_positive_u64_when_positive(#[case] value: u64, #[case] param: &str) {
672 assert!(check_positive_u64(value, param).is_ok());
673 }
674
675 #[rstest]
676 #[case(0, "value")]
677 fn test_check_positive_u64_when_not_positive(#[case] value: u64, #[case] param: &str) {
678 assert!(check_positive_u64(value, param).is_err());
679 }
680
681 #[rstest]
682 #[case(1, "value")]
683 fn test_check_positive_i64_when_positive(#[case] value: i64, #[case] param: &str) {
684 assert!(check_positive_i64(value, param).is_ok());
685 }
686
687 #[rstest]
688 #[case(0, "value")]
689 #[case(-1, "value")]
690 fn test_check_positive_i64_when_not_positive(#[case] value: i64, #[case] param: &str) {
691 assert!(check_positive_i64(value, param).is_err());
692 }
693
694 #[rstest]
695 #[case(0.0, "value")]
696 #[case(1.0, "value")]
697 fn test_check_non_negative_f64_when_not_negative(#[case] value: f64, #[case] param: &str) {
698 assert!(check_non_negative_f64(value, param).is_ok());
699 }
700
701 #[rstest]
702 #[case(f64::NAN, "value")]
703 #[case(f64::INFINITY, "value")]
704 #[case(f64::NEG_INFINITY, "value")]
705 #[case(-0.1, "value")]
706 fn test_check_non_negative_f64_when_negative(#[case] value: f64, #[case] param: &str) {
707 assert!(check_non_negative_f64(value, param).is_err());
708 }
709
710 #[rstest]
711 #[case(0, 0, 0, "value")]
712 #[case(0, 0, 1, "value")]
713 #[case(1, 0, 1, "value")]
714 fn test_check_in_range_inclusive_u8_when_in_range(
715 #[case] value: u8,
716 #[case] l: u8,
717 #[case] r: u8,
718 #[case] desc: &str,
719 ) {
720 assert!(check_in_range_inclusive_u8(value, l, r, desc).is_ok());
721 }
722
723 #[rstest]
724 #[case(0, 1, 2, "value")]
725 #[case(3, 1, 2, "value")]
726 fn test_check_in_range_inclusive_u8_when_out_of_range(
727 #[case] value: u8,
728 #[case] l: u8,
729 #[case] r: u8,
730 #[case] param: &str,
731 ) {
732 assert!(check_in_range_inclusive_u8(value, l, r, param).is_err());
733 }
734
735 #[rstest]
736 #[case(0, 0, 0, "value")]
737 #[case(0, 0, 1, "value")]
738 #[case(1, 0, 1, "value")]
739 fn test_check_in_range_inclusive_u64_when_in_range(
740 #[case] value: u64,
741 #[case] l: u64,
742 #[case] r: u64,
743 #[case] param: &str,
744 ) {
745 assert!(check_in_range_inclusive_u64(value, l, r, param).is_ok());
746 }
747
748 #[rstest]
749 #[case(0, 1, 2, "value")]
750 #[case(3, 1, 2, "value")]
751 fn test_check_in_range_inclusive_u64_when_out_of_range(
752 #[case] value: u64,
753 #[case] l: u64,
754 #[case] r: u64,
755 #[case] param: &str,
756 ) {
757 assert!(check_in_range_inclusive_u64(value, l, r, param).is_err());
758 }
759
760 #[rstest]
761 #[case(0, 0, 0, "value")]
762 #[case(0, 0, 1, "value")]
763 #[case(1, 0, 1, "value")]
764 fn test_check_in_range_inclusive_i64_when_in_range(
765 #[case] value: i64,
766 #[case] l: i64,
767 #[case] r: i64,
768 #[case] param: &str,
769 ) {
770 assert!(check_in_range_inclusive_i64(value, l, r, param).is_ok());
771 }
772
773 #[rstest]
774 #[case(0.0, 0.0, 0.0, "value")]
775 #[case(0.0, 0.0, 1.0, "value")]
776 #[case(1.0, 0.0, 1.0, "value")]
777 fn test_check_in_range_inclusive_f64_when_in_range(
778 #[case] value: f64,
779 #[case] l: f64,
780 #[case] r: f64,
781 #[case] param: &str,
782 ) {
783 assert!(check_in_range_inclusive_f64(value, l, r, param).is_ok());
784 }
785
786 #[rstest]
787 #[case(-1e16, 0.0, 0.0, "value")]
788 #[case(1.0 + 1e16, 0.0, 1.0, "value")]
789 fn test_check_in_range_inclusive_f64_when_out_of_range(
790 #[case] value: f64,
791 #[case] l: f64,
792 #[case] r: f64,
793 #[case] param: &str,
794 ) {
795 assert!(check_in_range_inclusive_f64(value, l, r, param).is_err());
796 }
797
798 #[rstest]
799 #[case(0, 1, 2, "value")]
800 #[case(3, 1, 2, "value")]
801 fn test_check_in_range_inclusive_i64_when_out_of_range(
802 #[case] value: i64,
803 #[case] l: i64,
804 #[case] r: i64,
805 #[case] param: &str,
806 ) {
807 assert!(check_in_range_inclusive_i64(value, l, r, param).is_err());
808 }
809
810 #[rstest]
811 #[case(0, 0, 0, "value")]
812 #[case(0, 0, 1, "value")]
813 #[case(1, 0, 1, "value")]
814 fn test_check_in_range_inclusive_usize_when_in_range(
815 #[case] value: usize,
816 #[case] l: usize,
817 #[case] r: usize,
818 #[case] param: &str,
819 ) {
820 assert!(check_in_range_inclusive_usize(value, l, r, param).is_ok());
821 }
822
823 #[rstest]
824 #[case(0, 1, 2, "value")]
825 #[case(3, 1, 2, "value")]
826 fn test_check_in_range_inclusive_usize_when_out_of_range(
827 #[case] value: usize,
828 #[case] l: usize,
829 #[case] r: usize,
830 #[case] param: &str,
831 ) {
832 assert!(check_in_range_inclusive_usize(value, l, r, param).is_err());
833 }
834
835 #[rstest]
836 #[case(vec![], true)]
837 #[case(vec![1_u8], false)]
838 fn test_check_slice_empty(#[case] collection: Vec<u8>, #[case] expected: bool) {
839 let result = check_slice_empty(collection.as_slice(), "param").is_ok();
840 assert_eq!(result, expected);
841 }
842
843 #[rstest]
844 #[case(vec![], false)]
845 #[case(vec![1_u8], true)]
846 fn test_check_slice_not_empty(#[case] collection: Vec<u8>, #[case] expected: bool) {
847 let result = check_slice_not_empty(collection.as_slice(), "param").is_ok();
848 assert_eq!(result, expected);
849 }
850
851 #[rstest]
852 #[case(HashMap::new(), true)]
853 #[case(HashMap::from([("A".to_string(), 1_u8)]), false)]
854 fn test_check_map_empty(#[case] map: HashMap<String, u8>, #[case] expected: bool) {
855 let result = check_map_empty(&map, "param").is_ok();
856 assert_eq!(result, expected);
857 }
858
859 #[rstest]
860 #[case(HashMap::new(), false)]
861 #[case(HashMap::from([("A".to_string(), 1_u8)]), true)]
862 fn test_check_map_not_empty(#[case] map: HashMap<String, u8>, #[case] expected: bool) {
863 let result = check_map_not_empty(&map, "param").is_ok();
864 assert_eq!(result, expected);
865 }
866
867 #[rstest]
868 #[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(
872 #[case] map: &HashMap<u32, u32>,
873 #[case] key: u32,
874 #[case] key_name: &str,
875 #[case] map_name: &str,
876 #[case] expected: bool,
877 ) {
878 let result = check_key_not_in_map(&key, map, key_name, map_name).is_ok();
879 assert_eq!(result, expected);
880 }
881
882 #[rstest]
883 #[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(
887 #[case] map: &HashMap<u32, u32>,
888 #[case] key: u32,
889 #[case] key_name: &str,
890 #[case] map_name: &str,
891 #[case] expected: bool,
892 ) {
893 let result = check_key_in_map(&key, map, key_name, map_name).is_ok();
894 assert_eq!(result, expected);
895 }
896
897 #[rstest]
898 #[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(
902 #[case] set: &HashSet<u32>,
903 #[case] member: u32,
904 #[case] member_name: &str,
905 #[case] set_name: &str,
906 #[case] expected: bool,
907 ) {
908 let result = check_member_not_in_set(&member, set, member_name, set_name).is_ok();
909 assert_eq!(result, expected);
910 }
911
912 #[rstest]
913 #[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(
917 #[case] set: &HashSet<u32>,
918 #[case] member: u32,
919 #[case] member_name: &str,
920 #[case] set_name: &str,
921 #[case] expected: bool,
922 ) {
923 let result = check_member_in_set(&member, set, member_name, set_name).is_ok();
924 assert_eq!(result, expected);
925 }
926
927 #[rstest]
928 #[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) {
935 let value = Decimal::from_str(raw).expect("valid decimal literal");
936 let result = super::check_positive_decimal(value, "param").is_ok();
937 assert_eq!(result, expected);
938 }
939}