Skip to content

Commit

Permalink
add various logic type
Browse files Browse the repository at this point in the history
  • Loading branch information
tomoikey committed Nov 10, 2024
1 parent c42c333 commit 03cea9c
Show file tree
Hide file tree
Showing 7 changed files with 418 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/rule.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::result::Error;
pub use collection::*;
pub use empty::*;
pub use length::*;
Expand All @@ -18,3 +19,27 @@ pub trait Rule {
type Item;
fn validate(target: Self::Item) -> crate::Result<Self::Item>;
}

/// This is a `Rule` that always returns `Ok`
pub struct Valid<T> {
_phantom: std::marker::PhantomData<T>,
}

impl<T> Rule for Valid<T> {
type Item = T;
fn validate(target: Self::Item) -> crate::Result<Self::Item> {
Ok(target)
}
}

/// This is a `Rule` that always returns `Err`
pub struct Invalid<T> {
_phantom: std::marker::PhantomData<T>,
}

impl<T> Rule for Invalid<T> {
type Item = T;
fn validate(target: Self::Item) -> crate::Result<Self::Item> {
Err(Error::new(target, "Invalid"))
}
}
10 changes: 10 additions & 0 deletions src/rule/composer.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
mod and;
mod equiv;
mod imply;
mod nand;
mod nor;
mod not;
mod or;
mod xor;

pub use and::And;
pub use equiv::Equiv;
pub use imply::Imply;
pub use nand::Nand;
pub use nor::Nor;
pub use not::Not;
pub use or::Or;
pub use xor::Xor;
47 changes: 47 additions & 0 deletions src/rule/composer/equiv.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use crate::rule::composer::imply::Imply;
use crate::And;

/// This is a type that represents logical equivalence in logic.
///
/// # Example
/// ```rust
/// use refined_type::rule::composer::Equiv;
/// use refined_type::rule::{EvenRuleI8, GreaterEqualRuleI8, Rule};
///
/// type Target = Equiv<GreaterEqualRuleI8<10>, EvenRuleI8>;
///
/// for value in vec![1, 10] {
/// assert!(Target::validate(value).is_ok());
/// }
///
/// for value in vec![2, 4] {
/// assert!(Target::validate(value).is_err());
/// }
/// ```
pub type Equiv<RULE1, RULE2> = And![Imply<RULE1, RULE2>, Imply<RULE2, RULE1>];

#[cfg(test)]
mod test {
use crate::rule::composer::Equiv;
use crate::rule::{EvenRuleI8, GreaterEqualRuleI8, Rule};

type Target = Equiv<GreaterEqualRuleI8<10>, EvenRuleI8>;

#[test]
fn test_rule_binder_ok() {
let table = vec![1, 10];

for value in table {
assert!(Target::validate(value).is_ok());
}
}

#[test]
fn test_rule_binder_err() {
let table = vec![2, 4];

for value in table {
assert!(Target::validate(value).is_err());
}
}
}
46 changes: 46 additions & 0 deletions src/rule/composer/imply.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use crate::rule::composer::Not;
use crate::Or;

/// This is a type that represents logical implication in logic.
/// By applying it to programming, you can make it function similarly to an “If-Then” statement.
/// # Example
/// ```rust
/// use refined_type::rule::composer::Imply;
/// use refined_type::rule::{EvenRuleI8, GreaterEqualRuleI8, Rule};
///
/// type IfGreaterOrEqual10ThenEven = Imply<GreaterEqualRuleI8<10>, EvenRuleI8>;
///
/// for value in vec![8, 9, 10, 12] {
/// assert!(IfGreaterOrEqual10ThenEven::validate(value).is_ok());
/// }
///
/// for value in vec![11, 13] {
/// assert!(IfGreaterOrEqual10ThenEven::validate(value).is_err());
/// }
pub type Imply<RULE1, RULE2> = Or![Not<RULE1>, RULE2];

#[cfg(test)]
mod test {
use crate::rule::composer::Imply;
use crate::rule::{EvenRuleI8, GreaterEqualRuleI8, Rule};

type IfGreaterOrEqual10ThenEven = Imply<GreaterEqualRuleI8<10>, EvenRuleI8>;

#[test]
fn test_rule_binder_ok() {
let table = vec![8, 9, 10, 12];

for value in table {
assert!(IfGreaterOrEqual10ThenEven::validate(value).is_ok());
}
}

#[test]
fn test_rule_binder_err() {
let table = vec![11, 13];

for value in table {
assert!(IfGreaterOrEqual10ThenEven::validate(value).is_err());
}
}
}
74 changes: 74 additions & 0 deletions src/rule/composer/nand.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use crate::rule::composer::Not;
use crate::And;

/// This is a type that represents logical NAND in logic.
pub type Nand<RULE1, RULE2> = Not<And![RULE1, RULE2]>;

#[macro_export]
macro_rules! Nand {
($rule1:ty, $rule2:ty) => {
$crate::rule::composer::Nand<$rule1, $rule2>
};

($rule1:ty, $($rule2: ty), +) => {
$crate::rule::composer::Nand<$rule1, $crate::And![$($rule2), +]>
}
}

