1 use core::fmt; 2 use core::mem::ManuallyDrop; 3 4 #[repr(C)] 5 union DiplomatResultValue<T, E> { 6 ok: ManuallyDrop<T>, 7 err: ManuallyDrop<E>, 8 } 9 10 /// A [`Result`]-like type that can be passed across the FFI boundary 11 /// as a value. Used internally to return [`Result`]s and [`Option`]s 12 /// from functions. 13 #[repr(C)] 14 pub struct DiplomatResult<T, E> { 15 value: DiplomatResultValue<T, E>, 16 pub is_ok: bool, 17 } 18 19 /// A type to represent Option<T> over FFI. 20 /// 21 /// Used internally to handle `Option<T>` arguments and return types, and needs to be 22 /// used explicitly for optional struct fields. 23 pub type DiplomatOption<T> = DiplomatResult<T, ()>; 24 25 impl<T, E> DiplomatResult<T, E> { as_ref(&self) -> Result<&T, &E>26 pub fn as_ref(&self) -> Result<&T, &E> { 27 // Safety: we're only accessing the union variants when the flag is correct 28 unsafe { 29 if self.is_ok { 30 Ok(&self.value.ok) 31 } else { 32 Err(&self.value.err) 33 } 34 } 35 } 36 } 37 38 impl<T> DiplomatOption<T> { 39 /// Helper for converting into an Option to avoid trait ambiguity errors with Into 40 #[inline] into_option(self) -> Option<T>41 pub fn into_option(self) -> Option<T> { 42 self.into() 43 } 44 45 /// Helper for converting into an Option with the inner type converted 46 #[inline] into_converted_option<U: From<T>>(self) -> Option<U>47 pub fn into_converted_option<U: From<T>>(self) -> Option<U> { 48 self.into_option().map(Into::into) 49 } 50 } 51 52 impl<T: Clone, E: Clone> Clone for DiplomatResult<T, E> { clone(&self) -> Self53 fn clone(&self) -> Self { 54 unsafe { 55 if self.is_ok { 56 Ok((*self.value.ok).clone()).into() 57 } else { 58 Err((*self.value.err).clone()).into() 59 } 60 } 61 } 62 } 63 64 impl<T, E> Drop for DiplomatResult<T, E> { drop(&mut self)65 fn drop(&mut self) { 66 unsafe { 67 if self.is_ok { 68 let _ = ManuallyDrop::take(&mut self.value.ok); 69 } else { 70 let _ = ManuallyDrop::take(&mut self.value.err); 71 } 72 } 73 } 74 } 75 76 impl<T, E> From<Result<T, E>> for DiplomatResult<T, E> { from(result: Result<T, E>) -> Self77 fn from(result: Result<T, E>) -> Self { 78 match result { 79 Result::Ok(ok) => DiplomatResult { 80 value: DiplomatResultValue { 81 ok: ManuallyDrop::new(ok), 82 }, 83 is_ok: true, 84 }, 85 86 Result::Err(err) => DiplomatResult { 87 value: DiplomatResultValue { 88 err: ManuallyDrop::new(err), 89 }, 90 is_ok: false, 91 }, 92 } 93 } 94 } 95 96 impl<T> From<Option<T>> for DiplomatOption<T> { from(option: Option<T>) -> Self97 fn from(option: Option<T>) -> Self { 98 option.ok_or(()).into() 99 } 100 } 101 102 impl<T> From<DiplomatOption<T>> for Option<T> { from(result: DiplomatOption<T>) -> Self103 fn from(result: DiplomatOption<T>) -> Self { 104 Result::<T, ()>::from(result).ok() 105 } 106 } 107 108 impl<T, E> From<DiplomatResult<T, E>> for Result<T, E> { from(mut result: DiplomatResult<T, E>) -> Result<T, E>109 fn from(mut result: DiplomatResult<T, E>) -> Result<T, E> { 110 unsafe { 111 if result.is_ok { 112 Ok(ManuallyDrop::take(&mut result.value.ok)) 113 } else { 114 Err(ManuallyDrop::take(&mut result.value.err)) 115 } 116 } 117 } 118 } 119 120 impl<T: fmt::Debug, E: fmt::Debug> fmt::Debug for DiplomatResult<T, E> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result121 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 122 self.as_ref().fmt(f) 123 } 124 } 125