use rs_ws281x::RawColor; use std::{ vec::Vec, string::String }; use std::sync::RwLockWriteGuard; pub type ParseError = Box; pub trait Pattern { fn execute(&self, values: &mut RwLockWriteGuard<'_, [RawColor; crate::LED_SIZE]>); fn parse(args: Vec) -> Result where Self: Sized; } impl 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 Pattern for Unit { fn execute(&self, _values: &mut RwLockWriteGuard<'_, [RawColor; crate::LED_SIZE]>) {} fn parse(_args: Vec) -> Result { Ok(Unit {}) } } struct Value { r: Option, g: Option, b: Option } impl Pattern for Value { fn execute(&self, values: &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 = if args.len() >= 1 { match args[1].parse::() { Ok(i) => Some(i), Err(_) => None } } else { None }; let param2 = if args.len() >= 2 { match args[2].parse::() { Ok(i) => Some(i), Err(_) => None } } else { None }; let param3 = if args.len() >= 3 { match args[3].parse::() { Ok(i) => Some(i), Err(_) => None } } else { None }; if param1.is_some() && param2.is_some() && param3.is_some() { Ok(Value{ r: param1, g: param2, b: param3 }) } else if args.len() >= 2 { match param2 { Some(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("no rgb".into()) }, None => Err("no param2".into()) } } else { Err("incorrect number of arguments".into()) } } } pub fn parse_line(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() }