Skip to main content

ranvier_std/nodes/
math.rs

1use async_trait::async_trait;
2use num_traits::Num;
3use ranvier_core::{bus::Bus, outcome::Outcome, transition::Transition};
4use schemars::JsonSchema;
5use serde::{Deserialize, Serialize};
6use std::{fmt::Debug, marker::PhantomData};
7
8#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema, PartialEq)]
9pub enum MathOperation {
10    Add,
11    Sub,
12    Mul,
13    Div,
14}
15
16#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
17pub struct MathNode<T> {
18    pub operation: MathOperation,
19    pub operand: T,
20    #[serde(skip)]
21    pub _marker: PhantomData<T>,
22}
23
24impl<T> MathNode<T> {
25    pub fn new(operation: MathOperation, operand: T) -> Self {
26        Self {
27            operation,
28            operand,
29            _marker: PhantomData,
30        }
31    }
32}
33
34#[async_trait]
35impl<T> Transition<T, T> for MathNode<T>
36where
37    T: Num + Clone + Send + Sync + Debug + 'static,
38{
39    type Error = String;
40    type Resources = ();
41
42    async fn run(
43        &self,
44        input: T,
45        _resources: &Self::Resources,
46        _bus: &mut Bus,
47    ) -> Outcome<T, Self::Error> {
48        let result = match self.operation {
49            MathOperation::Add => input.clone() + self.operand.clone(),
50            MathOperation::Sub => input.clone() - self.operand.clone(),
51            MathOperation::Mul => input.clone() * self.operand.clone(),
52            MathOperation::Div => input.clone() / self.operand.clone(),
53        };
54
55        Outcome::next(result)
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[tokio::test]
64    async fn math_add() {
65        let node = MathNode::new(MathOperation::Add, 10i64);
66        let mut bus = Bus::new();
67        let result = node.run(5i64, &(), &mut bus).await;
68        assert!(matches!(result, Outcome::Next(15)));
69    }
70
71    #[tokio::test]
72    async fn math_sub() {
73        let node = MathNode::new(MathOperation::Sub, 3i64);
74        let mut bus = Bus::new();
75        let result = node.run(10i64, &(), &mut bus).await;
76        assert!(matches!(result, Outcome::Next(7)));
77    }
78
79    #[tokio::test]
80    async fn math_mul() {
81        let node = MathNode::new(MathOperation::Mul, 4i64);
82        let mut bus = Bus::new();
83        let result = node.run(5i64, &(), &mut bus).await;
84        assert!(matches!(result, Outcome::Next(20)));
85    }
86
87    #[tokio::test]
88    async fn math_div() {
89        let node = MathNode::new(MathOperation::Div, 2i64);
90        let mut bus = Bus::new();
91        let result = node.run(10i64, &(), &mut bus).await;
92        assert!(matches!(result, Outcome::Next(5)));
93    }
94}