use std::marker::PhantomData;
use std::ops::{Shl, Shr};
use crate::Node;
use crate::error::RoplatError;
pub struct LogicAnd;
impl Node for LogicAnd {
type Input = (bool, bool);
type Output = Result<bool, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<bool, RoplatError> {
Ok(input.0 && input.1)
}
}
pub struct LogicOr;
impl Node for LogicOr {
type Input = (bool, bool);
type Output = Result<bool, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<bool, RoplatError> {
Ok(input.0 || input.1)
}
}
pub struct LogicXor;
impl Node for LogicXor {
type Input = (bool, bool);
type Output = Result<bool, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<bool, RoplatError> {
Ok(input.0 ^ input.1)
}
}
pub struct LogicNot;
impl Node for LogicNot {
type Input = bool;
type Output = Result<bool, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<bool, RoplatError> {
Ok(!input)
}
}
pub struct LogicNand;
impl Node for LogicNand {
type Input = (bool, bool);
type Output = Result<bool, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<bool, RoplatError> {
Ok(!(input.0 && input.1))
}
}
pub struct LogicNor;
impl Node for LogicNor {
type Input = (bool, bool);
type Output = Result<bool, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<bool, RoplatError> {
Ok(!(input.0 || input.1))
}
}
pub struct Equal<T>(PhantomData<T>);
impl<T> Default for Equal<T> {
fn default() -> Self {
Self(PhantomData)
}
}
impl<T> Node for Equal<T>
where
T: PartialEq + Send + Sync + 'static,
{
type Input = (T, T);
type Output = Result<bool, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<bool, RoplatError> {
Ok(input.0 == input.1)
}
}
pub struct NotEqual<T>(PhantomData<T>);
impl<T> Default for NotEqual<T> {
fn default() -> Self {
Self(PhantomData)
}
}
impl<T> Node for NotEqual<T>
where
T: PartialEq + Send + Sync + 'static,
{
type Input = (T, T);
type Output = Result<bool, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<bool, RoplatError> {
Ok(input.0 != input.1)
}
}
pub struct Greater<T>(PhantomData<T>);
impl<T> Default for Greater<T> {
fn default() -> Self {
Self(PhantomData)
}
}
impl<T> Node for Greater<T>
where
T: PartialOrd + Send + Sync + 'static,
{
type Input = (T, T);
type Output = Result<bool, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<bool, RoplatError> {
Ok(input.0 > input.1)
}
}
pub struct GreaterEqual<T>(PhantomData<T>);
impl<T> Default for GreaterEqual<T> {
fn default() -> Self {
Self(PhantomData)
}
}
impl<T> Node for GreaterEqual<T>
where
T: PartialOrd + Send + Sync + 'static,
{
type Input = (T, T);
type Output = Result<bool, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<bool, RoplatError> {
Ok(input.0 >= input.1)
}
}
pub struct Less<T>(PhantomData<T>);
impl<T> Default for Less<T> {
fn default() -> Self {
Self(PhantomData)
}
}
impl<T> Node for Less<T>
where
T: PartialOrd + Send + Sync + 'static,
{
type Input = (T, T);
type Output = Result<bool, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<bool, RoplatError> {
Ok(input.0 < input.1)
}
}
pub struct LessEqual<T>(PhantomData<T>);
impl<T> Default for LessEqual<T> {
fn default() -> Self {
Self(PhantomData)
}
}
impl<T> Node for LessEqual<T>
where
T: PartialOrd + Send + Sync + 'static,
{
type Input = (T, T);
type Output = Result<bool, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<bool, RoplatError> {
Ok(input.0 <= input.1)
}
}
pub struct BitwiseAnd<I1, I2, O> {
_marker: PhantomData<(I1, I2, O)>,
}
impl<I1, I2, O> BitwiseAnd<I1, I2, O> {
pub fn new() -> Self {
Self { _marker: PhantomData }
}
}
impl<I1, I2, O> Default for BitwiseAnd<I1, I2, O> {
fn default() -> Self {
Self::new()
}
}
impl<I1, I2, O> Node for BitwiseAnd<I1, I2, O>
where
I1: std::ops::BitAnd<I2, Output = O> + Send + Sync,
I2: Send + Sync,
O: Send + Sync,
{
type Input = (I1, I2);
type Output = Result<O, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<O, RoplatError> {
Ok(input.0 & input.1)
}
}
pub struct BitwiseOr<I1, I2, O> {
_marker: PhantomData<(I1, I2, O)>,
}
impl<I1, I2, O> BitwiseOr<I1, I2, O> {
pub fn new() -> Self {
Self { _marker: PhantomData }
}
}
impl<I1, I2, O> Default for BitwiseOr<I1, I2, O> {
fn default() -> Self {
Self::new()
}
}
impl<I1, I2, O> Node for BitwiseOr<I1, I2, O>
where
I1: std::ops::BitOr<I2, Output = O> + Send + Sync,
I2: Send + Sync,
O: Send + Sync,
{
type Input = (I1, I2);
type Output = Result<O, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<O, RoplatError> {
Ok(input.0 | input.1)
}
}
pub struct BitwiseXor<I1, I2, O> {
_marker: PhantomData<(I1, I2, O)>,
}
impl<I1, I2, O> BitwiseXor<I1, I2, O> {
pub fn new() -> Self {
Self { _marker: PhantomData }
}
}
impl<I1, I2, O> Default for BitwiseXor<I1, I2, O> {
fn default() -> Self {
Self::new()
}
}
impl<I1, I2, O> Node for BitwiseXor<I1, I2, O>
where
I1: std::ops::BitXor<I2, Output = O> + Send + Sync,
I2: Send + Sync,
O: Send + Sync,
{
type Input = (I1, I2);
type Output = Result<O, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<O, RoplatError> {
Ok(input.0 ^ input.1)
}
}
pub struct BitwiseNot<I, O> {
_marker: PhantomData<(I, O)>,
}
impl<I, O> BitwiseNot<I, O> {
pub fn new() -> Self {
Self { _marker: PhantomData }
}
}
impl<I, O> Default for BitwiseNot<I, O> {
fn default() -> Self {
Self::new()
}
}
impl<I, O> Node for BitwiseNot<I, O>
where
I: std::ops::Not<Output = O> + Send + Sync,
O: Send + Sync,
{
type Input = I;
type Output = Result<O, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<O, RoplatError> {
Ok(!input)
}
}
pub struct BitwiseShl<I, O> {
_marker: PhantomData<(I, O)>,
}
impl<I, O> BitwiseShl<I, O> {
pub fn new() -> Self {
Self { _marker: PhantomData }
}
}
impl<I, O> Default for BitwiseShl<I, O> {
fn default() -> Self {
Self::new()
}
}
impl<I, O> Node for BitwiseShl<I, O>
where
I: Shl<u32, Output = O> + Send + Sync,
O: Send + Sync,
{
type Input = (I, u32);
type Output = Result<O, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<O, RoplatError> {
Ok(input.0 << input.1)
}
}
pub struct BitwiseShr<I, O> {
_marker: PhantomData<(I, O)>,
}
impl<I, O> BitwiseShr<I, O> {
pub fn new() -> Self {
Self { _marker: PhantomData }
}
}
impl<I, O> Default for BitwiseShr<I, O> {
fn default() -> Self {
Self::new()
}
}
impl<I, O> Node for BitwiseShr<I, O>
where
I: Shr<u32, Output = O> + Send + Sync,
O: Send + Sync,
{
type Input = (I, u32);
type Output = Result<O, RoplatError>;
type Error = RoplatError;
async fn process(&mut self, input: Self::Input) -> Result<O, RoplatError> {
Ok(input.0 >> input.1)
}
}
pub type BitAnd<I1, I2, O> = BitwiseAnd<I1, I2, O>;
pub type BitOr<I1, I2, O> = BitwiseOr<I1, I2, O>;
pub type BitXor<I1, I2, O> = BitwiseXor<I1, I2, O>;
pub type BitNot<I, O> = BitwiseNot<I, O>;
pub type BitShl<I, O> = BitwiseShl<I, O>;
pub type BitShr<I, O> = BitwiseShr<I, O>;
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_logic_and() {
let mut node = LogicAnd;
assert!(node.process((true, true)).await.unwrap());
assert!(!node.process((true, false)).await.unwrap());
assert!(!node.process((false, true)).await.unwrap());
assert!(!node.process((false, false)).await.unwrap());
}
#[tokio::test]
async fn test_logic_or() {
let mut node = LogicOr;
assert!(node.process((true, true)).await.unwrap());
assert!(node.process((true, false)).await.unwrap());
assert!(node.process((false, true)).await.unwrap());
assert!(!node.process((false, false)).await.unwrap());
}
#[tokio::test]
async fn test_logic_xor() {
let mut node = LogicXor;
assert!(!node.process((true, true)).await.unwrap());
assert!(node.process((true, false)).await.unwrap());
assert!(node.process((false, true)).await.unwrap());
assert!(!node.process((false, false)).await.unwrap());
}
#[tokio::test]
async fn test_logic_not() {
let mut node = LogicNot;
assert!(!node.process(true).await.unwrap());
assert!(node.process(false).await.unwrap());
}
#[tokio::test]
async fn test_logic_nand() {
let mut node = LogicNand;
assert!(!node.process((true, true)).await.unwrap());
assert!(node.process((true, false)).await.unwrap());
assert!(node.process((false, true)).await.unwrap());
assert!(node.process((false, false)).await.unwrap());
}
#[tokio::test]
async fn test_logic_nor() {
let mut node = LogicNor;
assert!(!node.process((true, true)).await.unwrap());
assert!(!node.process((true, false)).await.unwrap());
assert!(!node.process((false, true)).await.unwrap());
assert!(node.process((false, false)).await.unwrap());
}
#[tokio::test]
async fn test_equal_integer() {
let mut node = Equal::<i32>::default();
assert!(node.process((5, 5)).await.unwrap());
assert!(!node.process((5, 3)).await.unwrap());
assert!(node.process((-1, -1)).await.unwrap());
}
#[tokio::test]
async fn test_equal_string() {
let mut node = Equal::<String>::default();
assert!(
node.process(("hello".to_string(), "hello".to_string()))
.await
.unwrap()
);
assert!(
!node
.process(("hello".to_string(), "world".to_string()))
.await
.unwrap()
);
}
#[tokio::test]
async fn test_not_equal_integer() {
let mut node = NotEqual::<i32>::default();
assert!(!node.process((5, 5)).await.unwrap());
assert!(node.process((5, 3)).await.unwrap());
}
#[tokio::test]
async fn test_greater_integer() {
let mut node = Greater::<i32>::default();
assert!(node.process((5, 3)).await.unwrap());
assert!(!node.process((5, 5)).await.unwrap());
assert!(!node.process((3, 5)).await.unwrap());
}
#[tokio::test]
async fn test_greater_float() {
let mut node = Greater::<f64>::default();
assert!(node.process((5.5, 3.3)).await.unwrap());
assert!(!node.process((5.5, 5.5)).await.unwrap());
}
#[tokio::test]
async fn test_greater_equal_integer() {
let mut node = GreaterEqual::<i32>::default();
assert!(node.process((5, 3)).await.unwrap());
assert!(node.process((5, 5)).await.unwrap());
assert!(!node.process((3, 5)).await.unwrap());
}
#[tokio::test]
async fn test_less_integer() {
let mut node = Less::<i32>::default();
assert!(node.process((3, 5)).await.unwrap());
assert!(!node.process((5, 5)).await.unwrap());
assert!(!node.process((5, 3)).await.unwrap());
}
#[tokio::test]
async fn test_less_equal_integer() {
let mut node = LessEqual::<i32>::default();
assert!(node.process((3, 5)).await.unwrap());
assert!(node.process((5, 5)).await.unwrap());
assert!(!node.process((5, 3)).await.unwrap());
}
#[tokio::test]
async fn test_bitwise_and_integer() {
let mut node = BitwiseAnd::<i32, i32, i32>::new();
assert_eq!(node.process((0b1100, 0b1010)).await.unwrap(), 0b1000);
assert_eq!(node.process((0xFF, 0x0F)).await.unwrap(), 0x0F);
}
#[tokio::test]
async fn test_bitwise_and_unsigned() {
let mut node = BitwiseAnd::<u32, u32, u32>::new();
assert_eq!(node.process((0xFFFF, 0x00FF)).await.unwrap(), 0x00FF);
}
#[tokio::test]
async fn test_bitwise_or_integer() {
let mut node = BitwiseOr::<i32, i32, i32>::new();
assert_eq!(node.process((0b1100, 0b1010)).await.unwrap(), 0b1110);
assert_eq!(node.process((0xF0, 0x0F)).await.unwrap(), 0xFF);
}
#[tokio::test]
async fn test_bitwise_xor_integer() {
let mut node = BitwiseXor::<i32, i32, i32>::new();
assert_eq!(node.process((0b1100, 0b1010)).await.unwrap(), 0b0110);
assert_eq!(node.process((0xFF, 0xFF)).await.unwrap(), 0);
}
#[tokio::test]
async fn test_bitwise_not_integer() {
let mut node = BitwiseNot::<i32, i32>::new();
assert_eq!(node.process(1_i32).await.unwrap(), -2);
assert_eq!(node.process(0_i32).await.unwrap(), -1);
}
#[tokio::test]
async fn test_bitwise_not_unsigned() {
let mut node = BitwiseNot::<u8, u8>::new();
assert_eq!(node.process(0x00_u8).await.unwrap(), 0xFF);
assert_eq!(node.process(0xFF_u8).await.unwrap(), 0x00);
}
#[tokio::test]
async fn test_bitwise_shl_integer() {
let mut node = BitwiseShl::<i32, i32>::new();
assert_eq!(node.process((1_i32, 2_u32)).await.unwrap(), 4);
assert_eq!(node.process((1_i32, 4_u32)).await.unwrap(), 16);
}
#[tokio::test]
async fn test_bitwise_shr_integer() {
let mut node = BitwiseShr::<i32, i32>::new();
assert_eq!(node.process((8_i32, 2_u32)).await.unwrap(), 2);
assert_eq!(node.process((16_i32, 4_u32)).await.unwrap(), 1);
}
#[tokio::test]
async fn test_bitwise_shr_unsigned() {
let mut node = BitwiseShr::<u32, u32>::new();
assert_eq!(node.process((8_u32, 2_u32)).await.unwrap(), 2);
assert_eq!(node.process((0xFF_u32, 4_u32)).await.unwrap(), 0x0F);
}
#[tokio::test]
async fn test_bit_and_alias() {
let mut node = BitAnd::<i32, i32, i32>::new();
assert_eq!(node.process((0b1100, 0b1010)).await.unwrap(), 0b1000);
}
#[tokio::test]
async fn test_bit_or_alias() {
let mut node = BitOr::<i32, i32, i32>::new();
assert_eq!(node.process((0b1100, 0b1010)).await.unwrap(), 0b1110);
}
#[tokio::test]
async fn test_bit_xor_alias() {
let mut node = BitXor::<i32, i32, i32>::new();
assert_eq!(node.process((0b1100, 0b1010)).await.unwrap(), 0b0110);
}
#[tokio::test]
async fn test_bit_not_alias() {
let mut node = BitNot::<u8, u8>::new();
assert_eq!(node.process(0x00_u8).await.unwrap(), 0xFF);
}
#[tokio::test]
async fn test_bit_shl_alias() {
let mut node = BitShl::<i32, i32>::new();
assert_eq!(node.process((1_i32, 2_u32)).await.unwrap(), 4);
}
#[tokio::test]
async fn test_bit_shr_alias() {
let mut node = BitShr::<i32, i32>::new();
assert_eq!(node.process((8_i32, 2_u32)).await.unwrap(), 2);
}
#[tokio::test]
async fn test_comparison_with_zero() {
let mut greater = Greater::<i32>::default();
let mut less = Less::<i32>::default();
assert!(greater.process((0, -1)).await.unwrap());
assert!(!greater.process((0, 0)).await.unwrap());
assert!(less.process((0, 1)).await.unwrap());
assert!(!less.process((0, 0)).await.unwrap());
}
#[tokio::test]
async fn test_bitwise_operations_boundary() {
let mut and_node = BitwiseAnd::<u8, u8, u8>::new();
let mut or_node = BitwiseOr::<u8, u8, u8>::new();
assert_eq!(and_node.process((0xFF, 0xFF)).await.unwrap(), 0xFF);
assert_eq!(and_node.process((0x00, 0x00)).await.unwrap(), 0x00);
assert_eq!(or_node.process((0xFF, 0x00)).await.unwrap(), 0xFF);
assert_eq!(or_node.process((0x00, 0x00)).await.unwrap(), 0x00);
}
#[tokio::test]
async fn test_shift_overflow() {
let mut node = BitwiseShl::<u32, u32>::new();
let result = node.process((1_u32, 8_u32)).await.unwrap();
assert!(result == 256);
}
}