Skip to content

Commit ef1fe16

Browse files
authored
Merge pull request #33 from tomoikey/v0.5.18
Release V0.5.18
2 parents d8733c7 + 635849f commit ef1fe16

14 files changed

+667
-8
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ repository = "https://github.com/tomoikey/refined_type"
66
readme = "README.md"
77
categories = ["accessibility", "development-tools", "rust-patterns"]
88
license = "MIT"
9-
version = "0.5.17"
9+
version = "0.5.18"
1010
edition = "2021"
1111

1212
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

README.md

+52
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,58 @@ fn not_example() -> Result<(), Error<u8>> {
196196
}
197197
```
198198

199+
### 4: `If` Rule Composer
200+
201+
`If` Rule Composer is a rule that applies a specific rule only when a certain condition is met.
202+
203+
```rust
204+
type Target = Refined<If<GreaterEqualRuleI8<10>, EvenRuleI8>>;
205+
206+
fn if_example() -> Result<(), Error<i8>> {
207+
let target = Target::new(8)?;
208+
assert_eq!(target.into_value(), 8);
209+
210+
let target = Target::new(9)?;
211+
assert_eq!(target.into_value(), 9);
212+
213+
let target = Target::new(10)?;
214+
assert_eq!(target.into_value(), 10);
215+
216+
let target = Target::new(11);
217+
assert!(target.is_err());
218+
219+
Ok(())
220+
}
221+
```
222+
223+
### 5: `IfElse` Rule Composer
224+
225+
`IfElse` Rule Composer is a rule that applies a specific rule when a certain condition is met and another rule when it is not met.
226+
227+
```rust
228+
type Target = Refined<IfElse<GreaterEqualRuleI8<10>, EvenRuleI8, OddRuleI8>>;
229+
230+
fn if_else_example() -> Result<(), Error<i8>> {
231+
let target = Target::new(8);
232+
assert!(target.is_err());
233+
234+
let target = Target::new(9)?;
235+
assert_eq!(target.into_value(), 9);
236+
237+
let target = Target::new(10)?;
238+
assert_eq!(target.into_value(), 10);
239+
240+
let target = Target::new(11);
241+
assert!(target.is_err());
242+
243+
Ok(())
244+
}
245+
```
246+
247+
### 6: Other Rule Composer
248+
249+
`Equiv`, `Nand`, `Nor` and `Xor` are also available.
250+
199251
# Number
200252

201253
## `MinMax`

src/rule.rs

+25
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::result::Error;
12
pub use collection::*;
23
pub use empty::*;
34
pub use length::*;
@@ -18,3 +19,27 @@ pub trait Rule {
1819
type Item;
1920
fn validate(target: Self::Item) -> crate::Result<Self::Item>;
2021
}
22+
23+
/// This is a `Rule` that always returns `Ok`
24+
pub struct Valid<T> {
25+
_phantom: std::marker::PhantomData<T>,
26+
}
27+
28+
impl<T> Rule for Valid<T> {
29+
type Item = T;
30+
fn validate(target: Self::Item) -> crate::Result<Self::Item> {
31+
Ok(target)
32+
}
33+
}
34+
35+
/// This is a `Rule` that always returns `Err`
36+
pub struct Invalid<T> {
37+
_phantom: std::marker::PhantomData<T>,
38+
}
39+
40+
impl<T> Rule for Invalid<T> {
41+
type Item = T;
42+
fn validate(target: Self::Item) -> crate::Result<Self::Item> {
43+
Err(Error::new(target, "Invalid"))
44+
}
45+
}

src/rule/collection.rs

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mod index;
55
mod init;
66
mod iterable;
77
mod last;
8+
mod nothing;
89
mod reverse;
910
mod skip;
1011
mod tail;
@@ -16,6 +17,7 @@ pub use index::*;
1617
pub use init::*;
1718
pub use iterable::*;
1819
pub use last::*;
20+
pub use nothing::*;
1921
pub use reverse::*;
2022
pub use skip::*;
2123
pub use tail::*;

src/rule/collection/exists.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::collections::{HashMap, HashSet, VecDeque};
22

33
use crate::rule::composer::Not;
4-
use crate::rule::{ForAllRule, Rule};
4+
use crate::rule::{NothingRule, Rule};
55
use crate::Refined;
66

77
/// A type that holds a value satisfying the `ExistsRule`
@@ -23,7 +23,7 @@ pub type ExistsHashMap<K, RULE> = Refined<ExistsHashMapRule<K, RULE>>;
2323
pub type ExistsString<RULE> = Refined<ExistsStringRule<RULE>>;
2424

2525
/// Rule where at least one data in the collection satisfies the condition
26-
pub type ExistsRule<RULE, ITERABLE> = Not<ForAllRule<Not<RULE>, ITERABLE>>;
26+
pub type ExistsRule<RULE, ITERABLE> = Not<NothingRule<RULE, ITERABLE>>;
2727

2828
/// Rule where at least one data in the `Vec` satisfies the condition
2929
pub type ExistsVecRule<RULE> = ExistsRule<RULE, Vec<<RULE as Rule>::Item>>;
@@ -60,4 +60,12 @@ mod tests {
6060
assert!(exists_result.is_err());
6161
Ok(())
6262
}
63+
64+
#[test]
65+
fn exists_3() -> anyhow::Result<()> {
66+
let value = vec![];
67+
let exists_result = Exists::<NonEmptyStringRule, Vec<_>>::new(value.clone());
68+
assert!(exists_result.is_err());
69+
Ok(())
70+
}
6371
}

src/rule/collection/nothing.rs

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
use crate::rule::composer::Not;
2+
use crate::rule::{ForAllRule, Rule};
3+
use crate::Refined;
4+
use std::collections::{HashMap, HashSet, VecDeque};
5+
6+
/// A type that holds a value satisfying the `NothingRule`
7+
pub type Nothing<RULE, ITERABLE> = Refined<NothingRule<RULE, ITERABLE>>;
8+
9+
/// A type that holds a `Vec` value satisfying the `NothingRule`
10+
pub type NothingVec<RULE> = Refined<NothingVecRule<RULE>>;
11+
12+
/// A type that holds a `VecDeque` value satisfying the `NothingRule`
13+
pub type NothingVecDeque<RULE> = Refined<NothingVecDequeRule<RULE>>;
14+
15+
/// A type that holds a `HashSet` value satisfying the `NothingRule`
16+
pub type NothingHashSet<RULE> = Refined<NothingHashSetRule<RULE>>;
17+
18+
/// A type that holds a `HashMap` value satisfying the `NothingRule`
19+
pub type NothingHashMap<K, RULE> = Refined<NothingHashMapRule<K, RULE>>;
20+
21+
/// A type that holds a `String` value satisfying the `NothingRule`
22+
pub type NothingString<RULE> = Refined<NothingStringRule<RULE>>;
23+
24+
/// Rule where no data in the collection satisfies the condition
25+
pub type NothingRule<RULE, ITERABLE> = ForAllRule<Not<RULE>, ITERABLE>;
26+
27+
/// Rule where no data in the `Vec` satisfies the condition
28+
pub type NothingVecRule<RULE> = NothingRule<RULE, Vec<<RULE as Rule>::Item>>;
29+
30+
/// Rule where no data in the `VecDeque` satisfies the condition
31+
pub type NothingVecDequeRule<RULE> = NothingRule<RULE, VecDeque<<RULE as Rule>::Item>>;
32+
33+
/// Rule where no data in the `HashSet` satisfies the condition
34+
pub type NothingHashSetRule<RULE> = NothingRule<RULE, HashSet<<RULE as Rule>::Item>>;
35+
36+
/// Rule where no data in the `HashMap` satisfies the condition
37+
pub type NothingHashMapRule<K, RULE> = NothingRule<RULE, HashMap<K, <RULE as Rule>::Item>>;
38+
39+
/// Rule where no data in the `String` satisfies the condition
40+
pub type NothingStringRule<RULE> = NothingRule<RULE, String>;
41+
42+
#[cfg(test)]
43+
mod tests {
44+
use crate::result::Error;
45+
use crate::rule::{NonEmptyStringRule, NothingVec};
46+
47+
#[test]
48+
fn nothing_valid() -> Result<(), Error<Vec<String>>> {
49+
let table = vec![vec![], vec!["".to_string()]];
50+
51+
for value in table {
52+
let nothing = NothingVec::<NonEmptyStringRule>::new(value.clone())?;
53+
assert_eq!(nothing.into_value(), value);
54+
}
55+
56+
Ok(())
57+
}
58+
59+
#[test]
60+
fn nothing_invalid() -> anyhow::Result<()> {
61+
let table = vec![
62+
vec!["good morning".to_string(), "hello".to_string()],
63+
vec!["good morning".to_string()],
64+
];
65+
66+
for value in table {
67+
let nothing_result = NothingVec::<NonEmptyStringRule>::new(value.clone());
68+
assert!(nothing_result.is_err());
69+
}
70+
71+
Ok(())
72+
}
73+
}

src/rule/composer.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,19 @@
11
mod and;
2+
mod equiv;
3+
mod if_else;
4+
mod imply;
5+
mod nand;
6+
mod nor;
27
mod not;
38
mod or;
9+
mod xor;
410

511
pub use and::And;
12+
pub use equiv::Equiv;
13+
pub use if_else::IfElse;
14+
pub use imply::{If, Imply};
15+
pub use nand::Nand;
16+
pub use nor::Nor;
617
pub use not::Not;
718
pub use or::Or;
19+
pub use xor::Xor;

src/rule/composer/equiv.rs

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use crate::rule::composer::imply::Imply;
2+
use crate::And;
3+
4+
/// This is a type that represents logical equivalence in logic.
5+
///
6+
/// # Example
7+
/// ```rust
8+
/// use refined_type::rule::composer::Equiv;
9+
/// use refined_type::rule::{EvenRuleI8, GreaterEqualRuleI8, Rule};
10+
///
11+
/// type Target = Equiv<GreaterEqualRuleI8<10>, EvenRuleI8>;
12+
///
13+
/// for value in vec![1, 10] {
14+
/// assert!(Target::validate(value).is_ok());
15+
/// }
16+
///
17+
/// for value in vec![2, 4] {
18+
/// assert!(Target::validate(value).is_err());
19+
/// }
20+
/// ```
21+
pub type Equiv<RULE1, RULE2> = And![Imply<RULE1, RULE2>, Imply<RULE2, RULE1>];
22+
23+
#[cfg(test)]
24+
mod test {
25+
use crate::rule::composer::Equiv;
26+
use crate::rule::{EvenRuleI8, GreaterEqualRuleI8, Rule};
27+
28+
type Target = Equiv<GreaterEqualRuleI8<10>, EvenRuleI8>;
29+
30+
#[test]
31+
fn test_rule_binder_ok() {
32+
let table = vec![1, 10];
33+
34+
for value in table {
35+
assert!(Target::validate(value).is_ok());
36+
}
37+
}
38+
39+
#[test]
40+
fn test_rule_binder_err() {
41+
let table = vec![2, 4];
42+
43+
for value in table {
44+
assert!(Target::validate(value).is_err());
45+
}
46+
}
47+
}

