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 core::mem::MaybeUninit;
85
86 use super::*;
87 #[stabby::stabby]
88 pub struct Storage<Size: Unsigned, Align: Alignment + Alignment> {
89 inner: MaybeUninit<<Align::Divide<Size> as IUnsignedBase>::Array<Align::AsUint>>,
90 }
91 impl<Size: Unsigned, Align: Alignment + Alignment> Storage<Size, Align> {
92 pub const fn zeroed() -> Self {
93 Self {
94 inner: MaybeUninit::zeroed(),
95 }
96 }
97 }
98}
99
100impl<Size: Unsigned, Align: Alignment + Alignment> Storage<Size, Align> {
101 const fn as_ptr(&self) -> *const u8 {
102 self as *const Self as *const _
103 }
104 #[rustversion::attr(since(1.86), const)]
105 fn as_mut_ptr(&mut self) -> *mut u8 {
106 self as *mut Self as *mut _
107 }
108}
109
110impl<Ok: Clone, Err: Clone> Clone for Result<Ok, Err>
111where
112 Ok: IDeterminantProvider<Err>,
113 Err: IStable,
114{
115 fn clone(&self) -> Self {
116 self.match_ref(|ok| Self::Ok(ok.clone()), |err| Self::Err(err.clone()))
117 }
118}
119impl<Ok, Err> core::fmt::Debug for Result<Ok, Err>
120where
121 Ok: IDeterminantProvider<Err>,
122 Err: IStable,
123 Ok: core::fmt::Debug,
124 Err: core::fmt::Debug,
125{
126 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
127 self.as_ref().fmt(f)
128 }
129}
130impl<Ok, Err> core::hash::Hash for Result<Ok, Err>
131where
132 Ok: IDeterminantProvider<Err>,
133 Err: IStable,
134 Ok: core::hash::Hash,
135 Err: core::hash::Hash,
136{
137 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
138 if self.is_ok() {
139 true.hash(state);
140 unsafe { self.ok_unchecked() }.hash(state);
141 } else {
142 false.hash(state);
143 unsafe { self.err_unchecked() }.hash(state);
144 }
145 }
146}
147impl<Ok, Err> core::cmp::PartialEq for Result<Ok, Err>
148where
149 Ok: IDeterminantProvider<Err>,
150 Err: IStable,
151 Ok: core::cmp::PartialEq,
152 Err: core::cmp::PartialEq,
153{
154 fn eq(&self, other: &Self) -> bool {
155 match (self.is_ok(), other.is_ok()) {
156 (true, true) => unsafe { self.ok_unchecked().eq(other.ok_unchecked()) },
157 (false, false) => unsafe { self.err_unchecked().eq(other.err_unchecked()) },
158 _ => false,
159 }
160 }
161}
162impl<Ok, Err> core::cmp::Eq for Result<Ok, Err>
163where
164 Ok: IDeterminantProvider<Err>,
165 Err: IStable,
166 Ok: core::cmp::Eq,
167 Err: core::cmp::Eq,
168{
169}
170impl<Ok, Err> From<core::result::Result<Ok, Err>> for Result<Ok, Err>
171where
172 Ok: IDeterminantProvider<Err>,
173 Err: IStable,
174{
175 fn from(value: core::result::Result<Ok, Err>) -> Self {
176 match value {
177 Ok(value) => Self::Ok(value),
178 Err(value) => Self::Err(value),
179 }
180 }
181}
182impl<Ok, Err> From<Result<Ok, Err>> for core::result::Result<Ok, Err>
183where
184 Ok: IDeterminantProvider<Err>,
185 Err: IStable,
186{
187 fn from(value: Result<Ok, Err>) -> Self {
188 value.match_owned(Ok, Err)
189 }
190}
191impl<Ok, Err> Drop for Result<Ok, Err>
192where
193 Ok: IDeterminantProvider<Err>,
194 Err: IStable,
195{
196 fn drop(&mut self) {
197 unsafe {
198 self.match_mut(
199 |mut ok| core::ptr::drop_in_place::<Ok>(&mut *ok),
200 |mut err| core::ptr::drop_in_place::<Err>(&mut *err),
201 )
202 }
203 }
204}
205impl<Ok, Err> Result<Ok, Err>
206where
207 Ok: IDeterminantProvider<Err>,
208 Err: IStable,
209{
210 const DET_SIZE: usize = <<<Determinant<Ok, Err> as IStable>::Size as Unsigned>::NextMultipleOf<
211 <Self as IStable>::Align,
212 > as Unsigned>::USIZE;
213 const OK_OFFSET: usize =
214 <<Ok as IDeterminantProvider<Err>>::OkShift as Unsigned>::USIZE + Self::DET_SIZE;
215 const ERR_OFFSET: usize =
216 <<Ok as IDeterminantProvider<Err>>::ErrShift as Unsigned>::USIZE + Self::DET_SIZE;
217 const fn ok_ptr(
218 storage: *const Storage<<Self as IStable>::Size, <Self as IStable>::Align>,
219 ) -> *const Ok {
220 unsafe { storage.cast::<u8>().add(Self::OK_OFFSET).cast() }
221 }
222 const fn ok_ptr_mut(
223 storage: *mut Storage<<Self as IStable>::Size, <Self as IStable>::Align>,
224 ) -> *mut Ok {
225 unsafe { storage.cast::<u8>().add(Self::OK_OFFSET).cast() }
226 }
227 const fn err_ptr(
228 storage: *const Storage<<Self as IStable>::Size, <Self as IStable>::Align>,
229 ) -> *const Err {
230 unsafe { storage.cast::<u8>().add(Self::ERR_OFFSET).cast() }
231 }
232 const fn err_ptr_mut(
233 storage: *mut Storage<<Self as IStable>::Size, <Self as IStable>::Align>,
234 ) -> *mut Err {
235 unsafe { storage.cast::<u8>().add(Self::ERR_OFFSET).cast() }
236 }
237 const fn det_ptr(
238 storage: *const Storage<<Self as IStable>::Size, <Self as IStable>::Align>,
239 ) -> *const Determinant<Ok, Err> {
240 storage.cast()
241 }
242 const fn det_ptr_mut(
243 storage: *mut Storage<<Self as IStable>::Size, <Self as IStable>::Align>,
244 ) -> *mut Determinant<Ok, Err> {
245 storage.cast()
246 }
247 #[allow(non_snake_case)]
249 pub fn Ok(value: Ok) -> Self {
250 let mut storage = Storage::zeroed();
251 let storage_ptr = &mut storage as *mut _;
252 unsafe {
253 Self::ok_ptr_mut(storage_ptr).write(value);
254 Self::det_ptr_mut(storage_ptr).write(Determinant::<Ok, Err>::ok(storage_ptr.cast()));
255 Self { storage }
256 }
257 }
258 #[allow(non_snake_case)]
260 pub fn Err(value: Err) -> Self {
261 let mut storage = Storage::zeroed();
262 unsafe {
263 let storage_ptr = &mut storage as *mut _;
264 Self::err_ptr_mut(storage_ptr).write(value);
265 Self::det_ptr_mut(storage_ptr).write(Determinant::<Ok, Err>::err(storage_ptr.cast()));
266 Self { storage }
267 }
268 }
269 #[allow(clippy::missing_errors_doc)]
271 pub fn as_ref(&self) -> core::result::Result<&Ok, &Err> {
272 self.match_ref(Ok, Err)
273 }
274
275 pub fn match_ref<'a, U, FnOk: FnOnce(&'a Ok) -> U, FnErr: FnOnce(&'a Err) -> U>(
278 &'a self,
279 ok: FnOk,
280 err: FnErr,
281 ) -> U {
282 if self.is_ok() {
283 unsafe { ok(self.ok_unchecked()) }
284 } else {
285 unsafe { err(self.err_unchecked()) }
286 }
287 }
288 pub fn match_ref_ctx<'a, T, U, FnOk: FnOnce(T, &'a Ok) -> U, FnErr: FnOnce(T, &'a Err) -> U>(
290 &'a self,
291 ctx: T,
292 ok: FnOk,
293 err: FnErr,
294 ) -> U {
295 if self.is_ok() {
296 unsafe { ok(ctx, self.ok_unchecked()) }
297 } else {
298 unsafe { err(ctx, self.err_unchecked()) }
299 }
300 }
301 pub fn match_mut<
304 'a,
305 U,
306 FnOk: FnOnce(OkGuard<'a, Ok, Err>) -> U,
307 FnErr: FnOnce(ErrGuard<'a, Ok, Err>) -> U,
308 >(
309 &'a mut self,
310 ok: FnOk,
311 err: FnErr,
312 ) -> U {
313 let r;
314 if Self::is_ok(self) {
315 unsafe {
316 r = ok(self.ok_mut_unchecked());
317 }
318 } else {
319 unsafe {
320 r = err(self.err_mut_unchecked());
321 }
322 }
323 r
324 }
325 pub fn match_mut_ctx<
327 'a,
328 T,
329 U,
330 FnOk: FnOnce(T, OkGuard<'a, Ok, Err>) -> U,
331 FnErr: FnOnce(T, ErrGuard<'_, Ok, Err>) -> U,
332 >(
333 &'a mut self,
334 ctx: T,
335 ok: FnOk,
336 err: FnErr,
337 ) -> U {
338 let r;
339 if Self::is_ok(self) {
340 unsafe {
341 r = ok(ctx, self.ok_mut_unchecked());
342 }
343 } else {
344 unsafe {
345 r = err(ctx, self.err_mut_unchecked());
346 }
347 }
348 r
349 }
350 pub fn match_owned<U, FnOk: FnOnce(Ok) -> U, FnErr: FnOnce(Err) -> U>(
353 self,
354 ok: FnOk,
355 err: FnErr,
356 ) -> U {
357 let is_ok = self.is_ok();
358 let storage = &self.storage;
359 if is_ok {
360 let t = unsafe { core::ptr::read(Self::ok_ptr(storage)) };
361 core::mem::forget(self);
362 ok(t)
363 } else {
364 let t = unsafe { core::ptr::read(Self::err_ptr(storage)) };
365 core::mem::forget(self);
366 err(t)
367 }
368 }
369 pub fn match_owned_ctx<U, T, FnOk: FnOnce(T, Ok) -> U, FnErr: FnOnce(T, Err) -> U>(
371 self,
372 ctx: T,
373 ok: FnOk,
374 err: FnErr,
375 ) -> U {
376 let is_ok = self.is_ok();
377 let storage = &self.storage;
378 if is_ok {
379 let t = unsafe { core::ptr::read(Self::ok_ptr(storage)) };
380 core::mem::forget(self);
381 ok(ctx, t)
382 } else {
383 let t = unsafe { core::ptr::read(Self::err_ptr(storage)) };
384 core::mem::forget(self);
385 err(ctx, t)
386 }
387 }
388 pub fn is_ok(&self) -> bool {
390 unsafe { &*Self::det_ptr(&self.storage) }.is_det_ok(self.storage.as_ptr())
391 }
392 pub fn is_err(&self) -> bool {
394 !self.is_ok()
395 }
396 pub fn ok(self) -> Option<Ok> {
398 self.match_owned(Some, |_| None)
399 }
400 pub fn err(self) -> Option<Err> {
402 self.match_owned(|_| None, Some)
403 }
404 pub fn ok_ref(&self) -> Option<&Ok> {
406 self.match_ref(Some, |_| None)
407 }
408 pub fn err_ref(&self) -> Option<&Err> {
410 self.match_ref(|_| None, Some)
411 }
412 pub fn ok_mut(&mut self) -> Option<OkGuard<'_, Ok, Err>> {
414 self.match_mut(Some, |_| None)
415 }
416 pub fn err_mut(&mut self) -> Option<ErrGuard<'_, Ok, Err>> {
418 self.match_mut(|_| None, Some)
419 }
420 pub fn map<F: FnOnce(Ok) -> U, U>(self, f: F) -> Result<U, Err>
422 where
423 U: IDeterminantProvider<Err>,
424 {
425 self.match_owned(move |x| Result::Ok(f(x)), |x| Result::Err(x))
426 }
427 pub fn and_then<F: FnOnce(Ok) -> Result<U, Err>, U>(self, f: F) -> Result<U, Err>
429 where
430 U: IDeterminantProvider<Err>,
431 {
432 self.match_owned(f, |x| Result::Err(x))
433 }
434 pub fn unwrap_or_else<F: FnOnce(Err) -> Ok>(self, f: F) -> Ok {
436 self.match_owned(|x| x, f)
437 }
438 pub unsafe fn unwrap_unchecked(self) -> Ok {
441 self.unwrap_or_else(|_| unsafe { unreachable_unchecked!() })
442 }
443 pub fn unwrap(self) -> Ok
446 where
447 Err: core::fmt::Debug,
448 {
449 self.unwrap_or_else(|e| panic!("Result::unwrap called on Err variant: {e:?}"))
450 }
451 pub fn unwrap_err_or_else<F: FnOnce(Ok) -> Err>(self, f: F) -> Err {
453 self.match_owned(f, |x| x)
454 }
455 pub unsafe fn unwrap_err_unchecked(self) -> Err {
458 self.unwrap_err_or_else(|_| unsafe { unreachable_unchecked!() })
459 }
460 pub fn unwrap_err(self) -> Err
463 where
464 Ok: core::fmt::Debug,
465 {
466 self.unwrap_err_or_else(|e| panic!("Result::unwrap_err called on Ok variant: {e:?}"))
467 }
468 const unsafe fn ok_unchecked(&self) -> &Ok {
469 &*Self::ok_ptr(&self.storage)
470 }
471 const unsafe fn err_unchecked(&self) -> &Err {
472 &*Self::err_ptr(&self.storage)
473 }
474 #[rustversion::attr(since(1.86), const)]
475 unsafe fn ok_mut_unchecked(&mut self) -> OkGuard<'_, Ok, Err> {
476 OkGuard { inner: self }
477 }
478 #[rustversion::attr(since(1.86), const)]
479 unsafe fn err_mut_unchecked(&mut self) -> ErrGuard<Ok, Err> {
480 ErrGuard { inner: self }
481 }
482}
483
484pub struct OkGuard<'a, Ok, Err>
489where
490 Ok: IDeterminantProvider<Err>,
491 Err: IStable,
492{
493 inner: &'a mut Result<Ok, Err>,
494}
495impl<Ok, Err> core::ops::Deref for OkGuard<'_, Ok, Err>
496where
497 Ok: IDeterminantProvider<Err>,
498 Err: IStable,
499{
500 type Target = Ok;
501 fn deref(&self) -> &Self::Target {
502 unsafe { self.inner.ok_unchecked() }
503 }
504}
505impl<Ok, Err> core::ops::DerefMut for OkGuard<'_, Ok, Err>
506where
507 Ok: IDeterminantProvider<Err>,
508 Err: IStable,
509{
510 fn deref_mut(&mut self) -> &mut Self::Target {
511 unsafe { &mut *Result::<Ok, Err>::ok_ptr_mut(&mut self.inner.storage) }
512 }
513}
514impl<Ok, Err> Drop for OkGuard<'_, Ok, Err>
515where
516 Ok: IDeterminantProvider<Err>,
517 Err: IStable,
518{
519 fn drop(&mut self) {
520 if <<Determinant<Ok, Err> as IDeterminant>::IsNicheTrick as Bit>::BOOL {
521 unsafe { Determinant::<Ok, Err>::ok(self.inner.storage.as_mut_ptr()) };
522 }
523 }
524}
525
526pub struct ErrGuard<'a, Ok, Err>
531where
532 Ok: IDeterminantProvider<Err>,
533 Err: IStable,
534{
535 inner: &'a mut Result<Ok, Err>,
536}
537
538impl<Ok, Err> core::ops::Deref for ErrGuard<'_, Ok, Err>
539where
540 Ok: IDeterminantProvider<Err>,
541 Err: IStable,
542{
543 type Target = Err;
544 fn deref(&self) -> &Self::Target {
545 unsafe { self.inner.err_unchecked() }
546 }
547}
548impl<Ok, Err> core::ops::DerefMut for ErrGuard<'_, Ok, Err>
549where
550 Ok: IDeterminantProvider<Err>,
551 Err: IStable,
552{
553 fn deref_mut(&mut self) -> &mut Self::Target {
554 unsafe { &mut *Result::<Ok, Err>::err_ptr_mut(&mut self.inner.storage) }
555 }
556}
557impl<Ok, Err> Drop for ErrGuard<'_, Ok, Err>
558where
559 Ok: IDeterminantProvider<Err>,
560 Err: IStable,
561{
562 fn drop(&mut self) {
563 if <<Determinant<Ok, Err> as IDeterminant>::IsNicheTrick as Bit>::BOOL {
564 unsafe { Determinant::<Ok, Err>::err(self.inner.storage.as_mut_ptr()) };
565 }
566 }
567}
568
569#[cfg(feature = "serde")]
570mod serde_impl {
571 use super::*;
572 use serde::{Deserialize, Serialize};
573 impl<Ok: Serialize, Err: Serialize> Serialize for Result<Ok, Err>
574 where
575 Ok: IDeterminantProvider<Err>,
576 Err: IStable,
577 {
578 fn serialize<S>(&self, serializer: S) -> core::result::Result<S::Ok, S::Error>
579 where
580 S: serde::Serializer,
581 {
582 let this: core::result::Result<_, _> = self.as_ref();
583 this.serialize(serializer)
584 }
585 }
586 impl<'a, Ok: IDeterminantProvider<Err>, Err: IStable> Deserialize<'a> for Result<Ok, Err>
587 where
588 core::result::Result<Ok, Err>: Deserialize<'a>,
589 {
590 fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
591 where
592 D: serde::Deserializer<'a>,
593 {
594 Ok(core::result::Result::<Ok, Err>::deserialize(deserializer)?.into())
595 }
596 }
597}