use core::slice::IterMut; use embedded_hal::serial::{Read, Write}; use esp_println::{print, println}; use nb::block; use nb::Error::{Other, WouldBlock}; use crate::command_handler::CommandHandleError::{CommandNotRead, NotFound}; use crate::command_handler::CommandReadError::{BufferOverflowed, CommandLoadedAlready, UnexpectedEndOfLine}; use crate::commands::command::Command; use crate::commands::command_argument::CommandArgument; use crate::map::Map; pub trait SpecificCommandHandler { fn handle(&self, command: &mut CommandData) -> Result<(), CommandHandleError>; fn help(&self) -> &'static str; } pub struct CommandData<'d, 'a> { pub command: Command<'d>, pub map: &'d mut Map<'a>, } pub struct CommandHandler<'d, const BUFFER_SIZE: usize, const HANDLERS_COUNT: usize> { buffer_position: usize, command_loaded: bool, buffer: [char; BUFFER_SIZE], handlers: [(&'d str, &'d dyn SpecificCommandHandler); HANDLERS_COUNT], handling_special: u8 } #[derive(Debug, Eq, PartialEq)] pub enum CommandReadError { UnexpectedEndOfLine, BufferOverflowed, CommandLoadedAlready, } #[derive(Debug, Eq, PartialEq)] pub enum CommandHandleError { NotFound, WrongArguments, CommandNotRead, } impl<'d, const BUFFER_SIZE: usize, const HANDLERS_COUNT: usize> CommandHandler<'d, BUFFER_SIZE, HANDLERS_COUNT> { pub fn new(handlers: [(&'d str, &'d dyn SpecificCommandHandler); HANDLERS_COUNT], buffer: [char; BUFFER_SIZE]) -> Self { Self { command_loaded: false, handling_special: 0, buffer_position: 0, buffer, handlers, } } pub fn reset(&mut self) -> () { self.buffer_position = 0; self.command_loaded = false; self.handling_special = 0; } fn handle_special(&mut self, serial: &mut Serial, data: u8) -> bool where Serial: Read + Write { if self.handling_special > 0 { // some special characters have char length 2. self.handling_special -= 1; return false; } match data { b'\x08' => { // backspace if self.buffer_position > 0 { self.buffer_position -= 1; block!(serial.write(b'\x08')).ok().unwrap(); block!(serial.write(b' ')).ok().unwrap(); block!(serial.write(b'\x08')).ok().unwrap(); } false }, b'\x1b' => { // other special characters self.handling_special = 2; false }, _ => true } } pub fn read_command(&mut self, serial: &mut Serial) -> nb::Result<(), CommandReadError> where Serial: Read + Write { if self.command_loaded { return Err(Other(CommandLoadedAlready)); } let read = serial.read(); if self.buffer_position >= BUFFER_SIZE { return Err(Other(BufferOverflowed)); } match read { Ok(data) => { if self.handle_special(serial, data) { self.buffer[self.buffer_position] = data as char } else { // special character handled return Err(WouldBlock); } } Err(_) => return Err(WouldBlock) }; let read = self.buffer[self.buffer_position]; self.buffer_position += 1; block!(serial.write(read as u8)).ok().unwrap(); if read != '\r' { return Err(WouldBlock); } block!(serial.write(b'\n')).ok().unwrap(); if self.buffer_position <= 1 { self.reset(); return Err(Other(UnexpectedEndOfLine)); } self.command_loaded = true; Ok(()) } fn parse_command<'a>(&self, buffer: &'a [char], args: &'a mut [CommandArgument<'a>]) -> Command<'a> { let mut last_arg_index = 0; let mut length = 0; let mut args_iter = args.iter_mut(); for i in 0..buffer.len() { let argument_length = i - last_arg_index; if buffer[i] == ' ' { if argument_length > 0 { *args_iter.next().unwrap() = CommandArgument::new(&buffer[last_arg_index..i]); length += 1; } last_arg_index = i + 1; } if buffer[i] == '\r' || buffer[i] == '\n' { if argument_length > 0 { *args_iter.next().unwrap() = CommandArgument::new(&buffer[last_arg_index..i]); length += 1; } break; } } Command { full: buffer, parsed_arguments: &args[0..length], } } fn handle_help(&self) -> Result<(), CommandHandleError> { println!("Available commands:\r"); for (cmd, handler) in self.handlers { println!(" {0} {1}\r", cmd, handler.help()); } Ok(()) } pub fn handle_command(&mut self, map: &mut Map) -> Result<(), CommandHandleError> { if !self.command_loaded { return Err(CommandNotRead); } let buffer = &self.buffer[0..self.buffer_position]; let mut args = [CommandArgument::new(buffer); BUFFER_SIZE]; let command = self.parse_command(buffer, &mut args); if command.parsed_arguments.len() == 0 { self.reset(); return Err(NotFound); } let first_argument = command.parsed_arguments[0]; if first_argument.compare("HELP") { let help_handled = self.handle_help(); self.reset(); return help_handled; } for (handler_command, handler) in self.handlers { if !first_argument.compare(handler_command) { continue; } let mut command_data = CommandData { command, map, }; let handled = handler.handle(&mut command_data); self.reset(); return handled; } self.reset(); Err(NotFound) } } // HELP // DEFAULT // SET // ALL // RESET // ITER [X] [Y] (X start, Y end) // SNAKE [X] [Y] (X start, Y end) // RAINBOW -- show rainbow // WIFI