Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a standard way to wrap a string in an error? Also how do I make, box and return a custom error type?

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(())
}
like image 463
Roman A. Taycher Avatar asked Oct 20 '25 10:10

Roman A. Taycher


1 Answers

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.

like image 101
Jan Segre Avatar answered Oct 22 '25 04:10

Jan Segre



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!