src/rule/composer/if_else.rs

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use crate::rule::composer::Not;
2+
use crate::{And, Or};
3+
4+
/// This is a type that represents logical if-else in logic.
5+
/// # Example
6+
/// ```rust
7+
/// use refined_type::rule::composer::IfElse;
8+
///
9+
/// use refined_type::rule::{EvenRuleI8, GreaterEqualRuleI8, OddRuleI8, Rule};
10+
///
11+
/// type Target = IfElse<GreaterEqualRuleI8<10>, EvenRuleI8, OddRuleI8>;
12+
///
13+
/// for value in vec![1, 10] {
14+
/// assert!(Target::validate(value).is_ok());
15+
/// }
16+
///
17+
/// for value in vec![2, 11] {
18+
/// assert!(Target::validate(value).is_err());
19+
/// }
20+
/// ```
21+
pub type IfElse<CONDITION, THEN, ELSE> = Or![And![CONDITION, THEN], And![Not<CONDITION>, ELSE]];
22+
23+
#[cfg(test)]
24+
mod test {
25+
use crate::rule::composer::IfElse;
26+
use crate::rule::{EvenRuleI8, GreaterEqualRuleI8, OddRuleI8, Rule};
27+
28+
type Target = IfElse<GreaterEqualRuleI8<10>, EvenRuleI8, OddRuleI8>;
29+
30+
#[test]
31+
fn test_rule_binder_ok() {
32+
let table = vec![1, 10];
33+
34+
for value in table {
35+
assert!(Target::validate(value).is_ok());
36+
}
37+
}
38+
39+
#[test]
40+
fn test_rule_binder_err() {
41+
let table = vec![2, 11];
42+
43+
for value in table {
44+
assert!(Target::validate(value).is_err());
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)