Skip to main content

wasibox_core/
lib.rs

1pub mod utils;
2#[cfg(test)]
3mod tests;
4
5use std::ffi::OsString;
6use std::path::Path;
7use std::io::{Read, Write};
8
9/// Context for utility IO, allowing redirection of stdin, stdout, and stderr.
10pub struct IoContext {
11    pub stdin: Box<dyn Read + Send>,
12    pub stdout: Box<dyn Write + Send>,
13    pub stderr: Box<dyn Write + Send>,
14}
15
16impl IoContext {
17    pub fn new(
18        stdin: Box<dyn Read + Send>,
19        stdout: Box<dyn Write + Send>,
20        stderr: Box<dyn Write + Send>,
21    ) -> Self {
22        Self { stdin, stdout, stderr }
23    }
24}
25
26impl Default for IoContext {
27    fn default() -> Self {
28        Self {
29            stdin: Box::new(std::io::stdin()),
30            stdout: Box::new(std::io::stdout()),
31            stderr: Box::new(std::io::stderr()),
32        }
33    }
34}
35
36pub fn execute<I, T>(args: I) -> Result<(), String>
37where
38    I: IntoIterator<Item = T>,
39    T: Into<OsString> + Clone,
40{
41    execute_with_context(args, &mut IoContext::default())
42}
43
44pub fn execute_with_context<I, T>(args: I, ctx: &mut IoContext) -> Result<(), String>
45where
46    I: IntoIterator<Item = T>,
47    T: Into<OsString> + Clone,
48{
49    let args_vec: Vec<OsString> = args.into_iter().map(|a| a.into()).collect();
50    if args_vec.is_empty() {
51        return Err("No utility specified".to_string());
52    }
53
54    let prog_name_raw = Path::new(&args_vec[0])
55        .file_name()
56        .unwrap_or_default()
57        .to_string_lossy();
58    let prog_name = prog_name_raw
59        .trim_end_matches(".exe")
60        .trim_end_matches(".wasm");
61
62    let (util_name, util_args) = if prog_name == "core" || prog_name == "core-rust" || prog_name == "wasibox-core" {
63        if args_vec.len() < 2 {
64            return Err("Usage: core <utility> [args...]".to_string());
65        }
66        (args_vec[1].to_string_lossy().to_string(), &args_vec[1..])
67    } else {
68        (prog_name.to_string(), &args_vec[..])
69    };
70
71    match util_name.as_str() {
72        #[cfg(feature = "arch")]
73        "arch" => utils::arch::execute_with_context(util_args, ctx),
74        #[cfg(feature = "basename")]
75        "basename" => utils::basename::execute_with_context(util_args, ctx),
76        #[cfg(feature = "cat")]
77        "cat" => utils::cat::execute_with_context(util_args, ctx),
78        #[cfg(feature = "cp")]
79        "cp" => utils::cp::execute_with_context(util_args, ctx),
80        #[cfg(feature = "dir")]
81        "dir" => utils::dir::execute_with_context(util_args, ctx),
82        #[cfg(feature = "dirname")]
83        "dirname" => utils::dirname::execute_with_context(util_args, ctx),
84        #[cfg(feature = "echo")]
85        "echo" => utils::echo::execute_with_context(util_args, ctx),
86        #[cfg(feature = "env")]
87        "env" => utils::env::execute_with_context(util_args, ctx),
88        #[cfg(feature = "false")]
89        "false" => utils::r#false::execute_with_context(util_args, ctx),
90        #[cfg(feature = "grep")]
91        "grep" => utils::grep::execute_with_context(util_args, ctx),
92        #[cfg(feature = "head")]
93        "head" => utils::head::execute_with_context(util_args, ctx),
94        #[cfg(feature = "link")]
95        "link" => utils::link::execute_with_context(util_args, ctx),
96        #[cfg(feature = "ln")]
97        "ln" => utils::ln::execute_with_context(util_args, ctx),
98        #[cfg(feature = "ls")]
99        "ls" => utils::ls::execute_with_context(util_args, ctx),
100        #[cfg(feature = "mkdir")]
101        "mkdir" => utils::mkdir::execute_with_context(util_args, ctx),
102        #[cfg(feature = "mv")]
103        "mv" => utils::mv::execute_with_context(util_args, ctx),
104        #[cfg(feature = "pwd")]
105        "pwd" => utils::pwd::execute_with_context(util_args, ctx),
106        #[cfg(feature = "rm")]
107        "rm" => utils::rm::execute_with_context(util_args, ctx),
108        #[cfg(feature = "rmdir")]
109        "rmdir" => utils::rmdir::execute_with_context(util_args, ctx),
110        #[cfg(feature = "sleep")]
111        "sleep" => utils::sleep::execute_with_context(util_args, ctx),
112        #[cfg(feature = "tail")]
113        "tail" => utils::tail::execute_with_context(util_args, ctx),
114        #[cfg(feature = "tee")]
115        "tee" => utils::tee::execute_with_context(util_args, ctx),
116        #[cfg(feature = "touch")]
117        "touch" => utils::touch::execute_with_context(util_args, ctx),
118        #[cfg(feature = "tree")]
119        "tree" => utils::tree::execute_with_context(util_args, ctx),
120        #[cfg(feature = "true")]
121        "true" => utils::r#true::execute_with_context(util_args, ctx),
122        #[cfg(feature = "uname")]
123        "uname" => utils::uname::execute_with_context(util_args, ctx),
124        #[cfg(feature = "unlink")]
125        "unlink" => utils::unlink::execute_with_context(util_args, ctx),
126        #[cfg(feature = "wc")]
127        "wc" => utils::wc::execute_with_context(util_args, ctx),
128        #[cfg(feature = "whoami")]
129        "whoami" => utils::whoami::execute_with_context(util_args, ctx),
130        #[cfg(feature = "yes")]
131        "yes" => utils::yes::execute_with_context(util_args, ctx),
132        _ => Err(format!("Unknown utility: {}", util_name)),
133    }
134}