use rs_ws281x::RawColor; use std::{ vec::Vec, string::String }; use std::sync::RwLockWriteGuard; type ParseError = Box; pub trait Pattern<'a> { fn execute(&self, values: &'a mut RwLockWriteGuard<'_, [RawColor; crate::LED_SIZE]>); fn parse(args: Vec) -> Result where Self: Sized; } impl<'a> TryFrom> for Box> { type Error = ParseError; fn try_from(s: Vec) -> Result { match s[0].as_str() { "unit" => Ok(Box::new(Unit::parse(s).unwrap()) as Box), "val" => Ok(Box::new(Value::parse(s).unwrap()) as Box), _ => Err("No Match".into()) } } } struct Unit; impl<'a> Pattern<'a> for Unit { fn execute(&self, _values: &'a mut RwLockWriteGuard<'_, [RawColor; crate::LED_SIZE]>) {} fn parse(_args: Vec) -> Result { Ok(Unit {}) } } struct Value { r: Option, g: Option, b: Option } impl<'a> Pattern<'a> for Value { fn execute(&self, values: &'a mut RwLockWriteGuard<'_, [RawColor; crate::LED_SIZE]>) { for i in 0..crate::LED_SIZE { let mut color: RawColor = (*values)[i]; if self.r.is_some() { color[2] = self.r.unwrap(); } if self.g.is_some() { color[1] = self.g.unwrap(); } if self.b.is_some() { color[0] = self.b.unwrap(); } (*values)[i] = color; } } fn parse(args: Vec) -> Result { let param1 = args[1].parse::(); let param2 = args[2].parse::(); let param3 = args[3].parse::(); if param1.is_ok() && param2.is_ok() && param3.is_ok() { Ok(Value{ r: Some(param1.unwrap()), g: Some(param2.unwrap()), b: Some(param3.unwrap()) }) } else { match param2 { Ok(i) => match args[1].as_str() { "r" => { Ok(Value { r: Some(i), g: None, b: None }) }, "g" => { Ok(Value { r: None, g: Some(i), b: None }) }, "b" => { Ok(Value { r: None, g: None, b: Some(i) }) } _ => Err("unreachable".into()) }, Err(e) => Err(Box::new(e)) } } } } pub fn parse_line<'a>(v: Vec) -> Result>, ParseError> { v.try_into() } pub fn format_multiline(input: &str) -> Vec> { input.lines() .map(|x: &str| x.split_whitespace() .map(|y| String::from(y)) .collect::>() ) .collect() }