use core::mem::ManuallyDrop; #[repr(C)] union DiplomatResultValue { ok: ManuallyDrop, err: ManuallyDrop, } /// A `Result`-like type that can be passed across the FFI boundary /// as a value. Use this type when returning a result from an FFI /// function instead of `Result`. #[repr(C)] pub struct DiplomatResult { value: DiplomatResultValue, pub is_ok: bool, } impl Drop for DiplomatResult { fn drop(&mut self) { unsafe { if self.is_ok { let _ = ManuallyDrop::take(&mut self.value.ok); } else { let _ = ManuallyDrop::take(&mut self.value.err); } } } } impl From> for DiplomatResult { fn from(result: Result) -> Self { match result { Result::Ok(ok) => DiplomatResult { value: DiplomatResultValue { ok: ManuallyDrop::new(ok), }, is_ok: true, }, Result::Err(err) => DiplomatResult { value: DiplomatResultValue { err: ManuallyDrop::new(err), }, is_ok: false, }, } } } impl From> for Result { fn from(mut result: DiplomatResult) -> Result { unsafe { if result.is_ok { Ok(ManuallyDrop::take(&mut result.value.ok)) } else { Err(ManuallyDrop::take(&mut result.value.err)) } } } }