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