ffi_result/
lib.rs

1use std::{
2    fmt::Debug,
3    mem::ManuallyDrop,
4    ops::{Deref, DerefMut},
5};
6
7/// FFI-compatibe and ABI-stable analogue for [`core::result::Result`].
8///
9/// Can be freely converted to and from the core Result.
10#[repr(C)]
11pub struct Result<T, E> {
12    kind: ResultKind,
13    data: ResultData<T, E>,
14}
15
16impl<T, E> Result<T, E> {
17    pub const fn new_ok(t: T) -> Self {
18        Self {
19            kind: ResultKind::Ok,
20            data: ResultData {
21                ok: ManuallyDrop::new(t),
22            },
23        }
24    }
25    pub const fn new_err(e: E) -> Self {
26        Self {
27            kind: ResultKind::Err,
28            data: ResultData {
29                err: ManuallyDrop::new(e),
30            },
31        }
32    }
33
34    pub fn is_ok(&self) -> bool {
35        self.kind == ResultKind::Ok
36    }
37    pub fn is_err(&self) -> bool {
38        self.kind == ResultKind::Err
39    }
40
41    pub const fn kind(&self) -> &ResultKind {
42        &self.kind
43    }
44
45    /// # Safety
46    /// Cannot guarantee that the user will preserve correct kind-data relationship.
47    pub const unsafe fn kind_mut(&mut self) -> &mut ResultKind {
48        &mut self.kind
49    }
50
51    pub const fn data(&self) -> &ResultData<T, E> {
52        &self.data
53    }
54
55    /// # Safety
56    /// Cannot guarantee that the user will preserve correct kind-data relationship.
57    pub const unsafe fn data_mut(&mut self) -> &mut ResultData<T, E> {
58        &mut self.data
59    }
60
61    pub fn as_ref(&self) -> Result<&T, &E> {
62        Result {
63            kind: self.kind,
64            data: match self.kind {
65                ResultKind::Ok => {
66                    let inner = unsafe { &self.data.ok };
67                    ResultData {
68                        ok: ManuallyDrop::new(inner.deref()),
69                    }
70                }
71                ResultKind::Err => {
72                    let inner = unsafe { &self.data.err };
73                    ResultData {
74                        err: ManuallyDrop::new(inner.deref()),
75                    }
76                }
77            },
78        }
79    }
80
81    pub fn as_mut(&mut self) -> Result<&mut T, &mut E> {
82        Result {
83            kind: self.kind,
84            data: match self.kind {
85                ResultKind::Ok => {
86                    let inner = unsafe { &mut self.data.ok };
87                    ResultData {
88                        ok: ManuallyDrop::new(inner.deref_mut()),
89                    }
90                }
91                ResultKind::Err => {
92                    let inner = unsafe { &mut self.data.err };
93                    ResultData {
94                        err: ManuallyDrop::new(inner.deref_mut()),
95                    }
96                }
97            },
98        }
99    }
100
101    pub fn ok(self) -> Option<T> {
102        let kind = self.kind;
103        // SAFETY: we only read the union bits, which are valid for either variant
104        let mut data = unsafe { std::ptr::read(&self.data) };
105        std::mem::forget(self);
106
107        match kind {
108            ResultKind::Ok => Some(unsafe { ManuallyDrop::into_inner(data.ok) }),
109            ResultKind::Err => {
110                unsafe { ManuallyDrop::drop(&mut data.err) };
111                None
112            }
113        }
114    }
115    pub fn err(self) -> Option<E> {
116        let kind = self.kind;
117        // SAFETY: we only read the union bits, which are valid for either variant
118        let mut data = unsafe { std::ptr::read(&self.data) };
119        std::mem::forget(self);
120
121        match kind {
122            ResultKind::Err => Some(unsafe { ManuallyDrop::into_inner(data.err) }),
123            ResultKind::Ok => {
124                unsafe { ManuallyDrop::drop(&mut data.ok) };
125                None
126            }
127        }
128    }
129    pub fn into_result(self) -> core::result::Result<T, E> {
130        let kind = self.kind;
131        // SAFETY: we only read the union bits, which are valid for either variant
132        let data = unsafe { std::ptr::read(&self.data) };
133        std::mem::forget(self);
134
135        match kind {
136            ResultKind::Ok => {
137                core::result::Result::Ok(unsafe { ManuallyDrop::into_inner(data.ok) })
138            }
139            ResultKind::Err => {
140                core::result::Result::Err(unsafe { ManuallyDrop::into_inner(data.err) })
141            }
142        }
143    }
144    pub fn from_result(result: core::result::Result<T, E>) -> Self {
145        match result {
146            Ok(ok) => Self::new_ok(ok),
147            Err(err) => Self::new_err(err),
148        }
149    }
150
151    pub fn map<T2>(self, op: impl FnOnce(T) -> T2) -> Result<T2, E> {
152        self.into_result().map(op).into()
153    }
154    pub fn map_err<E2>(self, op: impl FnOnce(E) -> E2) -> Result<T, E2> {
155        self.into_result().map_err(op).into()
156    }
157}
158impl<T: Debug, E> Result<T, E> {
159    pub fn unwrap_err(self) -> E {
160        self.into_result().unwrap_err()
161    }
162    pub fn expect_err(self, msg: &str) -> E {
163        self.into_result().expect_err(msg)
164    }
165}
166impl<T, E: Debug> Result<T, E> {
167    pub fn unwrap(self) -> T {
168        self.into_result().unwrap()
169    }
170    pub fn expect(self, msg: &str) -> T {
171        self.into_result().expect(msg)
172    }
173}
174
175impl<T, E> From<Result<T, E>> for core::result::Result<T, E> {
176    fn from(val: Result<T, E>) -> core::result::Result<T, E> {
177        val.into_result()
178    }
179}
180impl<T, E> From<core::result::Result<T, E>> for Result<T, E> {
181    fn from(val: core::result::Result<T, E>) -> Self {
182        Self::from_result(val)
183    }
184}
185
186impl<T: Debug, E: Debug> Debug for Result<T, E> {
187    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
188        let mut structt = f.debug_struct("Result");
189        let dbg = structt.field("kind", &self.kind);
190
191        unsafe {
192            match self.kind {
193                ResultKind::Ok => dbg.field("data", self.data.ok.deref()).finish(),
194                ResultKind::Err => dbg.field("data", self.data.err.deref()).finish(),
195            }
196        }
197    }
198}
199
200impl<T: Clone, E: Clone> Clone for Result<T, E> {
201    fn clone(&self) -> Self {
202        unsafe {
203            Self {
204                kind: self.kind,
205                data: match self.kind {
206                    ResultKind::Ok => ResultData {
207                        ok: self.data.ok.clone(),
208                    },
209                    ResultKind::Err => ResultData {
210                        err: self.data.err.clone(),
211                    },
212                },
213            }
214        }
215    }
216}
217
218impl<T: PartialEq, E: PartialEq> PartialEq for Result<T, E> {
219    fn eq(&self, other: &Self) -> bool {
220        match (self.as_ref().into_result(), other.as_ref().into_result()) {
221            (Ok(a), Ok(b)) => a.eq(b),
222            (Err(a), Err(b)) => a.eq(b),
223            (Ok(_), Err(_)) => false,
224            (Err(_), Ok(_)) => false,
225        }
226    }
227}
228
229impl<T, E> Drop for Result<T, E> {
230    fn drop(&mut self) {
231        unsafe {
232            match self.kind {
233                ResultKind::Ok => {
234                    ManuallyDrop::drop(&mut self.data.ok);
235                }
236                ResultKind::Err => {
237                    ManuallyDrop::drop(&mut self.data.err);
238                }
239            }
240        }
241    }
242}
243
244#[repr(u8)]
245#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
246pub enum ResultKind {
247    Ok,
248    Err,
249}
250
251#[repr(C)]
252pub union ResultData<T, E> {
253    pub ok: ManuallyDrop<T>,
254    pub err: ManuallyDrop<E>,
255}