Skip to content

Commit ddcb3df

Browse files
committed
implement CountEqual
1 parent b5cbf40 commit ddcb3df

File tree

3 files changed

+107
-0
lines changed

3 files changed

+107
-0
lines changed

src/rule/collection.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod count;
12
mod exists;
23
mod for_all;
34
mod head;
@@ -10,6 +11,7 @@ mod reverse;
1011
mod skip;
1112
mod tail;
1213

14+
pub use count::*;
1315
pub use exists::*;
1416
pub use for_all::*;
1517
pub use head::*;

src/rule/collection/count.rs

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
mod equal;
2+
3+
pub use equal::*;

src/rule/collection/count/equal.rs

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
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

Comments
 (0)