Passing enum variant as fn arg and setting value in enum

How can I set the value in any of those enum variants? Please see the comment marked as LINE 1

pub enum EXIT_PROCESS_STATUS {
    COULD_NOT_READ_STDERR(String /*reason/output */),
    COULD_NOT_READ_STDOUT(String /*reason/output */),
}

fn read_std_stream<T: std::io::Read>(
    std_stream: Option<T>,
    execute_process_status: &mut EXiT_PROCESS_STATUS,
    err_flag: EXiT_PROCESS_STATUS,
) {
    let mut buf = String::new();

    match std_stream.unwrap().read_to_string(&mut buf) {
        Err(why) => {
            *execute_process_status = err_flag;//LINE 1 How can I pass the 'why' value to the execute_process_status?
        }
        _=> {

        }
    }
}

//Later on I call it:
read_std_stream(
                process.stderr,
                &mut execute_process_status,
                EXiT_PROCESS_STATUS::COULD_NOT_READ_STDERR("".to_owned()),
            );

Thank you

You might want this:

*execute_process_status = EXiT_PROCESS_STATUS::COULD_NOT_READ_STDERR(why.to_string());

though it's not clear why you pass err_flag in.

Hi,
Thank you. The reason I'm passing the err_flag is that I'm passing one time stderr, stdout.
But I think your reply helped me figure out how to do it. Thanks!

Instead of just passing in what the generic supposedly is in some separate way,

  • Use enums instead of generics, or
  • Use a trait bound that can supply the information of what the generic is in some way

A key idea of either approach is to make a logical mismatch between the generic and the ability to find out "what is this" impossible in your API / to avoid the need to manually keep them in sync.

I also suggest you

  • Return Result as opposed to updating a &mut status parameter
  • Don't use screaming snake case for types

It ended up a bit verbose but this still looks cleaner to me.

More reading:

5 Likes

Hi, yes, thanks for the time you've spend in preparing that example. I like it and definitely will use some of those techniques.