use uuid::Uuid;
use crate::base::{
block::{Block, BlockDesc, BlockProps, BlockState},
input::{InputProps, input_reader::InputReader},
output::Output,
};
use libhaystack::val::{Number, Value, kind::HaystackKind};
use crate::{blocks::InputImpl, blocks::OutputImpl};
#[block]
#[derive(BlockProps, Debug)]
#[dis = "Add"]
#[category = "math"]
#[input(kind = "Number", count = 16)]
pub struct Add {
#[output(kind = "Number")]
pub out: OutputImpl,
}
impl Block for Add {
async fn execute(&mut self) {
self.read_inputs_until_ready().await;
let mut has_err = false;
let val = self
.inputs()
.into_iter()
.filter_map(|input| match input.get_value().as_ref() {
Some(Value::Number(num)) => Some(*num),
_ => None,
})
.reduce(|mut acc, val| {
if acc.unit.is_none()
&& acc.value == 0.0
&& let Some(unit) = val.unit
{
acc = Number::make_with_unit(0.0, unit);
};
match acc + val {
Ok(res) => res,
Err(_) => {
has_err = true;
Number::make(0.0)
}
}
});
if has_err {
self.set_state(BlockState::fault("Add: unit mismatch between inputs"));
} else if !matches!(self.state(), BlockState::Running) {
self.set_state(BlockState::Running);
}
if let Some(res) = val {
self.out.set((res).into())
}
}
}
#[cfg(test)]
mod test {
use crate::{
base::block::{Block, BlockProps},
base::input::input_reader::InputReader,
blocks::math::Add,
};
#[tokio::test]
async fn test_add_block() {
let mut block = Add::new();
{
let in1 = block.get_input_mut("in0").unwrap();
in1.increment_conn();
in1.writer()
.send((3.into(), crate::base::Status::Ok))
.unwrap();
block.read_inputs().await;
}
{
let in16 = block.get_input_mut("in15").unwrap();
in16.increment_conn();
in16.writer()
.send((3.into(), crate::base::Status::Ok))
.unwrap();
}
block.execute().await;
assert_eq!(block.out.value, 6.into());
}
}