|
| 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 satisfying the `CountEqualRule` |
| 7 | +pub type CountEqual<const N: usize, RULE, ITERABLE> = Refined<CountEqualRule<N, RULE, ITERABLE>>; |
| 8 | + |
| 9 | +/// A type that holds a `Vec` value satisfying the `CountEqualRule` |
| 10 | +pub type CountEqualVec<const N: usize, RULE> = Refined<CountEqualVecRule<N, RULE>>; |
| 11 | + |
| 12 | +/// A type that holds a `VecDeque` value satisfying the `CountEqualRule` |
| 13 | +pub type CountEqualVecDeque<const N: usize, RULE> = Refined<CountEqualVecDequeRule<N, RULE>>; |
| 14 | + |
| 15 | +/// A type that holds a `HashMap` value satisfying the `CountEqualRule` |
| 16 | +pub type CountEqualHashMap<const N: usize, RULE, K> = Refined<CountEqualHashMapRule<N, RULE, K>>; |
| 17 | + |
| 18 | +/// A type that holds a `HashSet` value satisfying the `CountEqualRule` |
| 19 | +pub type CountEqualHashSet<const N: usize, RULE, K> = Refined<CountEqualHashSetRule<N, RULE, K>>; |
| 20 | + |
| 21 | +/// A type that holds a `String` value satisfying the `CountEqualRule` |
| 22 | +pub type CountEqualString<const N: usize, RULE> = Refined<CountEqualStringRule<N, RULE>>; |
| 23 | + |
| 24 | +/// A type that holds a `&'a str` value satisfying the `CountEqualRule` |
| 25 | +pub type CountEqualStr<'a, const N: usize, RULE> = Refined<CountEqualStrRule<'a, N, RULE>>; |
| 26 | + |
| 27 | +/// Rule where the count of items that satisfy the condition is equal to `N`. |
| 28 | +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
| 29 | +pub struct CountEqualRule<const N: usize, RULE: Rule, ITERABLE: Iterable> |
| 30 | +where |
| 31 | + ITERABLE: Iterable<Item = RULE::Item>, |
| 32 | +{ |
| 33 | + _phantom: std::marker::PhantomData<(RULE, ITERABLE)>, |
| 34 | +} |
| 35 | + |
| 36 | +impl<const N: usize, ITERABLE, RULE> Rule for CountEqualRule<N, RULE, ITERABLE> |
| 37 | +where |
| 38 | + ITERABLE: Iterable<Item = RULE::Item> + FromIterator<ITERABLE::Item>, |
| 39 | + RULE: Rule, |
| 40 | +{ |
| 41 | + type Item = ITERABLE; |
| 42 | + fn validate(target: Self::Item) -> crate::Result<Self::Item> { |
| 43 | + let mut count = 0; |
| 44 | + let mut deque = VecDeque::new(); |
| 45 | + for item in target.into_iterator() { |
| 46 | + match RULE::validate(item) { |
| 47 | + Ok(item) => { |
| 48 | + deque.push_back(item); |
| 49 | + count += 1 |
| 50 | + } |
| 51 | + Err(e) => { |
| 52 | + deque.push_back(e.into_value()); |
| 53 | + } |
| 54 | + } |
| 55 | + } |
| 56 | + let target = ITERABLE::from_iter(deque); |
| 57 | + if count == N { |
| 58 | + Ok(target) |
| 59 | + } else { |
| 60 | + Err(Error::new( |
| 61 | + target, |
| 62 | + format!("count is not equal to {}, actual count is {}", N, count), |
| 63 | + )) |
| 64 | + } |
| 65 | + } |
| 66 | +} |
| 67 | + |
| 68 | +/// Rule where the count of items in the `Vec` that satisfy the condition is equal to `N`. |
| 69 | +pub type CountEqualVecRule<const N: usize, RULE> = |
| 70 | + CountEqualRule<N, RULE, Vec<<RULE as Rule>::Item>>; |
| 71 | + |
| 72 | +/// Rule where the count of items in the `VecDeque` that satisfy the condition is equal to `N`. |
| 73 | +pub type CountEqualVecDequeRule<const N: usize, RULE> = |
| 74 | + CountEqualRule<N, RULE, VecDeque<<RULE as Rule>::Item>>; |
| 75 | + |
| 76 | +/// Rule where the count of items in the `HashMap` that satisfy the condition is equal to `N`. |
| 77 | +pub type CountEqualHashMapRule<const N: usize, RULE, K> = |
| 78 | + CountEqualRule<N, RULE, std::collections::HashMap<K, <RULE as Rule>::Item>>; |
| 79 | + |
| 80 | +/// Rule where the count of items in the `HashSet` that satisfy the condition is equal to `N`. |
| 81 | +pub type CountEqualHashSetRule<const N: usize, RULE, K> = |
| 82 | + CountEqualRule<N, RULE, std::collections::HashSet<K>>; |
| 83 | + |
| 84 | +/// Rule where the count of items in the `String` that satisfy the condition is equal to `N`. |
| 85 | +pub type CountEqualStringRule<const N: usize, RULE> = CountEqualRule<N, RULE, String>; |
| 86 | + |
| 87 | +/// Rule where the count of items in the `&'a str` that satisfy the condition is equal to `N`. |
| 88 | +pub type CountEqualStrRule<'a, const N: usize, RULE> = CountEqualRule<N, RULE, &'a str>; |
| 89 | + |
| 90 | +#[cfg(test)] |
| 91 | +mod tests { |
| 92 | + use crate::result::Error; |
| 93 | + use crate::rule::{CountEqualVec, NonEmptyStringRule}; |
| 94 | + |
| 95 | + #[test] |
| 96 | + fn count_equal_1() -> Result<(), Error<Vec<String>>> { |
| 97 | + let value = vec!["good morning".to_string(), "hello".to_string()]; |
| 98 | + let count_equal = CountEqualVec::<2, NonEmptyStringRule>::new(value.clone())?; |
| 99 | + assert_eq!(count_equal.into_value(), value); |
| 100 | + Ok(()) |
| 101 | + } |
| 102 | +} |
0 commit comments