sensd/action/
action.rs

1use crate::io::{IOEvent, Output, RawValue};
2use std::ops::DerefMut;
3use crate::helpers::Def;
4
5pub type BoxedAction = Box<dyn Action>;
6
7/// Trait that enables actions to be performed based on incoming data.
8///
9/// Actions are designed to activate [`Output`] devices based on data
10/// from [`crate::io::Input`] devices. The primary method for processing incoming
11/// data is [`Action::evaluate()`]
12pub trait Action {
13    fn name(&self) -> &String;
14
15    /// Evaluate incoming data and perform action if necessary.
16    ///
17    /// # Parameters
18    ///
19    /// - `data`: Raw incoming data from input device.
20    fn evaluate(&mut self, data: &IOEvent);
21
22    /// Builder function for setting `output` field.
23    ///
24    /// # Parameters
25    ///
26    /// - `device`: `DeferredDevice` to set as output
27    ///
28    /// # Returns
29    ///
30    /// Ownership of `self` to allow builder pattern method chaining
31    fn set_output(self, device: Def<Output>) -> Self
32    where
33        Self: Sized;
34
35    /// Getter function for `output` field.
36    fn output(&self) -> Option<Def<Output>>;
37
38    /// Setter function for output device field
39    ///
40    /// # Parameters
41    ///
42    /// - `value`: Binary value to send to device
43    ///
44    /// # Panics
45    ///
46    /// - If error occurs when writing to device
47    /// - If output has no associated output
48    fn write(&self, value: RawValue) {
49        let output = self.output()
50            .expect("Action has no associated output device");
51
52        let mut binding = output.try_lock().unwrap();
53        let device = binding.deref_mut();
54
55        device.write(value)
56            .expect("Unexpected error when writing to output device.");
57    }
58
59    /// Print notification to stdout.
60    ///
61    /// This should be controlled by an internal option flag.
62    fn notify(&self, msg: &str) {
63        println!("{}", msg);
64    }
65
66    /// Consume [`Self`] and wrap in a [`Box`] so it can be coerced into an [`Action`] trait object.
67    fn into_boxed(self) -> BoxedAction;
68}