#[cfg(test)]
mod test_2 {
use crate::rule::{Invalid, Rule, Valid};

type ValidI8 = Valid<i8>;
type InvalidI8 = Invalid<i8>;

type Target1 = Nand![ValidI8, ValidI8]; // ERR
type Target2 = Nand![ValidI8, InvalidI8]; // PASS
type Target3 = Nand![InvalidI8, ValidI8]; // PASS
type Target4 = Nand![InvalidI8, InvalidI8]; // PASS

#[test]
fn test_rule_binder_ok() {
assert!(Target2::validate(0).is_ok());
assert!(Target3::validate(0).is_ok());
assert!(Target4::validate(0).is_ok());
}

#[test]
fn test_rule_binder_err() {
assert!(Target1::validate(0).is_err());
}
}

#[cfg(test)]
mod test_3 {
use crate::rule::{Invalid, Rule, Valid};

type ValidI8 = Valid<i8>;
type InvalidI8 = Invalid<i8>;

type Target1 = Nand![ValidI8, ValidI8, ValidI8]; // ERR
type Target2 = Nand![ValidI8, ValidI8, InvalidI8]; // PASS
type Target3 = Nand![ValidI8, InvalidI8, ValidI8]; // PASS
type Target4 = Nand![ValidI8, InvalidI8, InvalidI8]; // PASS
type Target5 = Nand![InvalidI8, ValidI8, ValidI8]; // PASS
type Target6 = Nand![InvalidI8, ValidI8, InvalidI8]; // PASS
type Target7 = Nand![InvalidI8, InvalidI8, ValidI8]; // PASS
type Target8 = Nand![InvalidI8, InvalidI8, InvalidI8]; // PASS

#[test]
fn test_rule_binder_ok() {
assert!(Target2::validate(0).is_ok());
assert!(Target3::validate(0).is_ok());
assert!(Target4::validate(0).is_ok());
assert!(Target5::validate(0).is_ok());
assert!(Target6::validate(0).is_ok());
assert!(Target7::validate(0).is_ok());
assert!(Target8::validate(0).is_ok());
}

#[test]
fn test_rule_binder_err() {
assert!(Target1::validate(0).is_err());
}
}
74 changes: 74 additions & 0 deletions src/rule/composer/nor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use crate::Or;
use crate::rule::composer::Not;

/// This is a type that represents logical NOR in logic.
pub type Nor<RULE1, RULE2> = Not<Or![RULE1, RULE2]>;

#[macro_export]
macro_rules! Nor {
($rule1:ty, $rule2:ty) => {
$crate::rule::composer::Nor<$rule1, $rule2>
};

($rule1:ty, $($rule2: ty), +) => {
$crate::rule::composer::Nor<$rule1, $crate::Or![$($rule2), +]>
}
}

#[cfg(test)]
mod test_2 {
use crate::rule::{Invalid, Rule, Valid};

type ValidI8 = Valid<i8>;
type InvalidI8 = Invalid<i8>;

type Target1 = Nor![ValidI8, ValidI8]; // 2: ERR
type Target2 = Nor![ValidI8, InvalidI8]; // 1: ERR
type Target3 = Nor![InvalidI8, ValidI8]; // 1: ERR
type Target4 = Nor![InvalidI8, InvalidI8]; // 0: PASS

#[test]
fn test_rule_binder_ok() {
assert!(Target4::validate(0).is_ok());
}

#[test]
fn test_rule_binder_err() {
assert!(Target1::validate(0).is_err());
assert!(Target2::validate(0).is_err());
assert!(Target3::validate(0).is_err());
}
}

#[cfg(test)]
mod test_3 {
use crate::rule::{Invalid, Rule, Valid};

type ValidI8 = Valid<i8>;
type InvalidI8 = Invalid<i8>;

type Target1 = Nor![ValidI8, ValidI8, ValidI8]; // 3: ERR
type Target2 = Nor![ValidI8, ValidI8, InvalidI8]; // 2: ERR
type Target3 = Nor![ValidI8, InvalidI8, ValidI8]; // 2: ERR
type Target4 = Nor![ValidI8, InvalidI8, InvalidI8]; // 1: ERR
type Target5 = Nor![InvalidI8, ValidI8, ValidI8]; // 2: ERR
type Target6 = Nor![InvalidI8, ValidI8, InvalidI8]; // 1: ERR
type Target7 = Nor![InvalidI8, InvalidI8, ValidI8]; // 1: ERR
type Target8 = Nor![InvalidI8, InvalidI8, InvalidI8]; // 0: PASS

#[test]
fn test_rule_binder_ok() {
assert!(Target8::validate(0).is_ok());
}

#[test]
fn test_rule_binder_err() {
assert!(Target1::validate(0).is_err());
assert!(Target2::validate(0).is_err());
assert!(Target3::validate(0).is_err());
assert!(Target4::validate(0).is_err());
assert!(Target5::validate(0).is_err());
assert!(Target6::validate(0).is_err());
assert!(Target7::validate(0).is_err());
}
}
Loading

0 comments on commit 03cea9c

Please sign in to comment.