#![no_std] //! Exact builtin names and bounded external-command routing. use turkos_os_shell_words::Words; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Builtin { Cd, Exit, Help } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Route<'a> { Builtin(Builtin), External(&'a str) } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct Decision<'a> { pub route: Route<'a>, pub argc: usize } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Error { MissingCommand, InvalidName, BuiltinArity } pub fn decide( words: &Words, ) -> Result, Error> { let Some(name) = words.get(0) else { return Err(Error::MissingCommand); }; if name.is_empty() || name.bytes().any(|byte| byte == 0 || byte.is_ascii_whitespace()) { return Err(Error::InvalidName); } let argc = words.len() - 1; let route = match name { "cd" if argc == 1 => Route::Builtin(Builtin::Cd), "cd" => return Err(Error::BuiltinArity), "exit" if argc <= 1 => Route::Builtin(Builtin::Exit), "exit" => return Err(Error::BuiltinArity), "help" if argc == 0 => Route::Builtin(Builtin::Help), "help" => return Err(Error::BuiltinArity), _ => Route::External(name), }; Ok(Decision {route, argc}) }