But the error messages from Display-ing the file open / write / etc. errors are terribly vague. How would I make the errors more detailed without complicating the code with error handling statements everywhere?
Right now the errors resemble Permission denied (os error 13), but I want them to look like Could not create file 'post.txt' (permission denied). or something at least as informative and readable.
Yeah that's what I meant by adding extra error handling statements everywhere. There probably isn't a way better than that without wrapping the entire fscrate module though.
Edit: Nevermind I take it all back error-chain is amazing.
error-chain is usually pretty good in that you can chain a low level error like "file not found" with a more high-level message like "unable to load the configuration file, /foo/bar/baz.conf". That way you get an error message which is actually useful, while also retaining the low level context so you can figure out exactly how to fix something.
One example is where we have a parser for some custom file format at work and if there's an error you can use the -v flag to get a full "backtrace" of where the parsing went wrong.
Error: Couldn't parse the drawing
Caused By: Parsing error on line 42, column 7
Caused By: In drawing body
Caused By: In Polyline
Caused By: In Flags
Caused By: Invalid flag (0x0010)
That's a lot more user friendly than the generic "unable to parse file" message you'd usually get.
I also solved this problem by creating wrappers for everything. You can see my code here. I feel like someone should create a crate for this because it's not possible to build a user friendly program without something like this.
use quick_error::ResultExt;
quick_error! {
#[derive(Debug)]
pub enum Error {
File(filename: PathBuf, err: io::Error) {
context(path: &'a Path, err: io::Error)
-> (path.to_path_buf(), err)
}
}
}
fn openfile(path: &Path) -> Result<(), Error> {
try!(File::open(path).context(path));
// If we didn't have context, the line above would be written as;
//
// try!(File::open(path)
// .map_err(|err| Error::File(path.to_path_buf(), err)));
Ok(())
}
I like quick-error because its documentation and inner workings were easier to grok for me than error-chain. In return, it also has fewer features (e.g. no fancy backtraces), so your mileage may vary.