diplomat_runtime/
result.rs

1use core::mem::ManuallyDrop;
2
3#[repr(C)]
4union DiplomatResultValue<T, E> {
5    ok: ManuallyDrop<T>,
6    err: ManuallyDrop<E>,
7}
8
9/// A [`Result`]-like type that can be passed across the FFI boundary
10/// as a value. Used internally to return [`Result`]s and [`Option`]s
11/// from functions.
12#[repr(C)]
13pub struct DiplomatResult<T, E> {
14    value: DiplomatResultValue<T, E>,
15    pub is_ok: bool,
16}
17
18impl<T, E> Drop for DiplomatResult<T, E> {
19    fn drop(&mut self) {
20        unsafe {
21            if self.is_ok {
22                let _ = ManuallyDrop::take(&mut self.value.ok);
23            } else {
24                let _ = ManuallyDrop::take(&mut self.value.err);
25            }
26        }
27    }
28}
29
30impl<T, E> From<Result<T, E>> for DiplomatResult<T, E> {
31    fn from(result: Result<T, E>) -> Self {
32        match result {
33            Result::Ok(ok) => DiplomatResult {
34                value: DiplomatResultValue {
35                    ok: ManuallyDrop::new(ok),
36                },
37                is_ok: true,
38            },
39
40            Result::Err(err) => DiplomatResult {
41                value: DiplomatResultValue {
42                    err: ManuallyDrop::new(err),
43                },
44                is_ok: false,
45            },
46        }
47    }
48}
49
50impl<T, E> From<DiplomatResult<T, E>> for Result<T, E> {
51    fn from(mut result: DiplomatResult<T, E>) -> Result<T, E> {
52        unsafe {
53            if result.is_ok {
54                Ok(ManuallyDrop::take(&mut result.value.ok))
55            } else {
56                Err(ManuallyDrop::take(&mut result.value.err))
57            }
58        }
59    }
60}