Skip to content

Commit fc00172

Browse files
authored
Merge pull request #6 from tomoikey/refactioring
Refactioring
2 parents ff9db88 + 8c09f95 commit fc00172

18 files changed

+164
-560
lines changed

README.md

+35-79
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ use refined_type::rule::MinMaxU8Rule;
1313
use refined_type::Refined;
1414
use std::ops::Deref;
1515

16-
fn main() {
17-
let rule = MinMaxU8Rule::new(1, 6).unwrap();
16+
type NonEmptyString = Refined<NonEmptyStringRule>;
1817

19-
let five = Refined::new(5, &rule);
20-
assert_eq!(five.deref(), 5);
18+
fn main() {
19+
let hello_world = NonEmptyString::new("hello world".to_string());
20+
assert_eq!(five.deref(), "hello world");
2121

22-
let eight = Refined::new(8, &rule);
22+
let empty_string = NonEmptyString::new("".to_string());
2323
assert!(eight.is_err());
2424
}
2525
```
@@ -37,42 +37,15 @@ Once the definition is complete, all you need to do is implement the Rule trait.
3737
Add your preferred conditions as you like.
3838

3939
```rust
40-
use refined_type::rule::Rule;
41-
use refined_type::result::Error;
40+
use refined_type::rule::{NonEmptyString, NonEmptyStringRule};
4241
use refined_type::Refined;
4342

44-
struct BiggerRule {
45-
than: u32
46-
}
47-
48-
impl BiggerRule {
49-
pub fn new(than: u32) -> Self {
50-
Self { than }
51-
}
52-
}
53-
54-
impl Rule for BiggerRule {
55-
type Item = u32;
56-
fn validate(&self, target: Self::Item) -> Result<Self::Item, Error<Self::Item>> {
57-
if target > self.than {
58-
Ok(target)
59-
}
60-
else {
61-
Err(Error::new(
62-
format!("{} is not bigger than {}", target, self.than)
63-
))
64-
}
65-
}
66-
}
67-
6843
fn main() {
69-
let bigger_than_five_rule = BiggerRule::new(5);
44+
let non_empty_string_result = Refined::<NonEmptyStringRule>::new("Hello World".to_string());
45+
assert_eq!(non_empty_string_result.unwrap().deref(), "Hello World");
7046

71-
let bigger_than_five_result_ok = Refined::new(7, &bigger_than_five_rule);
72-
let bigger_than_five_result_err = Refined::new(3, &bigger_than_five_rule);
73-
74-
assert!(bigger_than_five_result_ok.is_ok());
75-
assert!(bigger_than_five_result_err.is_err());
47+
let empty_string_result = Refined::<NonEmptyStringRule>::new("".to_string());
48+
assert!(empty_string_result.is_err())
7649
}
7750
```
7851

@@ -96,7 +69,7 @@ struct ContainsWorldRule;
9669
impl Rule for ContainsHelloRule {
9770
type Item = String;
9871

99-
fn validate(&self, target: Self::Item) -> Result<Self::Item, Error<Self::Item>> {
72+
fn validate(target: Self::Item) -> Result<Self::Item, Error<Self::Item>> {
10073
if target.contains("Hello") {
10174
Ok(target)
10275
}
@@ -109,7 +82,7 @@ impl Rule for ContainsHelloRule {
10982
impl Rule for ContainsWorldRule {
11083
type Item = String;
11184

112-
fn validate(&self, target: Self::Item) -> Result<Self::Item, Error<Self::Item>> {
85+
fn validate(target: Self::Item) -> Result<Self::Item, Error<Self::Item>> {
11386
if target.contains("World") {
11487
Ok(target)
11588
}
@@ -125,12 +98,12 @@ impl Rule for ContainsWorldRule {
12598
It is generally effective when you want to narrow down the condition range.
12699
```rust
127100
fn main() {
128-
let rule = And::new(ContainsHelloRule, ContainsWorldRule);
101+
type HelloAndWorldRule = And<ContainsHelloRule, ContainsWorldRule>;
129102

130-
let rule_ok = Refined::new("Hello! World!".to_string(), &rule);
103+
let rule_ok = Refind::<HelloAndWorldRule>::new("Hello! World!".to_string());
131104
assert!(rule_ok.is_ok());
132105

133-
let rule_err = Refined::new("Hello, world!".to_string(), &rule);
106+
let rule_err = Refined::<HelloAndWorldRule>::new("Hello, world!".to_string());
134107
assert!(rule_err.is_err());
135108
}
136109
```
@@ -140,15 +113,15 @@ fn main() {
140113
It is generally effective when you want to expand the condition range.
141114
```rust
142115
fn main() {
143-
let rule = Or::new(ContainsHelloRule, ContainsWorldRule);
116+
type HelloOrWorldRule = Or<ContainsHelloRule, ContainsWorldRule>;
144117

145-
let rule_ok_1 = Refined::new("Hello! World!".to_string(), &rule);
118+
let rule_ok_1 = Refined::<HelloOrWorldRule>::new("Hello! World!".to_string());
146119
assert!(rule_ok_1.is_ok());
147120

148-
let rule_ok_2 = Refined::new("hello World!".to_string(), &rule);
121+
let rule_ok_2 = Refined::<HelloOrWorldRule>::new("hello World!".to_string());
149122
assert!(rule_ok_2.is_ok());
150123

151-
let rule_err = Refined::new("hello, world!".to_string(), &rule);
124+
let rule_err = Refined::<HelloOrWorldRule>::new("hello, world!".to_string());
152125
assert!(rule_err.is_err());
153126
}
154127
```
@@ -158,12 +131,12 @@ fn main() {
158131
It is generally effective when you want to discard only certain situations.
159132
```rust
160133
fn main() {
161-
let rule = Not::new(ContainsHelloRule);
134+
type NotHelloRule = Not<ContainsHelloRule>;
162135

163-
let rule_ok = Refined::new("hello! World!".to_string(), &rule);
136+
let rule_ok = Refined::<NotHelloRule>::new("hello! World!".to_string());
164137
assert!(rule_ok.is_ok());
165138

166-
let rule_err = Refined::new("Hello, World!".to_string(), &rule);
139+
let rule_err = Refined::<NotHelloRule>::new("Hello, World!".to_string());
167140
assert!(rule_err.is_err());
168141
}
169142
```
@@ -173,37 +146,20 @@ Rule Composer is also a rule.
173146
Therefore, it can be treated much like a composite function
174147
```rust
175148
fn main() {
176-
let less_than_3 = LessI8Rule::new(3);
177-
let more_than_1 = MoreI8Rule::new(1);
178-
179-
// (1 <= x <= 3)
180-
let more_than_1_and_less_than_3 = And::new(less_than_3, more_than_1);
181-
182-
assert!(more_than_1_and_less_than_3.validate(0).is_err());
183-
assert!(more_than_1_and_less_than_3.validate(2).is_ok());
184-
assert!(more_than_1_and_less_than_3.validate(4).is_err());
185-
186-
let more_than_5 = MoreI8Rule::new(5);
187-
188-
// (1 <= x <= 3) or (5 <= x)
189-
let or_more_than_5 = Or::new(more_than_1_and_less_than_3, more_than_5);
149+
struct StartWithHelloRule;
150+
struct StartWithByeRule;
190151

191-
assert!(or_more_than_5.validate(0).is_err());
192-
assert!(or_more_than_5.validate(2).is_ok());
193-
assert!(or_more_than_5.validate(4).is_err());
194-
assert!(or_more_than_5.validate(5).is_ok());
195-
assert!(or_more_than_5.validate(100).is_ok());
152+
struct EndWithJohnRule;
196153

197-
let more_than_7 = MoreI8Rule::new(7);
154+
type StartWithHelloOrByeRule = Or<StartWithHelloRule, StartWithByeRule>;
155+
type GreetingRule = And<StartWithHelloOrByeRule, EndWithJohnRule>;
198156

199-
// ((1 <= x <= 3) or (5 <= x)) & (x < 7)
200-
let not_more_than_7 = And::new(or_more_than_5, Not::new(more_than_7));
157+
type Greeting = Refined<GreetingRule>;
201158

202-
assert!(not_more_than_7.validate(0).is_err());
203-
assert!(not_more_than_7.validate(2).is_ok());
204-
assert!(not_more_than_7.validate(4).is_err());
205-
assert!(not_more_than_7.validate(5).is_ok());
206-
assert!(not_more_than_7.validate(100).is_err());
159+
assert!(GreetingRule::validate("Hello! Nice to meet you John".to_string()).is_ok());
160+
assert!(Greeting::validate("Bye! Have a good day John".to_string()).is_ok());
161+
assert!(Greeting::validate("How are you? Have a good day John".to_string()).is_err());
162+
assert!(Greeting::validate("Bye! Have a good day Tom".to_string()).is_err());
207163
}
208164
```
209165

@@ -212,15 +168,15 @@ Directly writing `And`, `Or`, `Not` or `Refined` can often lead to a decrease in
212168
Therefore, using **type aliases** can help make your code clearer.
213169

214170
```rust
215-
type ContainsHelloAndWorldRule = And<String, ContainsHelloRule, ContainsWorldRule>;
171+
type ContainsHelloAndWorldRule = And<ContainsHelloRule, ContainsWorldRule>;
216172

217-
type ContainsHelloAndWorld = Refined<ContainsHelloAndWorldRule, String>;
173+
type ContainsHelloAndWorld = Refined<ContainsHelloAndWorldRule>;
218174
```
219175

220176
# License
221177
MIT License
222178

223-
Copyright (c) 2023 Tomoki Someya
179+
Copyright (c) 2024 Tomoki Someya
224180

225181
Permission is hereby granted, free of charge, to any person obtaining a copy
226182
of this software and associated documentation files (the "Software"), to deal

src/refined.rs

+15-74
Original file line numberDiff line numberDiff line change
@@ -11,48 +11,34 @@ use std::ops::Deref;
1111
/// use refined_type::rule::{NonEmptyString, NonEmptyStringRule};
1212
/// use refined_type::Refined;
1313
///
14-
/// let non_empty_string_result = Refined::new("Hello World".to_string(), &NonEmptyStringRule::default());
14+
/// let non_empty_string_result = Refined::<NonEmptyStringRule>::new("Hello World".to_string());
1515
/// assert_eq!(non_empty_string_result.unwrap().deref(), "Hello World");
1616
///
17-
/// let empty_string_result = Refined::new("".to_string(), &NonEmptyStringRule::default());
17+
/// let empty_string_result = Refined::<NonEmptyStringRule>::new("".to_string());
1818
/// assert!(empty_string_result.is_err())
1919
/// ```
2020
#[derive(Debug, PartialEq, Eq, Clone)]
21-
pub struct Refined<RULE, T> {
22-
value: T,
23-
_rule: PhantomData<RULE>,
24-
}
25-
26-
impl<RULE, T> Refined<RULE, T>
21+
pub struct Refined<RULE>
2722
where
28-
RULE: Rule<Item = T>,
23+
RULE: Rule,
2924
{
30-
pub fn new(value: T, rule: &RULE) -> Result<Self, Error<T>> {
31-
Ok(Self {
32-
value: RULE::validate(rule, value)?,
33-
_rule: Default::default(),
34-
})
35-
}
25+
value: RULE::Item,
26+
_rule: PhantomData<RULE>,
3627
}
3728

38-
impl<RULE, ITERATOR, T> Refined<RULE, ITERATOR>
29+
impl<RULE, T> Refined<RULE>
3930
where
4031
RULE: Rule<Item = T>,
41-
ITERATOR: IntoIterator<Item = T> + FromIterator<T>,
4232
{
43-
pub fn from_iter(value: ITERATOR, rule: &RULE) -> Result<Self, Error<T>> {
44-
let mut result = Vec::new();
45-
for i in value.into_iter() {
46-
result.push(RULE::validate(rule, i)?)
47-
}
33+
pub fn new(value: T) -> Result<Self, Error<T>> {
4834
Ok(Self {
49-
value: result.into_iter().collect(),
35+
value: RULE::validate(value)?,
5036
_rule: Default::default(),
5137
})
5238
}
5339
}
5440

55-
impl<RULE, T> Deref for Refined<RULE, T>
41+
impl<RULE, T> Deref for Refined<RULE>
5642
where
5743
RULE: Rule<Item = T>,
5844
{
@@ -63,8 +49,9 @@ where
6349
}
6450
}
6551

66-
impl<RULE, T> Display for Refined<RULE, T>
52+
impl<RULE, T> Display for Refined<RULE>
6753
where
54+
RULE: Rule<Item = T>,
6855
T: Display,
6956
{
7057
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
@@ -77,70 +64,24 @@ mod test {
7764
use crate::refined::Refined;
7865
use crate::result::Error;
7966
use crate::rule::NonEmptyStringRule;
80-
use std::collections::HashSet;
8167

8268
#[test]
8369
fn test_refined_non_empty_string_ok() -> Result<(), Error<String>> {
84-
let non_empty_string = Refined::new("Hello".to_string(), &NonEmptyStringRule::default())?;
70+
let non_empty_string = Refined::<NonEmptyStringRule>::new("Hello".to_string())?;
8571
assert_eq!(non_empty_string.value, "Hello");
8672
Ok(())
8773
}
8874

8975
#[test]
9076
fn test_refined_non_empty_string_err() -> Result<(), String> {
91-
let non_empty_string = Refined::new("".to_string(), &NonEmptyStringRule::default());
77+
let non_empty_string = Refined::<NonEmptyStringRule>::new("".to_string());
9278
assert!(non_empty_string.is_err());
9379
Ok(())
9480
}
9581

96-
#[test]
97-
fn test_refined_array_of_non_empty_string_ok() -> Result<(), Error<String>> {
98-
let strings = vec![
99-
"Good Morning".to_string(),
100-
"Hello".to_string(),
101-
"Good Evening".to_string(),
102-
];
103-
let array_non_empty_string =
104-
Refined::from_iter(strings.clone(), &NonEmptyStringRule::default())?;
105-
assert_eq!(array_non_empty_string.value, strings);
106-
Ok(())
107-
}
108-
109-
#[test]
110-
fn test_refined_hash_set_of_non_empty_string_ok() -> Result<(), Error<String>> {
111-
let mut set = HashSet::new();
112-
vec![
113-
"Good Morning".to_string(),
114-
"Hello".to_string(),
115-
"Good Evening".to_string(),
116-
]
117-
.into_iter()
118-
.for_each(|n| {
119-
set.insert(n);
120-
});
121-
122-
let array_non_empty_string =
123-
Refined::from_iter(set.clone(), &NonEmptyStringRule::default())?;
124-
assert_eq!(array_non_empty_string.value, set);
125-
Ok(())
126-
}
127-
128-
#[test]
129-
fn test_refined_array_of_non_empty_string_err() -> Result<(), String> {
130-
let strings = vec![
131-
"Good Morning".to_string(),
132-
"".to_string(),
133-
"Good Evening".to_string(),
134-
];
135-
let array_non_empty_string_result =
136-
Refined::from_iter(strings.clone(), &NonEmptyStringRule::default());
137-
assert!(array_non_empty_string_result.is_err());
138-
Ok(())
139-
}
140-
14182
#[test]
14283
fn test_refined_display() -> Result<(), Error<String>> {
143-
let non_empty_string = Refined::new("Hello".to_string(), &NonEmptyStringRule::default())?;
84+
let non_empty_string = Refined::<NonEmptyStringRule>::new("Hello".to_string())?;
14485
assert_eq!(format!("{}", non_empty_string), "Hello");
14586
Ok(())
14687
}

src/rule.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
pub mod composer;
22
mod empty;
33
mod non_empty;
4-
mod number;
54
mod string;
65

76
use crate::result::Error;
87
pub use empty::*;
98
pub use non_empty::*;
10-
pub use number::*;
119
pub use string::*;
1210

1311
/// This is a `trait` that specifies the conditions a type `T` should satisfy
1412
pub trait Rule {
1513
type Item;
16-
fn validate(&self, target: Self::Item) -> Result<Self::Item, Error<Self::Item>>;
14+
fn validate(target: Self::Item) -> Result<Self::Item, Error<Self::Item>>;
1715
}

0 commit comments

Comments
 (0)