Representing compact NonZero result enums as FFI safe

I can't remember the name for this type of enum so I'll just write some example code:

use std::num::NonZeroU16;
enum SuccessOrError {
    Success,
    Error(NonZeroU16)
}

Which is the equivalent of Result<(), NonZeroU16>. In Rust this will be represented by a single u16 but it produces a warning for FFI because the memory layout should be explicitly stated. However if I use repr to set the layout to either u16 or C it could use anywhere from 4 to 8 bytes instead of simply 2.

Can I explicitly state I want the compact layout? Or do I have to manually convert to/from a u16 for FFI?

Your best bet is to impl From<u16> for SuccessOrResult and then employ that conversion after getting the u16.

Alternatively, skip the enum and do something like this:

#[repr(transparent)]
struct FfiResult(u16);

impl FfiResult {
    fn into_err(self) -> Option<NonZeroU16> {
        NonZeroU16::new(self.0)
    }
}
1 Like

Thanks. The second option might be nicer in terms of typing the raw FFI call. I'll experiment.