|
| 1 | +use crate::result::Error; |
| 2 | +use crate::rule::{Iterable, Rule}; |
| 3 | +use crate::Refined; |
| 4 | +use std::collections::VecDeque; |
| 5 | + |
| 6 | +/// A type that holds a value where the count of items in the collection that satisfy the condition is less than `N`. |
| 7 | +pub type CountLess<const N: usize, RULE, ITERABLE> = Refined<CountLessRule<N, RULE, ITERABLE>>; |
| 8 | + |
| 9 | +/// A type that holds a `Vec` value where the count of items that satisfy the condition is less than `N`. |
| 10 | +pub type CountLessVec<const N: usize, RULE> = CountLess<N, RULE, Vec<<RULE as Rule>::Item>>; |
| 11 | + |
| 12 | +/// A type that holds a `VecDeque` value where the count of items that satisfy the condition is less than `N`. |
| 13 | +pub type CountLessVecDeque<const N: usize, RULE> = |
| 14 | + CountLess<N, RULE, VecDeque<<RULE as Rule>::Item>>; |
| 15 | + |
| 16 | +/// A type that holds a `HashMap` value where the count of items that satisfy the condition is less than `N`. |
| 17 | +pub type CountLessHashMap<const N: usize, RULE, K> = |
| 18 | + CountLess<N, RULE, std::collections::HashMap<K, <RULE as Rule>::Item>>; |
| 19 | + |
| 20 | +/// A type that holds a `HashSet` value where the count of items that satisfy the condition is less than `N`. |
| 21 | +pub type CountLessHashSet<const N: usize, RULE, K> = |
| 22 | + CountLess<N, RULE, std::collections::HashSet<K>>; |
| 23 | + |
| 24 | +/// A type that holds a `String` value where the count of items that satisfy the condition is less than `N`. |
| 25 | +pub type CountLessString<const N: usize, RULE> = CountLess<N, RULE, String>; |
| 26 | + |
| 27 | +/// A type that holds a `&'a str` value where the count of items that satisfy the condition is less than `N`. |
| 28 | +pub type CountLessStr<'a, const N: usize, RULE> = CountLess<N, RULE, &'a str>; |
| 29 | + |
| 30 | +/// Rule where the count of items in the collection that satisfy the condition is less than `N`. |
| 31 | +pub struct CountLessRule<const N: usize, RULE: Rule, ITERABLE: Iterable> |
| 32 | +where |
| 33 | + ITERABLE: Iterable<Item = RULE::Item>, |
| 34 | +{ |
| 35 | + _phantom: std::marker::PhantomData<(RULE, ITERABLE)>, |
| 36 | +} |
| 37 | + |
| 38 | +impl<const N: usize, ITERABLE, RULE> Rule for CountLessRule<N, RULE, ITERABLE> |
| 39 | +where |
| 40 | + ITERABLE: Iterable<Item = RULE::Item> + FromIterator<ITERABLE::Item>, |
| 41 | + RULE: Rule, |
| 42 | +{ |
| 43 | + type Item = ITERABLE; |
| 44 | + fn validate(target: Self::Item) -> crate::Result<Self::Item> { |
| 45 | + let mut count = 0; |
| 46 | + let mut deque = VecDeque::new(); |
| 47 | + for item in target.into_iterator() { |
| 48 | + match RULE::validate(item) { |
| 49 | + Ok(item) => { |
| 50 | + deque.push_back(item); |
| 51 | + count += 1 |
| 52 | + } |
| 53 | + Err(e) => { |
| 54 | + deque.push_back(e.into_value()); |
| 55 | + } |
| 56 | + } |
| 57 | + } |
| 58 | + let target = ITERABLE::from_iter(deque); |
| 59 | + if count < N { |
| 60 | + Ok(target) |
| 61 | + } else { |
| 62 | + Err(Error::new( |
| 63 | + target, |
| 64 | + format!("count is not less than {}, actual count is {}", N, count), |
| 65 | + )) |
| 66 | + } |
| 67 | + } |
| 68 | +} |
| 69 | + |
| 70 | +/// Rule where the count of items in the `Vec` that satisfy the condition is less than `N`. |
| 71 | +pub type CountLessVecRule<const N: usize, RULE> = CountLessRule<N, RULE, Vec<<RULE as Rule>::Item>>; |
| 72 | + |
| 73 | +/// Rule where the count of items in the `VecDeque` that satisfy the condition is less than `N`. |
| 74 | +pub type CountLessVecDequeRule<const N: usize, RULE> = |
| 75 | + CountLessRule<N, RULE, VecDeque<<RULE as Rule>::Item>>; |
| 76 | + |
| 77 | +/// Rule where the count of items in the `HashMap` that satisfy the condition is less than `N`. |
| 78 | +pub type CountLessHashMapRule<const N: usize, RULE, K> = |
| 79 | + CountLessRule<N, RULE, std::collections::HashMap<K, <RULE as Rule>::Item>>; |
| 80 | + |
| 81 | +/// Rule where the count of items in the `HashSet` that satisfy the condition is less than `N`. |
| 82 | +pub type CountLessHashSetRule<const N: usize, RULE, K> = |
| 83 | + CountLessRule<N, RULE, std::collections::HashSet<K>>; |
| 84 | + |
| 85 | +/// Rule where the count of items in the `String` that satisfy the condition is less than `N`. |
| 86 | +pub type CountLessStringRule<const N: usize, RULE> = CountLessRule<N, RULE, String>; |
| 87 | + |
| 88 | +/// Rule where the count of items in the `&'a str` that satisfy the condition is less than `N`. |
| 89 | +pub type CountLessStrRule<'a, const N: usize, RULE> = CountLessRule<N, RULE, &'a str>; |
| 90 | + |
| 91 | +#[cfg(test)] |
| 92 | +mod tests { |
| 93 | + use crate::result::Error; |
| 94 | + use crate::rule::{CountLess, NonEmptyStringRule}; |
| 95 | + |
| 96 | + #[test] |
| 97 | + fn count_less_1() -> Result<(), Error<Vec<String>>> { |
| 98 | + let value = vec!["good morning".to_string(), "hello".to_string()]; |
| 99 | + let count_less: CountLess<3, NonEmptyStringRule, Vec<_>> = CountLess::new(value.clone())?; |
| 100 | + assert_eq!(count_less.into_value(), value); |
| 101 | + Ok(()) |
| 102 | + } |
| 103 | + |
| 104 | + #[test] |
| 105 | + fn count_less_2() -> anyhow::Result<()> { |
| 106 | + let value = vec!["".to_string(), "hello".to_string()]; |
| 107 | + let count_less_result = CountLess::<1, NonEmptyStringRule, Vec<_>>::new(value.clone()); |
| 108 | + assert!(count_less_result.is_err()); |
| 109 | + Ok(()) |
| 110 | + } |
| 111 | +} |
0 commit comments