I'm writing a basic program and putting the work in a
try_main and then exiting with nonzero if try_main returns an Error.
The basic try! statements work, but I can't figure out how to return a custom error. First I tried to return a string wrapped in a standard error, then I tried to implement my own error type but it complained I was trying to return an error instead of a result.
Is there a standard way to wrap a string in an error? Also how do I make, box and return a custom error type?
fn main() {
match try_main() {
Ok(()) => {},
Err(e) => {
println!("thumbnail extractor failed with {:?}", e.description());
std::process::exit(1);
}
}
}
fn try_main() -> Result<(), Box<std::error::Error>> {
let args : Vec<_> = std::env::args_os().collect();
let filename = args.get(1).expect("needs one argument") ;
println!("filename: {:?}", filename);
// if !(filename.to_string_lossy().ends_with(".odf") || filename.to_string_lossy().ends_with(".ora"))
// {
// let s = std::io::Error::new(Error::new(ErrorKind::Other, "This program only supports creating thumbnails from odf or ora files.".to_string()));
// return s;
// }
let f = try!(File::open(filename));
let mut odf = try!(zip::ZipArchive::new(f));
let thumb_name = r"Thumbnails/thumbnail.png";
let mut thumb_file_in_zip = try!(odf.by_name(thumb_name).or(Err("could not find thumbnail zip file")));
let mut fw = try!(File::create(r"thumbnail.png"));
let mut buffer : Vec<u8> = Vec::new();
try!(thumb_file_in_zip.read_to_end(& mut buffer));
try!(fw.write_all(buffer.as_slice()));
Ok(())
}
Result<T, E> is an enum with two variants Ok(T) and Err(E).
When you instantiate a Result<T, E> you will have to explicitly state which variant you want.
In your particular case you have to return Err(s) (given that s is of type E, you may have to use Box::new in your code, I haven't checked if s is correct, only that Err is missing).
One way to start using a custom error type is the following:
enum MyError {
IoError,
OtherError,
}
fn try_main() -> Result<(), MyError> {
// do stuff
return Err(MyError::IoError);
}
This is a simplistic approach, more on you'll probably want impl std::error::Error for MyError and impl From<std::io::Error> for MyError, possibly keeping the original error inside MyError. Though this is optional.
There's a chapter on the book about error handling with much more details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With