1use stabby_macros::tyeval;
18
19pub use crate::enums::IDeterminant;
20use crate::enums::IDeterminantProvider;
21use crate::istable::IBitMask;
22use crate::report::FieldReport;
23use crate::str::Str;
24use crate::unsigned::IUnsignedBase;
25use crate::{self as stabby, unreachable_unchecked, Bit, IStable, B0};
26use crate::{Alignment, Tuple, Unsigned};
27
28#[repr(transparent)]
29pub struct Result<Ok, Err>
31where
32 Ok: IDeterminantProvider<Err>,
33 Err: IStable,
34{
35 storage: Storage<<Self as IStable>::Size, <Self as IStable>::Align>,
36}
37impl<Ok: Unpin, Err: Unpin> Unpin for Result<Ok, Err>
38where
39 Ok: IDeterminantProvider<Err>,
40 Err: IStable,
41{
42}
43type Determinant<Ok, Err> = <Ok as IDeterminantProvider<Err>>::Determinant;
44unsafe impl<Ok, Err> IStable for Result<Ok, Err>
46where
47 Ok: IDeterminantProvider<Err>,
48 Err: IStable,
49{
50 type Size = tyeval!(<<Determinant<Ok, Err> as IStable>::Size as Unsigned>::NextMultipleOf<Self::Align> + <Ok::Size as Unsigned>::Max<Err::Size>);
52 type Align = <Ok::Align as Alignment>::Max<Err::Align>;
54 type ContainsIndirections = <Ok::ContainsIndirections as Bit>::Or<Err::ContainsIndirections>;
56 type ForbiddenValues =
58 <<Ok as IDeterminantProvider<Err>>::NicheExporter as IStable>::ForbiddenValues;
59 type UnusedBits = <<Tuple<Determinant<Ok, Err>, <Self::Align as Alignment>::AsUint> as IStable>::UnusedBits as IBitMask>::BitOr<<<<Ok as IDeterminantProvider<Err>>::NicheExporter as IStable>::UnusedBits as IBitMask>::Shift<<<Determinant<Ok, Err> as IStable>::Size as Unsigned>::NextMultipleOf<Self::Align>>>;
61 type HasExactlyOneNiche = B0;
63 #[cfg(feature = "experimental-ctypes")]
64 type CType = <Storage<<Self as IStable>::Size, <Self as IStable>::Align> as IStable>::CType;
65 const REPORT: &'static crate::report::TypeReport = &crate::report::TypeReport {
66 name: Str::new("Result"),
67 module: Str::new("stabby_abi::result"),
68 tyty: crate::report::TyTy::Enum(Str::new("stabby")),
69 version: 1,
70 fields: crate::StableLike::new(Some(&FieldReport {
71 name: Str::new("Ok"),
72 ty: Ok::REPORT,
73 next_field: crate::StableLike::new(Some(&FieldReport {
74 name: Str::new("Err"),
75 ty: Err::REPORT,
76 next_field: crate::StableLike::new(None),
77 })),
78 })),
79 };
80 const ID: u64 = crate::report::gen_id(Self::REPORT);
81}
82use seal::Storage;
83mod seal {
84 use super::*;
85 #[stabby::stabby]
86 pub struct Storage<Size: Unsigned, Align: Alignment + Alignment> {
87 inner: <Align::Divide<Size> as IUnsignedBase>::Array<Align::AsUint>,
88 }
89}
90
91impl<Size: Unsigned, Align: Alignment + Alignment> Storage<Size, Align> {
92 const fn as_ptr(&self) -> *const u8 {
93 self as *const Self as *const _
94 }
95 fn as_mut_ptr(&mut self) -> *mut u8 {
96 self as *mut Self as *mut _
97 }
98}
99
100impl<Ok: Clone, Err: Clone> Clone for Result<Ok, Err>
101where
102 Ok: IDeterminantProvider<Err>,
103 Err: IStable,
104{
105 fn clone(&self) -> Self {
106 self.match_ref(|ok| Self::Ok(ok.clone()), |err| Self::Err(err.clone()))
107 }
108}
109impl<Ok, Err> core::fmt::Debug for Result<Ok, Err>
110where
111 Ok: IDeterminantProvider<Err>,
112 Err: IStable,
113 Ok: core::fmt::Debug,
114 Err: core::fmt::Debug,
115{
116 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
117 self.as_ref().fmt(f)
118 }
119}
120impl<Ok, Err> core::hash::Hash for Result<Ok, Err>
121where
122 Ok: IDeterminantProvider<Err>,
123 Err: IStable,
124 Ok: core::hash::Hash,
125 Err: core::hash::Hash,
126{
127 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
128 if self.is_ok() {
129 true.hash(state);
130 unsafe { self.ok_unchecked() }.hash(state);
131 } else {
132 false.hash(state);
133 unsafe { self.err_unchecked() }.hash(state);
134 }
135 }
136}
137impl<Ok, Err> core::cmp::PartialEq for Result<Ok, Err>
138where
139 Ok: IDeterminantProvider<Err>,
140 Err: IStable,
141 Ok: core::cmp::PartialEq,
142 Err: core::cmp::PartialEq,
143{
144 fn eq(&self, other: &Self) -> bool {
145 match (self.is_ok(), other.is_ok()) {
146 (true, true) => unsafe { self.ok_unchecked().eq(other.ok_unchecked()) },
147 (false, false) => unsafe { self.err_unchecked().eq(other.err_unchecked()) },
148 _ => false,
149 }
150 }
151}
152impl<Ok, Err> core::cmp::Eq for Result<Ok, Err>
153where
154 Ok: IDeterminantProvider<Err>,
155 Err: IStable,
156 Ok: core::cmp::Eq,
157 Err: core::cmp::Eq,
158{
159}
160impl<Ok, Err> From<core::result::Result<Ok, Err>> for Result<Ok, Err>
161where
162 Ok: IDeterminantProvider<Err>,
163 Err: IStable,
164{
165 fn from(value: core::result::Result<Ok, Err>) -> Self {
166 match value {
167 Ok(value) => Self::Ok(value),
168 Err(value) => Self::Err(value),
169 }
170 }
171}
172impl<Ok, Err> From<Result<Ok, Err>> for core::result::Result<Ok, Err>
173where
174 Ok: IDeterminantProvider<Err>,
175 Err: IStable,
176{
177 fn from(value: Result<Ok, Err>) -> Self {
178 value.match_owned(Ok, Err)
179 }
180}
181impl<Ok, Err> Drop for Result<Ok, Err>
182where
183 Ok: IDeterminantProvider<Err>,
184 Err: IStable,
185{
186 fn drop(&mut self) {
187 unsafe {
188 self.match_mut(
189 |mut ok| core::ptr::drop_in_place::<Ok>(&mut *ok),
190 |mut err| core::ptr::drop_in_place::<Err>(&mut *err),
191 )
192 }
193 }
194}
195impl<Ok, Err> Result<Ok, Err>
196where
197 Ok: IDeterminantProvider<Err>,
198 Err: IStable,
199{
200 const DET_SIZE: usize = <<<Determinant<Ok, Err> as IStable>::Size as Unsigned>::NextMultipleOf<
201 <Self as IStable>::Align,
202 > as Unsigned>::USIZE;
203 const OK_OFFSET: usize =
204 <<Ok as IDeterminantProvider<Err>>::OkShift as Unsigned>::USIZE + Self::DET_SIZE;
205 const ERR_OFFSET: usize =
206 <<Ok as IDeterminantProvider<Err>>::ErrShift as Unsigned>::USIZE + Self::DET_SIZE;
207 const fn ok_ptr(
208 storage: *const Storage<<Self as IStable>::Size, <Self as IStable>::Align>,
209 ) -> *const Ok {
210 unsafe { storage.cast::<u8>().add(Self::OK_OFFSET).cast() }
211 }
212 const fn ok_ptr_mut(
213 storage: *mut Storage<<Self as IStable>::Size, <Self as IStable>::Align>,
214 ) -> *mut Ok {
215 unsafe { storage.cast::<u8>().add(Self::OK_OFFSET).cast() }
216 }
217 const fn err_ptr(
218 storage: *const Storage<<Self as IStable>::Size, <Self as IStable>::Align>,
219 ) -> *const Err {
220 unsafe { storage.cast::<u8>().add(Self::ERR_OFFSET).cast() }
221 }
222 const fn err_ptr_mut(
223 storage: *mut Storage<<Self as IStable>::Size, <Self as IStable>::Align>,
224 ) -> *mut Err {
225 unsafe { storage.cast::<u8>().add(Self::ERR_OFFSET).cast() }
226 }
227 const fn det_ptr(
228 storage: *const Storage<<Self as IStable>::Size, <Self as IStable>::Align>,
229 ) -> *const Determinant<Ok, Err> {
230 storage.cast()
231 }
232 const fn det_ptr_mut(
233 storage: *mut Storage<<Self as IStable>::Size, <Self as IStable>::Align>,
234 ) -> *mut Determinant<Ok, Err> {
235 storage.cast()
236 }
237 #[allow(non_snake_case)]
239 pub fn Ok(value: Ok) -> Self {
240 let mut storage = core::mem::MaybeUninit::zeroed();
241 unsafe {
242 let storage_ptr = storage.as_mut_ptr();
243 Self::ok_ptr_mut(storage_ptr).write(value);
244 Self::det_ptr_mut(storage_ptr).write(Determinant::<Ok, Err>::ok(storage_ptr.cast()));
245 Self {
246 storage: storage.assume_init(),
247 }
248 }
249 }
250 #[allow(non_snake_case)]
252 pub fn Err(value: Err) -> Self {
253 let mut storage = core::mem::MaybeUninit::zeroed();
254 unsafe {
255 let storage_ptr = storage.as_mut_ptr();
256 Self::err_ptr_mut(storage_ptr).write(value);
257 Self::det_ptr_mut(storage_ptr).write(Determinant::<Ok, Err>::err(storage_ptr.cast()));
258 Self {
259 storage: storage.assume_init(),
260 }
261 }
262 }
263 #[allow(clippy::missing_errors_doc)]
265 pub fn as_ref(&self) -> core::result::Result<&Ok, &Err> {
266 self.match_ref(Ok, Err)
267 }
268
269 pub fn match_ref<'a, U, FnOk: FnOnce(&'a Ok) -> U, FnErr: FnOnce(&'a Err) -> U>(
272 &'a self,
273 ok: FnOk,
274 err: FnErr,
275 ) -> U {
276 if self.is_ok() {
277 unsafe { ok(self.ok_unchecked()) }
278 } else {
279 unsafe { err(self.err_unchecked()) }
280 }
281 }
282 pub fn match_ref_ctx<'a, T, U, FnOk: FnOnce(T, &'a Ok) -> U, FnErr: FnOnce(T, &'a Err) -> U>(
284 &'a self,
285 ctx: T,
286 ok: FnOk,
287 err: FnErr,
288 ) -> U {
289 if self.is_ok() {
290 unsafe { ok(ctx, self.ok_unchecked()) }
291 } else {
292 unsafe { err(ctx, self.err_unchecked()) }
293 }
294 }
295 pub fn match_mut<
298 'a,
299 U,
300 FnOk: FnOnce(OkGuard<'a, Ok, Err>) -> U,
301 FnErr: FnOnce(ErrGuard<'a, Ok, Err>) -> U,
302 >(
303 &'a mut self,
304 ok: FnOk,
305 err: FnErr,
306 ) -> U {
307 let r;
308 if Self::is_ok(self) {
309 unsafe {
310 r = ok(self.ok_mut_unchecked());
311 }
312 } else {
313 unsafe {
314 r = err(self.err_mut_unchecked());
315 }
316 }
317 r
318 }
319 pub fn match_mut_ctx<
321 'a,
322 T,
323 U,
324 FnOk: FnOnce(T, OkGuard<'a, Ok, Err>) -> U,
325 FnErr: FnOnce(T, ErrGuard<'_, Ok, Err>) -> U,
326 >(
327 &'a mut self,
328 ctx: T,
329 ok: FnOk,
330 err: FnErr,
331 ) -> U {
332 let r;
333 if Self::is_ok(self) {
334 unsafe {
335 r = ok(ctx, self.ok_mut_unchecked());
336 }
337 } else {
338 unsafe {
339 r = err(ctx, self.err_mut_unchecked());
340 }
341 }
342 r
343 }
344 pub fn match_owned<U, FnOk: FnOnce(Ok) -> U, FnErr: FnOnce(Err) -> U>(
347 self,
348 ok: FnOk,
349 err: FnErr,
350 ) -> U {
351 let is_ok = self.is_ok();
352 let storage = &self.storage;
353 if is_ok {
354 let t = unsafe { core::ptr::read(Self::ok_ptr(storage)) };
355 core::mem::forget(self);
356 ok(t)
357 } else {
358 let t = unsafe { core::ptr::read(Self::err_ptr(storage)) };
359 core::mem::forget(self);
360 err(t)
361 }
362 }
363 pub fn match_owned_ctx<U, T, FnOk: FnOnce(T, Ok) -> U, FnErr: FnOnce(T, Err) -> U>(
365 self,
366 ctx: T,
367 ok: FnOk,
368 err: FnErr,
369 ) -> U {
370 let is_ok = self.is_ok();
371 let storage = &self.storage;
372 if is_ok {
373 let t = unsafe { core::ptr::read(Self::ok_ptr(storage)) };
374 core::mem::forget(self);
375 ok(ctx, t)
376 } else {
377 let t = unsafe { core::ptr::read(Self::err_ptr(storage)) };
378 core::mem::forget(self);
379 err(ctx, t)
380 }
381 }
382 pub fn is_ok(&self) -> bool {
384 unsafe { &*Self::det_ptr(&self.storage) }.is_det_ok(self.storage.as_ptr())
385 }
386 pub fn is_err(&self) -> bool {
388 !self.is_ok()
389 }
390 pub fn ok(self) -> Option<Ok> {
392 self.match_owned(Some, |_| None)
393 }
394 pub fn err(self) -> Option<Err> {
396 self.match_owned(|_| None, Some)
397 }
398 pub fn ok_ref(&self) -> Option<&Ok> {
400 self.match_ref(Some, |_| None)
401 }
402 pub fn err_ref(&self) -> Option<&Err> {
404 self.match_ref(|_| None, Some)
405 }
406 pub fn ok_mut(&mut self) -> Option<OkGuard<'_, Ok, Err>> {
408 self.match_mut(Some, |_| None)
409 }
410 pub fn err_mut(&mut self) -> Option<ErrGuard<'_, Ok, Err>> {
412 self.match_mut(|_| None, Some)
413 }
414 pub fn map<F: FnOnce(Ok) -> U, U>(self, f: F) -> Result<U, Err>
416 where
417 U: IDeterminantProvider<Err>,
418 {
419 self.match_owned(move |x| Result::Ok(f(x)), |x| Result::Err(x))
420 }
421 pub fn and_then<F: FnOnce(Ok) -> Result<U, Err>, U>(self, f: F) -> Result<U, Err>
423 where
424 U: IDeterminantProvider<Err>,
425 {
426 self.match_owned(f, |x| Result::Err(x))
427 }
428 pub fn unwrap_or_else<F: FnOnce(Err) -> Ok>(self, f: F) -> Ok {
430 self.match_owned(|x| x, f)
431 }
432 pub unsafe fn unwrap_unchecked(self) -> Ok {
435 self.unwrap_or_else(|_| unsafe { unreachable_unchecked!() })
436 }
437 pub fn unwrap(self) -> Ok
440 where
441 Err: core::fmt::Debug,
442 {
443 self.unwrap_or_else(|e| panic!("Result::unwrap called on Err variant: {e:?}"))
444 }
445 pub fn unwrap_err_or_else<F: FnOnce(Ok) -> Err>(self, f: F) -> Err {
447 self.match_owned(f, |x| x)
448 }
449 pub unsafe fn unwrap_err_unchecked(self) -> Err {
452 self.unwrap_err_or_else(|_| unsafe { unreachable_unchecked!() })
453 }
454 pub fn unwrap_err(self) -> Err
457 where
458 Ok: core::fmt::Debug,
459 {
460 self.unwrap_err_or_else(|e| panic!("Result::unwrap_err called on Ok variant: {e:?}"))
461 }
462 const unsafe fn ok_unchecked(&self) -> &Ok {
463 &*Self::ok_ptr(&self.storage)
464 }
465 const unsafe fn err_unchecked(&self) -> &Err {
466 &*Self::err_ptr(&self.storage)
467 }
468 unsafe fn ok_mut_unchecked(&mut self) -> OkGuard<'_, Ok, Err> {
469 OkGuard { inner: self }
470 }
471 unsafe fn err_mut_unchecked(&mut self) -> ErrGuard<Ok, Err> {
472 ErrGuard { inner: self }
473 }
474}
475
476pub struct OkGuard<'a, Ok, Err>
481where
482 Ok: IDeterminantProvider<Err>,
483 Err: IStable,
484{
485 inner: &'a mut Result<Ok, Err>,
486}
487impl<Ok, Err> core::ops::Deref for OkGuard<'_, Ok, Err>
488where
489 Ok: IDeterminantProvider<Err>,
490 Err: IStable,
491{
492 type Target = Ok;
493 fn deref(&self) -> &Self::Target {
494 unsafe { self.inner.ok_unchecked() }
495 }
496}
497impl<Ok, Err> core::ops::DerefMut for OkGuard<'_, Ok, Err>
498where
499 Ok: IDeterminantProvider<Err>,
500 Err: IStable,
501{
502 fn deref_mut(&mut self) -> &mut Self::Target {
503 unsafe { &mut *Result::<Ok, Err>::ok_ptr_mut(&mut self.inner.storage) }
504 }
505}
506impl<Ok, Err> Drop for OkGuard<'_, Ok, Err>
507where
508 Ok: IDeterminantProvider<Err>,
509 Err: IStable,
510{
511 fn drop(&mut self) {
512 if <<Determinant<Ok, Err> as IDeterminant>::IsNicheTrick as Bit>::BOOL {
513 unsafe { Determinant::<Ok, Err>::ok(self.inner.storage.as_mut_ptr()) };
514 }
515 }
516}
517
518pub struct ErrGuard<'a, Ok, Err>
523where
524 Ok: IDeterminantProvider<Err>,
525 Err: IStable,
526{
527 inner: &'a mut Result<Ok, Err>,
528}
529
530impl<Ok, Err> core::ops::Deref for ErrGuard<'_, Ok, Err>
531where
532 Ok: IDeterminantProvider<Err>,
533 Err: IStable,
534{
535 type Target = Err;
536 fn deref(&self) -> &Self::Target {
537 unsafe { self.inner.err_unchecked() }
538 }
539}
540impl<Ok, Err> core::ops::DerefMut for ErrGuard<'_, Ok, Err>
541where
542 Ok: IDeterminantProvider<Err>,
543 Err: IStable,
544{
545 fn deref_mut(&mut self) -> &mut Self::Target {
546 unsafe { &mut *Result::<Ok, Err>::err_ptr_mut(&mut self.inner.storage) }
547 }
548}
549impl<Ok, Err> Drop for ErrGuard<'_, Ok, Err>
550where
551 Ok: IDeterminantProvider<Err>,
552 Err: IStable,
553{
554 fn drop(&mut self) {
555 if <<Determinant<Ok, Err> as IDeterminant>::IsNicheTrick as Bit>::BOOL {
556 unsafe { Determinant::<Ok, Err>::err(self.inner.storage.as_mut_ptr()) };
557 }
558 }
559}
560
561#[cfg(feature = "serde")]
562mod serde_impl {
563 use super::*;
564 use serde::{Deserialize, Serialize};
565 impl<Ok: Serialize, Err: Serialize> Serialize for Result<Ok, Err>
566 where
567 Ok: IDeterminantProvider<Err>,
568 Err: IStable,
569 {
570 fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
571 where
572 S: serde::Serializer,
573 {
574 let this: core::result::Result<_, _> = self.as_ref();
575 this.serialize(serializer)
576 }
577 }
578 impl<'a, Ok: IDeterminantProvider<Err>, Err: IStable> Deserialize<'a> for Result<Ok, Err>
579 where
580 core::result::Result<Ok, Err>: Deserialize<'a>,
581 {
582 fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
583 where
584 D: serde::Deserializer<'a>,
585 {
586 Ok(core::result::Result::<Ok, Err>::deserialize(deserializer)?.into())
587 }
588 }
589}