//! The programs that run inside tool containers. use proto::tools::{ReadFileArgs, WriteFileArgs}; pub mod files; pub mod input; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Exit { Done, ToolError, Misuse, } impl Exit { /// 0, 1, 2. No `as` cast: a `match`. pub fn code(self) -> u8 { match self { Exit::Done => 0, Exit::ToolError => 1, Exit::Misuse => 2, } } } #[derive(Debug, Clone, PartialEq, Eq)] pub struct Outcome { pub exit: Exit, pub stdout: String, pub stderr: String, } impl Outcome { pub fn done(stdout: String) -> Outcome { Outcome { exit: Exit::Done, stdout, stderr: String::new(), } } pub fn tool_error(stdout: String) -> Outcome { Outcome { exit: Exit::ToolError, stdout, stderr: String::new(), } } pub fn misuse(stderr: String) -> Outcome { Outcome { exit: Exit::Misuse, stdout: String::new(), stderr, } } } /// Run tool `name` with the arguments on `stdin`. pub fn run(name: &str, stdin: &mut dyn std::io::Read) -> Outcome { let text = match input::read_input(stdin) { Ok(t) => t, Err(e) => return Outcome::misuse(format!("toolkit: {e}")), }; match name { "read_file" => { let args = match input::parse::(name, &text) { Ok(a) => a, Err(e) => return Outcome::misuse(e), }; files::read_file(&args) } "write_file" => { let args = match input::parse::(name, &text) { Ok(a) => a, Err(e) => return Outcome::misuse(e), }; files::write_file(&args) } _ => Outcome::misuse(format!("toolkit: unknown tool {name:?}")), } }