Skip to content

Commit

Permalink
Merge pull request #23 from tomoikey/feat/less_greater_than
Browse files Browse the repository at this point in the history
Feat/less greater than
  • Loading branch information
tomoikey authored Oct 29, 2024
2 parents 0014a61 + d04f6b1 commit 4aca032
Show file tree
Hide file tree
Showing 10 changed files with 254 additions and 40 deletions.
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@ repository = "https://github.com/tomoikey/refined-type"
readme = "README.md"
categories = ["accessibility", "development-tools", "rust-patterns"]
license = "MIT"
version = "0.5.12"
version = "0.5.13"
edition = "2021"

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

[dependencies]
paste = "1.0.15"
regex = "1.11.0"
serde = { version = "1.0.210", features = ["derive"] }
regex = "1.11.1"
serde = { version = "1.0.214", features = ["derive"] }

[dev-dependencies]
anyhow = "1.0.89"
Expand Down
97 changes: 67 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,73 @@ fn equal_example() -> Result<(), Error<u8>> {
}
```

## `LessEqual`

`LessEqual` is a type that signifies the target is less than or equal to a certain number.

```rust
type Age = LessEqualU8<80>;

fn less_equal_example() -> Result<(), Error<u8>> {
let age = Age::new(79)?;
assert_eq!(age.into_value(), 79);

let age = Age::new(80)?;
assert_eq!(age.into_value(), 80);

let age = Age::new(81);
assert!(age.is_err());

Ok(())
}
```

## `GreaterEqual`

`GreaterEqual` is a type that signifies the target is greater than or equal to a certain number.

```rust
type Age = GreaterEqualU8<18>;

fn greater_equal_example() -> Result<(), Error<u8>> {
let age = Age::new(19)?;
assert_eq!(age.into_value(), 19);

let age = Age::new(18)?;
assert_eq!(age.into_value(), 18);

let age = Age::new(17);
assert!(age.is_err());

Ok(())
}
```

## `Range`

`Range` is a type that signifies the target exists between a certain number and another number.

```rust
type Age = RangeU8<18, 80>;

fn range_example() -> Result<(), Error<u8>> {
let age = Age::new(17);
assert!(age.is_err());

let age = Age::new(18)?;
assert_eq!(age.into_value(), 18);

let age = Age::new(79)?;
assert_eq!(age.into_value(), 79);

let age = Age::new(80);
assert!(age.is_err());

Ok(())
}
```


# Iterator

`refined_type` has several useful refined types for Iterators.
Expand Down Expand Up @@ -604,36 +671,6 @@ impl<ITEM> SkipOption for NoSkip<ITEM> {
}
```

---

## `into_iter()` and `iter()`

The Iterator I’ve prepared has `into_iter` and `iter` implemented.
Therefore, you can easily map or convert it to a different Iterator using `collect`.
Feel free to explore the capabilities of the Iterator you’ve been given!

### `into_iter()`

```rust
fn example_20() -> anyhow::Result<()> {
let ne_vec = NonEmptyVec::new(vec![1, 2, 3])?;
let ne_vec: NonEmptyVec<i32> = ne_vec.into_iter().map(|n| n * 2).map(|n| n * 3).collect();
assert_eq!(ne_vec.into_value(), vec![6, 12, 18]);
Ok(())
}
```

### `iter()`

```rust
fn example_21() -> anyhow::Result<()> {
let ne_vec = NonEmptyVec::new(vec![1, 2, 3])?;
let ne_vec: NonEmptyVec<i32> = ne_vec.iter().map(|n| n * 2).map(|n| n * 3).collect();
assert_eq!(ne_vec.into_value(), vec![6, 12, 18]);
Ok(())
}
```

### `NonEmptyVec` to `NonEmptyVecDeque` using `collect()`

