I've been fumbling through Rust's documentation trying to execute a simple esoteric example for my own educational benefit more than practicality. While doing this, I can't seem to wrap my head around how Rust's error handling is meant to be used.
The programming example I'm using is to write a function that runs a command in a shell. From the result of the command I want to retrieve stdout
(as a String
or &str
) and know whether or not the command failed.
The std::process::Command
struct gives me the methods I want, but it seems that the only way to combine them is kludgy and awkward:
use std::process::Command;
use std::string::{String, FromUtf8Error};
use std::io::Error;
enum CmdError {
UtfError(FromUtf8Error),
IoError(Error),
}
// I would really like to use std::error::Error instead of CmdError,
// but the compiler complains about using a trait in this context.
fn run_cmd(cmd: &str) -> Result<String, CmdError> {
let cmd_result = Command::new("sh").arg("-c").arg(cmd).output();
match cmd_result {
Err(e) => {
return Err(CmdError::IoError(e));
}
Ok(v) => {
let out_result = String::from_utf8(v.stdout);
match out_result {
Err(e) => {
return Err(CmdError::UtfError(e));
}
Ok(v) => {
return Ok(v);
}
}
}
}
}
fn main() {
let r = run_cmd("echo 'Hello World!'");
match r {
Err(e) => {
match e {
CmdError::IoError(e) => {
panic!("Failed to run command {:}", e);
}
CmdError::UtfError(e) => {
panic!("Failed to run command {:}", e);
}
}
}
Ok(e) => {
print!("{:}", e);
}
}
}
In particular, the nested match blocks inside run_cmd
seem really awkward, and the nested match blocks in main
are even worse.
What I'd really like to do is be able to use a more general class of error than FromUtf8Error
or io::Error
which I can type convert into easily from either concrete type, but it doesn't appear the type system is designed in this way, so I had to use the crude CmdError
as somewhat of a union type instead.
I'm sure there's an easier way to do this which is more idiomatic, but I haven't found it from the documentation I've read so far.
Any pointers appreciated.