use rs_ws281x::RawColor; use std::{ vec::Vec, string::String }; use std::sync::RwLockWriteGuard; pub type ParseError = Box; pub trait Pattern: Send { fn execute(&self, values: &mut RwLockWriteGuard<'_, [RawColor; crate::LED_SIZE]>, ticks: u64); 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), "rand" => Ok(Box::new(Random::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]>, _ticks: u64) {} 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]>, _ticks: u64) { 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()) } } } struct Random { r: bool, g: bool, b: bool, min: u8, max: u8 } impl Pattern for Random { fn execute(&self, values: &mut RwLockWriteGuard<'_, [RawColor; crate::LED_SIZE]>, _ticks: u64) { use rand::prelude::*; let mut rng = rand::thread_rng(); for i in 0..values.len() { let mut color = (*values)[i]; let min = self.min; let max = self.max; if self.r { let y: f64 = rng.gen(); color[2] = (y * (max - min) as f64) as u8 + min; //println!("r {} {}", y, color[2]); } if self.g { let y: f64 = rng.gen(); color[1] = (y * (max - min) as f64) as u8 + min; //println!("g {} {}", y, color[1]); } if self.b { let y: f64 = rng.gen(); color[0] = (y * (max - min) as f64) as u8 + min; //println!("b {} {}", y, color[0]); } (*values)[i] = color; } } fn parse(args: Vec) -> Result { let end = args.len() - 1; let e = args[end].parse::(); let en = args[end-1].parse::(); let mut r = false; let mut g = false; let mut b = false; let (min, max) = match en { Ok(i) => { match e { Ok(j) => (i, j), Err(_) => (0, 255) } }, Err(_) => { match e { Ok(i) => (0, i), Err(_) => (0, 255) } } }; for x in 0..end+1 { match args[x].as_str() { "r" => {r = true;}, "g" => {g = true;}, "b" => {b = true;}, _ => {} } } //println!("{} {} {}", r,g,b); Ok(Random { r: r, g: g, b: b, min: min, max: max }) } } struct Rainbow { offset_r: Option, offset_g: Option, offset_b: Option } // todo // iterate over but pull // VecDeque::rotate_right() //let mut v = (1..6).collect::>(); //v.rotate_right(1); //println!("{:?}", v); // IF intented vec is the same as current vec // dupe & rotate current vec // change value so it is only gathered once per tick, and only for the first pixel // set new intended vec to rotated vec // exit IF // slowly transform current vec to intended vec by a constant fade value // reply inside execute fn struct Ticker { ticks: u64, } pub fn parse_line(v: Vec) -> Result, ParseError> { println!("{:?}", v); 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() }