```rust
Expand Down
6 changes: 6 additions & 0 deletions src/rule/number.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
mod equal;
mod even;
mod greater;
mod greater_equal;
mod less;
mod less_equal;
mod min_max;
mod odd;
mod range;

pub use equal::*;
pub use even::*;
pub use greater::*;
pub use greater_equal::*;
pub use less::*;
pub use less_equal::*;
pub use min_max::*;
pub use odd::*;
pub use range::*;
2 changes: 2 additions & 0 deletions src/rule/number/greater.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
macro_rules! define_greater_rule {
($t: ty) => {
$crate::paste::item! {
/// A type that holds a value satisfying the `GreaterRule`
pub type [<Greater $t:camel>]<const THAN: $t> = $crate::Refined<[<GreaterRule $t:camel>]<THAN>>;

/// Rule where the target value must be greater than `THAN`
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct [<GreaterRule $t:camel>]<const THAN: $t>;

Expand Down
34 changes: 34 additions & 0 deletions src/rule/number/greater_equal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
macro_rules! declare_greater_equal_rule {
($ty: ty) => {
$crate::paste::item! {
/// A type that holds a value satisfying the `GreaterEqualRule`
pub type [<GreaterEqual $ty:camel>]<const N: $ty> = $crate::Refined<[<GreaterEqualRule $ty:camel>]<N>>;

/// Rule where the target value must be greater than or equal to `N`
pub type [<GreaterEqualRule $ty:camel>]<const N: $ty> = $crate::Or![$crate::rule::[<EqualRule $ty:camel>]<N>, $crate::rule::[<GreaterRule $ty:camel>]<N>];
}
};
($t: ty, $($ts: ty),+) => {
declare_greater_equal_rule!($t);
declare_greater_equal_rule!($($ts), +);
};
}

declare_greater_equal_rule!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);

#[cfg(test)]
mod test {
use crate::rule::GreaterEqualU8;

#[test]
fn test_greater_equal_than_50u8_ok() {
let greater_equal_result = GreaterEqualU8::<50>::new(50);
assert!(greater_equal_result.is_ok());
}

#[test]
fn test_greater_equal_than_50u8_err() {
let greater_equal_result = GreaterEqualU8::<50>::new(49);
assert!(greater_equal_result.is_err());
}
}
2 changes: 2 additions & 0 deletions src/rule/number/less.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
macro_rules! define_less_rule {
($t: ty) => {
$crate::paste::item! {
/// A type that holds a value satisfying the `LessRule`
pub type [<Less $t:camel>]<const THAN: $t> = $crate::Refined<[<LessRule $t:camel>]<THAN>>;

/// Rule where the target value must be less than `THAN`
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct [<LessRule $t:camel>]<const THAN: $t>;

Expand Down
34 changes: 34 additions & 0 deletions src/rule/number/less_equal.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
macro_rules! declare_less_equal_rule {
($ty: ty) => {
$crate::paste::item! {
/// A type that holds a value satisfying the `LessEqualRule`
pub type [<LessEqual $ty:camel>]<const N: $ty> = $crate::Refined<[<LessEqualRule $ty:camel>]<N>>;

/// Rule where the target value must be less than or equal to `N`
pub type [<LessEqualRule $ty:camel>]<const N: $ty> = $crate::Or![$crate::rule::[<EqualRule $ty:camel>]<N>, $crate::rule::[<LessRule $ty:camel>]<N>];
}
};
($t: ty, $($ts: ty),+) => {
declare_less_equal_rule!($t);
declare_less_equal_rule!($($ts), +);
};
}

declare_less_equal_rule!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize);

#[cfg(test)]
mod test {
use crate::rule::LessEqualU8;

#[test]
fn test_less_equal_than_50u8_ok() {
let less_equal_result = LessEqualU8::<50>::new(50);
assert!(less_equal_result.is_ok());
}

#[test]
fn test_less_equal_than_50u8_err() {
let less_equal_result = LessEqualU8::<50>::new(51);
assert!(less_equal_result.is_err());
}
}
8 changes: 5 additions & 3 deletions src/rule/number/min_max.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
macro_rules! define_min_max_rule {
($t: ty) => {
$crate::paste::item! {
/// A type that holds a value satisfying the `MinMaxRule`
pub type [<MinMax $t:camel>]<const MIN: $t, const MAX: $t> = $crate::Refined<[<MinMaxRule $t:camel>]<MIN, MAX>>;

pub type [<MinMaxRule $t:camel>]<const MIN: $t, const MAX: $t> = $crate::And![
$crate::Or![$crate::rule::[<EqualRule $t:camel>]<MIN>, $crate::rule::[<GreaterRule $t:camel>]<MIN>],
$crate::Or![$crate::rule::[<EqualRule $t:camel>]<MAX>, $crate::rule::[<LessRule $t:camel>]<MAX>]
/// Rule where the target value must be greater than or equal to `MIN` and less than or equal to `MAX`
pub type [<MinMaxRule $t:camel>]<const MIN: $t, const MAX: $t> = $crate::Or![
$crate::rule::[<RangeRule $t:camel>]<MIN, MAX>,
$crate::rule::[<EqualRule $t:camel>]<MAX>
];
}
};
Expand Down
46 changes: 46 additions & 0 deletions src/rule/number/range.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
macro_rules! define_range_rule {
($t: ty) => {
$crate::paste::item! {
/// A type that holds a value satisfying the `RangeRule`
pub type [<Range $t:camel>]<const FROM: $t, const UNTIL: $t> = $crate::Refined<[<RangeRule $t:camel>]<FROM, UNTIL>>;

/// Rule where the target value must be greater than or equal to `FROM` and less than `UNTIL`
pub type [<RangeRule $t:camel>]<const FROM: $t, const UNTIL: $t> = $crate::And![
$crate::rule::[<GreaterEqualRule $t:camel>]<FROM>,
$crate::rule::[<LessRule $t:camel>]<UNTIL>
];
}
};
($t: ty, $($ts: ty),+) => {
define_range_rule!($t);
define_range_rule!($($ts), +);
};
}

define_range_rule!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize);

#[cfg(test)]
mod test {
use crate::rule::RangeI8;

#[test]
fn test_range_i8_ok() {
let range_result = RangeI8::<1, 10>::new(0);
assert!(range_result.is_err());

let range_result = RangeI8::<1, 10>::new(1);
assert!(range_result.is_ok());

let range_result = RangeI8::<1, 10>::new(10);
assert!(range_result.is_err());
}

#[test]
fn test_range_i8_err() {
let range_result = RangeI8::<1, 10>::new(-1);
assert!(range_result.is_err());

let range_result = RangeI8::<1, 10>::new(11);
assert!(range_result.is_err());
}
}
59 changes: 55 additions & 4 deletions tests/read_me.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ use serde_json::json;
use refined_type::result::Error;
use refined_type::rule::composer::Not;
use refined_type::rule::{
EqualU8, ExistsVec, ForAllVec, GreaterU8, HeadVec, IndexRuleVec, IndexVec, InitVec, LastVec,
LengthDefinition, LengthEqual, LengthEqualRule, LengthGreater, LengthLess, LengthMinMax,
LessU8, MinMaxU8, NonEmptyString, NonEmptyStringRule, NonEmptyVec, NonEmptyVecDeque, Reverse,
Rule, SkipFirst, SkipVec, TailVec,
EqualU8, ExistsVec, ForAllVec, GreaterEqualU8, GreaterU8, HeadVec, IndexRuleVec, IndexVec,
InitVec, LastVec, LengthDefinition, LengthEqual, LengthEqualRule, LengthGreater, LengthLess,
LengthMinMax, LessEqualU8, LessU8, MinMaxU8, NonEmptyString, NonEmptyStringRule, NonEmptyVec,
NonEmptyVecDeque, RangeU8, Reverse, Rule, SkipFirst, SkipVec, TailVec,
};
use refined_type::{And, Or, Refined};

Expand Down Expand Up @@ -312,6 +312,57 @@ fn equal_example() -> Result<(), Error<u8>> {
Ok(())
}

#[test]
fn less_equal_example() -> Result<(), Error<u8>> {
type Age = LessEqualU8<80>;

let age = Age::new(79)?;
assert_eq!(age.into_value(), 79);

let age = Age::new(80)?;
assert_eq!(age.into_value(), 80);

let age = Age::new(81);
assert!(age.is_err());

Ok(())
}

#[test]
fn greater_equal_example() -> Result<(), Error<u8>> {
type Age = GreaterEqualU8<18>;

let age = Age::new(19)?;
assert_eq!(age.into_value(), 19);

let age = Age::new(18)?;
assert_eq!(age.into_value(), 18);

let age = Age::new(17);
assert!(age.is_err());

Ok(())
}

#[test]
fn range_example() -> Result<(), Error<u8>> {
type Age = RangeU8<18, 80>;

let age = Age::new(17);
assert!(age.is_err());

let age = Age::new(18)?;
assert_eq!(age.into_value(), 18);

let age = Age::new(79)?;
assert_eq!(age.into_value(), 79);

let age = Age::new(80);
assert!(age.is_err());

Ok(())
}

#[test]
fn example_11() -> Result<(), Error<Vec<String>>> {
let vec = vec!["Hello".to_string(), "World".to_string()];
Expand Down

0 comments on commit 4aca032

Please sign in to comment.