Non-trivial struct initialization

I am porting C++ class which contains file handle, and its constructor takes as input argument the path to a filename. If the file at specified path can not be opened for whatever reason, the constructor throws an exception which is caught by the child class, and so on until the caller catches it and converts the chain of exceptions into the success status value.

I am trying to write the Rust equivalent, but haven't gone too far with structuring the handling of the failures from within the constructor which merely fills the list of member variables with initializer values

pub fn new(str_filename: &Path) -> Self {
     Self {
              data1: 0,
              data2: 0,
              input_file: match File::open(str_filename) {
                   Err(_why) => panic!("panic message"),
                   Ok(f) => f
           }
}

I do plan on this method returning the Option but simply can't figure out how to convert the failure to open the file into the Option values.

Your help is highly appreciated.

Sure! You can use the ? operator to make your life easy and be idiomatic:

pub fn new(str_filename: &Path) -> Option<Self> {
    Some(
        Self {
            data1: 0,
            data2: 0,
            input_file: File::open(str_filename).ok()?,
        }
    )
}

Or you can return the error too if it happens:

pub fn new(str_filename: &Path) -> std::io::Result<Self> {
    Ok(
        Self {
            data1: 0,
            data2: 0,
            input_file: File::open(str_filename)?,
        }
    )
}

This will automatically return the error should there be an error while opening the file. Note that the Result type used here is the special type declaration in the IO module. See std::io::Result for more on the result, and std::io::Error for more on the errors possible.


Edit: ? will apparently not discard errors when converting to and option from a Result, so I inserted an .ok() call in there. Also, I had forgotten to return the correct type; so wrapping the struct in Ok and Some fixes it. I apologize for the mixup!

You have to return Some(…) or Ok(…) though.

1 Like

The first proposed solution does not compile, the compiler error is:

export enum std::option::Option, found struct mymodule::mystruct.

Putting Some(Self { bla bla}) results with

? couldn't convert the error to std::option::NoneError

How exactly is the error converted to Option in general ?

I've fixed my post; please reread it.