1use std::fmt::{Debug, Display};
27
28use crate::collections::{MapLike, SetLike};
29
30pub const FAILED: &str = "Condition failed";
36
37#[inline(always)]
43pub fn check_predicate_true(predicate: bool, fail_msg: &str) -> anyhow::Result<()> {
44 if !predicate {
45 anyhow::bail!("{fail_msg}")
46 }
47 Ok(())
48}
49
50#[inline(always)]
56pub fn check_predicate_false(predicate: bool, fail_msg: &str) -> anyhow::Result<()> {
57 if predicate {
58 anyhow::bail!("{fail_msg}")
59 }
60 Ok(())
61}
62
63#[inline(always)]
72pub fn check_nonempty_string<T: AsRef<str>>(s: T, param: &str) -> anyhow::Result<()> {
73 if s.as_ref().is_empty() {
74 anyhow::bail!("invalid string for '{param}', was empty");
75 }
76 Ok(())
77}
78
79#[inline(always)]
88pub fn check_valid_string<T: AsRef<str>>(s: T, param: &str) -> anyhow::Result<()> {
89 let s = s.as_ref();
90
91 if s.is_empty() {
92 anyhow::bail!("invalid string for '{param}', was empty");
93 }
94
95 let mut has_non_whitespace = false;
97 for c in s.chars() {
98 if !c.is_whitespace() {
99 has_non_whitespace = true;
100 }
101 if !c.is_ascii() {
102 anyhow::bail!("invalid string for '{param}' contained a non-ASCII char, was '{s}'");
103 }
104 }
105
106 if !has_non_whitespace {
107 anyhow::bail!("invalid string for '{param}', was all whitespace");
108 }
109
110 Ok(())
111}
112
113#[inline(always)]
122pub fn check_valid_string_optional<T: AsRef<str>>(s: Option<T>, param: &str) -> anyhow::Result<()> {
123 if let Some(s) = s {
124 check_valid_string(s, param)?;
125 }
126 Ok(())
127}
128
129#[inline(always)]
135pub fn check_string_contains<T: AsRef<str>>(s: T, pat: &str, param: &str) -> anyhow::Result<()> {
136 let s = s.as_ref();
137 if !s.contains(pat) {
138 anyhow::bail!("invalid string for '{param}' did not contain '{pat}', was '{s}'")
139 }
140 Ok(())
141}
142
143#[inline(always)]
149pub fn check_equal<T: PartialEq + Debug + Display>(
150 lhs: &T,
151 rhs: &T,
152 lhs_param: &str,
153 rhs_param: &str,
154) -> anyhow::Result<()> {
155 if lhs != rhs {
156 anyhow::bail!("'{lhs_param}' value of {lhs} was not equal to '{rhs_param}' value of {rhs}");
157 }
158 Ok(())
159}
160
161#[inline(always)]
167pub fn check_equal_u8(lhs: u8, rhs: u8, lhs_param: &str, rhs_param: &str) -> anyhow::Result<()> {
168 if lhs != rhs {
169 anyhow::bail!("'{lhs_param}' u8 of {lhs} was not equal to '{rhs_param}' u8 of {rhs}")
170 }
171 Ok(())
172}
173
174#[inline(always)]
180pub fn check_equal_usize(
181 lhs: usize,
182 rhs: usize,
183 lhs_param: &str,
184 rhs_param: &str,
185) -> anyhow::Result<()> {
186 if lhs != rhs {
187 anyhow::bail!("'{lhs_param}' usize of {lhs} was not equal to '{rhs_param}' usize of {rhs}")
188 }
189 Ok(())
190}
191
192#[inline(always)]
198pub fn check_positive_u64(value: u64, param: &str) -> anyhow::Result<()> {
199 if value == 0 {
200 anyhow::bail!("invalid u64 for '{param}' not positive, was {value}")
201 }
202 Ok(())
203}
204
205#[inline(always)]
211pub fn check_positive_u128(value: u128, param: &str) -> anyhow::Result<()> {
212 if value == 0 {
213 anyhow::bail!("invalid u128 for '{param}' not positive, was {value}")
214 }
215 Ok(())
216}
217
218#[inline(always)]
224pub fn check_positive_i64(value: i64, param: &str) -> anyhow::Result<()> {
225 if value <= 0 {
226 anyhow::bail!("invalid i64 for '{param}' not positive, was {value}")
227 }
228 Ok(())
229}
230
231#[inline(always)]
237pub fn check_positive_i128(value: i128, param: &str) -> anyhow::Result<()> {
238 if value <= 0 {
239 anyhow::bail!("invalid i128 for '{param}' not positive, was {value}")
240 }
241 Ok(())
242}
243
244#[inline(always)]
250pub fn check_non_negative_f64(value: f64, param: &str) -> anyhow::Result<()> {
251 if value.is_nan() || value.is_infinite() {
252 anyhow::bail!("invalid f64 for '{param}', was {value}")
253 }
254 if value < 0.0 {
255 anyhow::bail!("invalid f64 for '{param}' negative, was {value}")
256 }
257 Ok(())
258}
259
260#[inline(always)]
266pub fn check_in_range_inclusive_u8(value: u8, l: u8, r: u8, param: &str) -> anyhow::Result<()> {
267 if value < l || value > r {
268 anyhow::bail!("invalid u8 for '{param}' not in range [{l}, {r}], was {value}")
269 }
270 Ok(())
271}
272
273#[inline(always)]
279pub fn check_in_range_inclusive_u64(value: u64, l: u64, r: u64, param: &str) -> anyhow::Result<()> {
280 if value < l || value > r {
281 anyhow::bail!("invalid u64 for '{param}' not in range [{l}, {r}], was {value}")
282 }
283 Ok(())
284}
285
286#[inline(always)]
292pub fn check_in_range_inclusive_i64(value: i64, l: i64, r: i64, param: &str) -> anyhow::Result<()> {
293 if value < l || value > r {
294 anyhow::bail!("invalid i64 for '{param}' not in range [{l}, {r}], was {value}")
295 }
296 Ok(())
297}
298
299#[inline(always)]
305pub fn check_in_range_inclusive_f64(value: f64, l: f64, r: f64, param: &str) -> anyhow::Result<()> {
306 const EPSILON: f64 = 1e-15; if value.is_nan() || value.is_infinite() {
309 anyhow::bail!("invalid f64 for '{param}', was {value}")
310 }
311 if value < l - EPSILON || value > r + EPSILON {
312 anyhow::bail!("invalid f64 for '{param}' not in range [{l}, {r}], was {value}")
313 }
314 Ok(())
315}
316
317#[inline(always)]
323pub fn check_in_range_inclusive_usize(
324 value: usize,
325 l: usize,
326 r: usize,
327 param: &str,
328) -> anyhow::Result<()> {
329 if value < l || value > r {
330 anyhow::bail!("invalid usize for '{param}' not in range [{l}, {r}], was {value}")
331 }
332 Ok(())
333}
334
335#[inline(always)]
341pub fn check_slice_empty<T>(slice: &[T], param: &str) -> anyhow::Result<()> {
342 if !slice.is_empty() {
343 anyhow::bail!(
344 "the '{param}' slice `&[{}]` was not empty",
345 std::any::type_name::<T>()
346 )
347 }
348 Ok(())
349}
350
351#[inline(always)]
357pub fn check_slice_not_empty<T>(slice: &[T], param: &str) -> anyhow::Result<()> {
358 if slice.is_empty() {
359 anyhow::bail!(
360 "the '{param}' slice `&[{}]` was empty",
361 std::any::type_name::<T>()
362 )
363 }
364 Ok(())
365}
366
367#[inline(always)]
373pub fn check_map_empty<M>(map: &M, param: &str) -> anyhow::Result<()>
374where
375 M: MapLike,
376{
377 if !map.is_empty() {
378 anyhow::bail!(
379 "the '{param}' map `&<{}, {}>` was not empty",
380 std::any::type_name::<M::Key>(),
381 std::any::type_name::<M::Value>(),
382 );
383 }
384 Ok(())
385}
386
387#[inline(always)]
393pub fn check_map_not_empty<M>(map: &M, param: &str) -> anyhow::Result<()>
394where
395 M: MapLike,
396{
397 if map.is_empty() {
398 anyhow::bail!(
399 "the '{param}' map `&<{}, {}>` was empty",
400 std::any::type_name::<M::Key>(),
401 std::any::type_name::<M::Value>(),
402 );
403 }
404 Ok(())
405}
406
407#[inline(always)]
413pub fn check_key_not_in_map<M>(
414 key: &M::Key,
415 map: &M,
416 key_name: &str,
417 map_name: &str,
418) -> anyhow::Result<()>
419where
420 M: MapLike,
421{
422 if map.contains_key(key) {
423 anyhow::bail!(
424 "the '{key_name}' key {key} was already in the '{map_name}' map `&<{}, {}>`",
425 std::any::type_name::<M::Key>(),
426 std::any::type_name::<M::Value>(),
427 );
428 }
429 Ok(())
430}
431
432#[inline(always)]
438pub fn check_key_in_map<M>(
439 key: &M::Key,
440 map: &M,
441 key_name: &str,
442 map_name: &str,
443) -> anyhow::Result<()>
444where
445 M: MapLike,
446{
447 if !map.contains_key(key) {
448 anyhow::bail!(
449 "the '{key_name}' key {key} was not in the '{map_name}' map `&<{}, {}>`",
450 std::any::type_name::<M::Key>(),
451 std::any::type_name::<M::Value>(),
452 );
453 }
454 Ok(())
455}
456
457#[inline(always)]
463pub fn check_member_not_in_set<S>(
464 member: &S::Item,
465 set: &S,
466 member_name: &str,
467 set_name: &str,
468) -> anyhow::Result<()>
469where
470 S: SetLike,
471{
472 if set.contains(member) {
473 anyhow::bail!(
474 "the '{member_name}' member was already in the '{set_name}' set `&<{}>`",
475 std::any::type_name::<S::Item>(),
476 );
477 }
478 Ok(())
479}
480
481#[inline(always)]
487pub fn check_member_in_set<S>(
488 member: &S::Item,
489 set: &S,
490 member_name: &str,
491 set_name: &str,
492) -> anyhow::Result<()>
493where
494 S: SetLike,
495{
496 if !set.contains(member) {
497 anyhow::bail!(
498 "the '{member_name}' member was not in the '{set_name}' set `&<{}>`",
499 std::any::type_name::<S::Item>(),
500 );
501 }
502 Ok(())
503}
504
505#[cfg(test)]
509mod tests {
510 use std::{
511 collections::{HashMap, HashSet},
512 fmt::Display,
513 };
514
515 use rstest::rstest;
516
517 use super::*;
518
519 #[rstest]
520 #[case(false, false)]
521 #[case(true, true)]
522 fn test_check_predicate_true(#[case] predicate: bool, #[case] expected: bool) {
523 let result = check_predicate_true(predicate, "the predicate was false").is_ok();
524 assert_eq!(result, expected);
525 }
526
527 #[rstest]
528 #[case(false, true)]
529 #[case(true, false)]
530 fn test_check_predicate_false(#[case] predicate: bool, #[case] expected: bool) {
531 let result = check_predicate_false(predicate, "the predicate was true").is_ok();
532 assert_eq!(result, expected);
533 }
534
535 #[rstest]
536 #[case("a")]
537 #[case(" ")] #[case(" ")] #[case("🦀")] #[case(" a")]
541 #[case("a ")]
542 #[case("abc")]
543 fn test_check_nonempty_string_with_valid_values(#[case] s: &str) {
544 assert!(check_nonempty_string(s, "value").is_ok());
545 }
546
547 #[rstest]
548 #[case("")] fn test_check_nonempty_string_with_invalid_values(#[case] s: &str) {
550 assert!(check_nonempty_string(s, "value").is_err());
551 }
552
553 #[rstest]
554 #[case(" a")]
555 #[case("a ")]
556 #[case("a a")]
557 #[case(" a ")]
558 #[case("abc")]
559 fn test_check_valid_string_with_valid_value(#[case] s: &str) {
560 assert!(check_valid_string(s, "value").is_ok());
561 }
562
563 #[rstest]
564 #[case("")] #[case(" ")] #[case(" ")] #[case("🦀")] fn test_check_valid_string_with_invalid_values(#[case] s: &str) {
569 assert!(check_valid_string(s, "value").is_err());
570 }
571
572 #[rstest]
573 #[case(None)]
574 #[case(Some(" a"))]
575 #[case(Some("a "))]
576 #[case(Some("a a"))]
577 #[case(Some(" a "))]
578 #[case(Some("abc"))]
579 fn test_check_valid_string_optional_with_valid_value(#[case] s: Option<&str>) {
580 assert!(check_valid_string_optional(s, "value").is_ok());
581 }
582
583 #[rstest]
584 #[case("a", "a")]
585 fn test_check_string_contains_when_does_contain(#[case] s: &str, #[case] pat: &str) {
586 assert!(check_string_contains(s, pat, "value").is_ok());
587 }
588
589 #[rstest]
590 #[case("a", "b")]
591 fn test_check_string_contains_when_does_not_contain(#[case] s: &str, #[case] pat: &str) {
592 assert!(check_string_contains(s, pat, "value").is_err());
593 }
594
595 #[rstest]
596 #[case(0u8, 0u8, "left", "right", true)]
597 #[case(1u8, 1u8, "left", "right", true)]
598 #[case(0u8, 1u8, "left", "right", false)]
599 #[case(1u8, 0u8, "left", "right", false)]
600 #[case(10i32, 10i32, "left", "right", true)]
601 #[case(10i32, 20i32, "left", "right", false)]
602 #[case("hello", "hello", "left", "right", true)]
603 #[case("hello", "world", "left", "right", false)]
604 fn test_check_equal<T: PartialEq + Debug + Display>(
605 #[case] lhs: T,
606 #[case] rhs: T,
607 #[case] lhs_param: &str,
608 #[case] rhs_param: &str,
609 #[case] expected: bool,
610 ) {
611 let result = check_equal(&lhs, &rhs, lhs_param, rhs_param).is_ok();
612 assert_eq!(result, expected);
613 }
614
615 #[rstest]
616 #[case(0, 0, "left", "right", true)]
617 #[case(1, 1, "left", "right", true)]
618 #[case(0, 1, "left", "right", false)]
619 #[case(1, 0, "left", "right", false)]
620 fn test_check_equal_u8_when_equal(
621 #[case] lhs: u8,
622 #[case] rhs: u8,
623 #[case] lhs_param: &str,
624 #[case] rhs_param: &str,
625 #[case] expected: bool,
626 ) {
627 let result = check_equal_u8(lhs, rhs, lhs_param, rhs_param).is_ok();
628 assert_eq!(result, expected);
629 }
630
631 #[rstest]
632 #[case(0, 0, "left", "right", true)]
633 #[case(1, 1, "left", "right", true)]
634 #[case(0, 1, "left", "right", false)]
635 #[case(1, 0, "left", "right", false)]
636 fn test_check_equal_usize_when_equal(
637 #[case] lhs: usize,
638 #[case] rhs: usize,
639 #[case] lhs_param: &str,
640 #[case] rhs_param: &str,
641 #[case] expected: bool,
642 ) {
643 let result = check_equal_usize(lhs, rhs, lhs_param, rhs_param).is_ok();
644 assert_eq!(result, expected);
645 }
646
647 #[rstest]
648 #[case(1, "value")]
649 fn test_check_positive_u64_when_positive(#[case] value: u64, #[case] param: &str) {
650 assert!(check_positive_u64(value, param).is_ok());
651 }
652
653 #[rstest]
654 #[case(0, "value")]
655 fn test_check_positive_u64_when_not_positive(#[case] value: u64, #[case] param: &str) {
656 assert!(check_positive_u64(value, param).is_err());
657 }
658
659 #[rstest]
660 #[case(1, "value")]
661 fn test_check_positive_i64_when_positive(#[case] value: i64, #[case] param: &str) {
662 assert!(check_positive_i64(value, param).is_ok());
663 }
664
665 #[rstest]
666 #[case(0, "value")]
667 #[case(-1, "value")]
668 fn test_check_positive_i64_when_not_positive(#[case] value: i64, #[case] param: &str) {
669 assert!(check_positive_i64(value, param).is_err());
670 }
671
672 #[rstest]
673 #[case(0.0, "value")]
674 #[case(1.0, "value")]
675 fn test_check_non_negative_f64_when_not_negative(#[case] value: f64, #[case] param: &str) {
676 assert!(check_non_negative_f64(value, param).is_ok());
677 }
678
679 #[rstest]
680 #[case(f64::NAN, "value")]
681 #[case(f64::INFINITY, "value")]
682 #[case(f64::NEG_INFINITY, "value")]
683 #[case(-0.1, "value")]
684 fn test_check_non_negative_f64_when_negative(#[case] value: f64, #[case] param: &str) {
685 assert!(check_non_negative_f64(value, param).is_err());
686 }
687
688 #[rstest]
689 #[case(0, 0, 0, "value")]
690 #[case(0, 0, 1, "value")]
691 #[case(1, 0, 1, "value")]
692 fn test_check_in_range_inclusive_u8_when_in_range(
693 #[case] value: u8,
694 #[case] l: u8,
695 #[case] r: u8,
696 #[case] desc: &str,
697 ) {
698 assert!(check_in_range_inclusive_u8(value, l, r, desc).is_ok());
699 }
700
701 #[rstest]
702 #[case(0, 1, 2, "value")]
703 #[case(3, 1, 2, "value")]
704 fn test_check_in_range_inclusive_u8_when_out_of_range(
705 #[case] value: u8,
706 #[case] l: u8,
707 #[case] r: u8,
708 #[case] param: &str,
709 ) {
710 assert!(check_in_range_inclusive_u8(value, l, r, param).is_err());
711 }
712
713 #[rstest]
714 #[case(0, 0, 0, "value")]
715 #[case(0, 0, 1, "value")]
716 #[case(1, 0, 1, "value")]
717 fn test_check_in_range_inclusive_u64_when_in_range(
718 #[case] value: u64,
719 #[case] l: u64,
720 #[case] r: u64,
721 #[case] param: &str,
722 ) {
723 assert!(check_in_range_inclusive_u64(value, l, r, param).is_ok());
724 }
725
726 #[rstest]
727 #[case(0, 1, 2, "value")]
728 #[case(3, 1, 2, "value")]
729 fn test_check_in_range_inclusive_u64_when_out_of_range(
730 #[case] value: u64,
731 #[case] l: u64,
732 #[case] r: u64,
733 #[case] param: &str,
734 ) {
735 assert!(check_in_range_inclusive_u64(value, l, r, param).is_err());
736 }
737
738 #[rstest]
739 #[case(0, 0, 0, "value")]
740 #[case(0, 0, 1, "value")]
741 #[case(1, 0, 1, "value")]
742 fn test_check_in_range_inclusive_i64_when_in_range(
743 #[case] value: i64,
744 #[case] l: i64,
745 #[case] r: i64,
746 #[case] param: &str,
747 ) {
748 assert!(check_in_range_inclusive_i64(value, l, r, param).is_ok());
749 }
750
751 #[rstest]
752 #[case(0.0, 0.0, 0.0, "value")]
753 #[case(0.0, 0.0, 1.0, "value")]
754 #[case(1.0, 0.0, 1.0, "value")]
755 fn test_check_in_range_inclusive_f64_when_in_range(
756 #[case] value: f64,
757 #[case] l: f64,
758 #[case] r: f64,
759 #[case] param: &str,
760 ) {
761 assert!(check_in_range_inclusive_f64(value, l, r, param).is_ok());
762 }
763
764 #[rstest]
765 #[case(-1e16, 0.0, 0.0, "value")]
766 #[case(1.0 + 1e16, 0.0, 1.0, "value")]
767 fn test_check_in_range_inclusive_f64_when_out_of_range(
768 #[case] value: f64,
769 #[case] l: f64,
770 #[case] r: f64,
771 #[case] param: &str,
772 ) {
773 assert!(check_in_range_inclusive_f64(value, l, r, param).is_err());
774 }
775
776 #[rstest]
777 #[case(0, 1, 2, "value")]
778 #[case(3, 1, 2, "value")]
779 fn test_check_in_range_inclusive_i64_when_out_of_range(
780 #[case] value: i64,
781 #[case] l: i64,
782 #[case] r: i64,
783 #[case] param: &str,
784 ) {
785 assert!(check_in_range_inclusive_i64(value, l, r, param).is_err());
786 }
787
788 #[rstest]
789 #[case(0, 0, 0, "value")]
790 #[case(0, 0, 1, "value")]
791 #[case(1, 0, 1, "value")]
792 fn test_check_in_range_inclusive_usize_when_in_range(
793 #[case] value: usize,
794 #[case] l: usize,
795 #[case] r: usize,
796 #[case] param: &str,
797 ) {
798 assert!(check_in_range_inclusive_usize(value, l, r, param).is_ok());
799 }
800
801 #[rstest]
802 #[case(0, 1, 2, "value")]
803 #[case(3, 1, 2, "value")]
804 fn test_check_in_range_inclusive_usize_when_out_of_range(
805 #[case] value: usize,
806 #[case] l: usize,
807 #[case] r: usize,
808 #[case] param: &str,
809 ) {
810 assert!(check_in_range_inclusive_usize(value, l, r, param).is_err());
811 }
812
813 #[rstest]
814 #[case(vec![], true)]
815 #[case(vec![1_u8], false)]
816 fn test_check_slice_empty(#[case] collection: Vec<u8>, #[case] expected: bool) {
817 let result = check_slice_empty(collection.as_slice(), "param").is_ok();
818 assert_eq!(result, expected);
819 }
820
821 #[rstest]
822 #[case(vec![], false)]
823 #[case(vec![1_u8], true)]
824 fn test_check_slice_not_empty(#[case] collection: Vec<u8>, #[case] expected: bool) {
825 let result = check_slice_not_empty(collection.as_slice(), "param").is_ok();
826 assert_eq!(result, expected);
827 }
828
829 #[rstest]
830 #[case(HashMap::new(), true)]
831 #[case(HashMap::from([("A".to_string(), 1_u8)]), false)]
832 fn test_check_map_empty(#[case] map: HashMap<String, u8>, #[case] expected: bool) {
833 let result = check_map_empty(&map, "param").is_ok();
834 assert_eq!(result, expected);
835 }
836
837 #[rstest]
838 #[case(HashMap::new(), false)]
839 #[case(HashMap::from([("A".to_string(), 1_u8)]), true)]
840 fn test_check_map_not_empty(#[case] map: HashMap<String, u8>, #[case] expected: bool) {
841 let result = check_map_not_empty(&map, "param").is_ok();
842 assert_eq!(result, expected);
843 }
844
845 #[rstest]
846 #[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(
850 #[case] map: &HashMap<u32, u32>,
851 #[case] key: u32,
852 #[case] key_name: &str,
853 #[case] map_name: &str,
854 #[case] expected: bool,
855 ) {
856 let result = check_key_not_in_map(&key, map, key_name, map_name).is_ok();
857 assert_eq!(result, expected);
858 }
859
860 #[rstest]
861 #[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(
865 #[case] map: &HashMap<u32, u32>,
866 #[case] key: u32,
867 #[case] key_name: &str,
868 #[case] map_name: &str,
869 #[case] expected: bool,
870 ) {
871 let result = check_key_in_map(&key, map, key_name, map_name).is_ok();
872 assert_eq!(result, expected);
873 }
874
875 #[rstest]
876 #[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(
880 #[case] set: &HashSet<u32>,
881 #[case] member: u32,
882 #[case] member_name: &str,
883 #[case] set_name: &str,
884 #[case] expected: bool,
885 ) {
886 let result = check_member_not_in_set(&member, set, member_name, set_name).is_ok();
887 assert_eq!(result, expected);
888 }
889
890 #[rstest]
891 #[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(
895 #[case] set: &HashSet<u32>,
896 #[case] member: u32,
897 #[case] member_name: &str,
898 #[case] set_name: &str,
899 #[case] expected: bool,
900 ) {
901 let result = check_member_in_set(&member, set, member_name, set_name).is_ok();
902 assert_eq!(result, expected);
903 }
904}