use core::slice::Iter; use std::{fmt::Display, str::FromStr}; use anyhow::{bail, Result}; #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] pub enum ActionType { GreaterThan, LessThan, Push, Receive, Update, } impl Display for ActionType { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::GreaterThan => write!(f, "GreaterThan"), Self::LessThan => write!(f, "LessThan"), Self::Push => write!(f, "Push"), Self::Receive => write!(f, "Receive"), Self::Update => write!(f, "Update"), } } } impl FromStr for ActionType { type Err = anyhow::Error; fn from_str(s: &str) -> Result { match s { "GreaterThan" => Ok(Self::GreaterThan), "LessThan" => Ok(Self::LessThan), "Push" => Ok(Self::Push), "Receive" => Ok(Self::Receive), "Update" => Ok(Self::Update), _ => bail!("could not parse ActionType from {s}"), } } } #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] pub struct Action { pub device_id: String, pub action_type: ActionType, pub parameter: String, } impl Action { pub fn new( device_id: impl ToString, action_type: ActionType, parameter: impl ToString, ) -> Self { Self { device_id: device_id.to_string(), action_type, parameter: parameter.to_string(), } } } #[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct ActionSet { actions: Vec, } impl ActionSet { pub fn push_device(&self) -> Option { self.iter() .find(|action| action.action_type == ActionType::Push) .map(|action| action.device_id.clone()) } pub fn receive_device(&self) -> Option { self.iter() .find(|action| action.action_type == ActionType::Receive) .map(|action| action.device_id.clone()) } pub fn begins_with_device(&self, device_name: &str) -> bool { match self.actions.get(0) { Some(action) => action.device_id == device_name, None => false, } } pub fn parameter(&self, parameter: &str) -> bool { match self.actions.get(0) { Some(action) => action.parameter == parameter, None => false, } } pub fn chain(&mut self, action: Action) { self.actions.push(action); } pub fn iter(&self) -> Iter<'_, Action> { self.actions.iter() } } impl From for ActionSet where I: IntoIterator, { fn from(value: I) -> Self { Self { actions: value.into_iter().collect(), } } } #[cfg(test)] mod test { use super::*; use anyhow::Result; #[test] fn example_chain() -> Result<()> { let mut action_set = ActionSet::default(); action_set.chain(Action::new( "shelly_plus_ht", ActionType::Push, "temperature", )); action_set.chain(Action::new( "shelly_trv", ActionType::Receive, "temperature", )); Ok(()) } }