logic_mesh/blocks/math/
min.rs1use anyhow::Ok;
4use uuid::Uuid;
5
6use crate::{
7    base::{
8        block::{Block, BlockDesc, BlockProps, BlockState},
9        input::{input_reader::InputReader, Input, InputProps},
10        output::Output,
11    },
12    blocks::utils::convert_units,
13};
14
15use libhaystack::val::{kind::HaystackKind, Number, Value};
16
17use crate::{blocks::InputImpl, blocks::OutputImpl};
18
19#[block]
21#[derive(BlockProps, Debug)]
22#[dis = "Minimum"]
23#[category = "math"]
24pub struct Min {
25    #[input(kind = "Number")]
26    pub a: InputImpl,
27    #[input(kind = "Number")]
28    pub b: InputImpl,
29    #[output(kind = "Number")]
30    pub out: OutputImpl,
31}
32
33impl Block for Min {
34    async fn execute(&mut self) {
35        self.read_inputs_until_ready().await;
36
37        if let (Some(Value::Number(a)), Some(Value::Number(b))) =
38            (self.a.get_value(), self.b.get_value())
39        {
40            let _ = convert_units(&[a.to_owned(), b.to_owned()])
41                .and_then(|parts| {
42                    if let [a, b] = &parts[..] {
43                        let val = Number {
44                            value: a.value.min(b.value),
45                            unit: a.unit,
46                        };
47                        self.out.set(val.into());
48                    }
49                    Ok(())
50                })
51                .or_else(|_| {
52                    self.set_state(BlockState::Fault);
53                    Ok(())
54                });
55        }
56    }
57}
58
59#[cfg(test)]
60mod test {
61
62    use std::assert_matches::assert_matches;
63
64    use libhaystack::val::{Number, Value};
65
66    use crate::{
67        base::block::test_utils::write_block_inputs,
68        base::{block::Block, input::input_reader::InputReader},
69        blocks::math::Min,
70    };
71
72    #[tokio::test]
73    async fn test_min_block() {
74        let mut block = Min::new();
75
76        for _ in
77            write_block_inputs(&mut [(&mut block.a, 8.into()), (&mut block.b, 42.into())]).await
78        {
79            block.read_inputs().await;
80        }
81
82        block.execute().await;
83
84        assert_matches!(
85            block.out.value,
86            Value::Number(Number { value, .. }) if value == 8.0
87        );
88    }
89}