1pub mod prelude {
84 pub use super::explicit::*;
85
86 pub use or_return as r;
88
89 pub use or_return_quiet as rq;
91
92 pub use or_return_log_once as ro;
94
95 pub use or_continue as c;
97
98 pub use or_continue_quiet as cq;
100
101 pub use or_continue_log_once as co;
103
104 pub use or_break as b;
106
107 pub use or_break_quiet as bq;
109
110 pub use or_break_log_once as bo;
112}
113
114pub mod explicit {
124 pub use super::{
125 or_break, or_break_log_once, or_break_quiet, or_continue, or_continue_log_once,
126 or_continue_quiet, or_return, or_return_log_once, or_return_quiet,
127 };
128}
129
130#[cfg(all(feature = "log", feature = "tracing"))]
132compile_error!("multiple log backend features are set (log, tracing)");
133#[cfg(any(
134 all(feature = "trace", feature = "debug"),
135 all(feature = "trace", feature = "info"),
136 all(feature = "trace", feature = "warn"),
137 all(feature = "trace", feature = "error"),
138 all(feature = "debug", feature = "info"),
139 all(feature = "debug", feature = "warn"),
140 all(feature = "debug", feature = "error"),
141 all(feature = "info", feature = "warn"),
142 all(feature = "info", feature = "error"),
143 all(feature = "warn", feature = "error"),
144))]
145compile_error!("multiple log level features are set (trace, debug, info, warn, error)");
146#[cfg(all(
147 any(feature = "log", feature = "tracing"),
148 not(any(
149 feature = "trace",
150 feature = "debug",
151 feature = "info",
152 feature = "warn",
153 feature = "error",
154 )),
155))]
156compile_error!(
157 "a log backend feature is set (log, tracing), but no log level feature is set (trace, debug, info, warn, error)",
158);
159#[cfg(all(
160 not(any(feature = "log", feature = "tracing")),
161 any(
162 feature = "trace",
163 feature = "debug",
164 feature = "info",
165 feature = "warn",
166 feature = "error",
167 ),
168))]
169compile_error!(
170 "a log level feature is set (trace, debug, info, warn, error), but no log backend feature is set (log, tracing)",
171);
172
173#[doc(hidden)]
175pub mod __log_backend {
176 #[cfg(feature = "log")]
177 pub use log::{debug, error, info, trace, warn};
178
179 #[cfg(feature = "tracing")]
180 pub use tracing::{debug, error, info, trace, warn};
181
182 #[cfg(not(any(feature = "log", feature = "tracing")))]
183 pub use std::println;
184}
185
186macro_rules! set_log_level {
188 ($level:ident) => {
189 #[doc(hidden)]
191 #[macro_export]
192 macro_rules! ___log_bail {
193 ($expr:expr, $err:expr) => {
194 $crate::__log_backend::$level!(
195 "Bailed at {}:{}:{}: `{}` is `{:?}`",
196 file!(),
197 line!(),
198 column!(),
199 stringify!($expr),
200 $err,
201 );
202 };
203 }
204
205 #[doc(hidden)]
207 pub use ___log_bail as __log_bail;
208 };
209}
210
211#[cfg(feature = "trace")]
212set_log_level!(trace);
213#[cfg(feature = "debug")]
214set_log_level!(debug);
215#[cfg(feature = "info")]
216set_log_level!(info);
217#[cfg(feature = "warn")]
218set_log_level!(warn);
219#[cfg(feature = "error")]
220set_log_level!(error);
221#[cfg(not(any(
222 feature = "trace",
223 feature = "debug",
224 feature = "info",
225 feature = "warn",
226 feature = "error",
227)))]
228set_log_level!(println);
229
230pub trait IntoResult<T, E> {
234 fn into_result(self) -> Result<T, E>;
236}
237
238impl IntoResult<bool, bool> for bool {
239 fn into_result(self) -> Result<bool, bool> {
240 self.then_some(true).ok_or(false)
241 }
242}
243
244impl<T> IntoResult<T, Option<()>> for Option<T> {
245 fn into_result(self) -> Result<T, Option<()>> {
246 self.ok_or(None)
247 }
248}
249
250impl<T, E> IntoResult<T, E> for Result<T, E> {
251 fn into_result(self) -> Result<T, E> {
252 self
253 }
254}
255
256#[doc(hidden)]
258#[macro_export]
259macro_rules! __unwrap_or {
260 ($expr:expr, $else:expr) => {
261 match $crate::IntoResult::into_result($expr) {
262 ::core::result::Result::Ok(x) => x,
263 ::core::result::Result::Err(__err) => {
264 $crate::__log_bail!($expr, __err);
265 $else;
266 }
267 }
268 };
269}
270
271#[macro_export]
275macro_rules! or_return {
276 ($return:expr, $expr:expr $(,)?) => {
277 $crate::__unwrap_or!($expr, return $return)
278 };
279
280 ($expr:expr $(,)?) => {
281 $crate::__unwrap_or!($expr, return ::core::default::Default::default())
282 };
283}
284
285#[macro_export]
289macro_rules! or_continue {
290 ($label:tt, $expr:expr $(,)?) => {
291 $crate::__unwrap_or!($expr, continue $label)
292 };
293
294 ($expr:expr $(,)?) => {
295 $crate::__unwrap_or!($expr, continue)
296 };
297}
298
299#[macro_export]
303macro_rules! or_break {
304 ($label:tt, $expr:expr $(,)?) => {
305 $crate::__unwrap_or!($expr, break $label)
306 };
307
308 ($expr:expr $(,)?) => {
309 $crate::__unwrap_or!($expr, break)
310 };
311}
312
313#[doc(hidden)]
315#[macro_export]
316macro_rules! __unwrap_or_quiet {
317 ($expr:expr, $else:expr) => {
318 match $crate::IntoResult::into_result($expr) {
319 ::core::result::Result::Ok(x) => x,
320 _ => {
321 $else;
322 }
323 }
324 };
325}
326
327#[macro_export]
331macro_rules! or_return_quiet {
332 ($return:expr, $expr:expr $(,)?) => {
333 $crate::__unwrap_or_quiet!($expr, return $return)
334 };
335
336 ($expr:expr $(,)?) => {
337 $crate::__unwrap_or_quiet!($expr, return ::core::default::Default::default())
338 };
339}
340
341#[macro_export]
345macro_rules! or_continue_quiet {
346 ($label:tt, $expr:expr $(,)?) => {
347 $crate::__unwrap_or_quiet!($expr, continue $label)
348 };
349
350 ($expr:expr $(,)?) => {
351 $crate::__unwrap_or_quiet!($expr, continue)
352 };
353}
354
355#[macro_export]
359macro_rules! or_break_quiet {
360 ($label:tt, $expr:expr $(,)?) => {
361 $crate::__unwrap_or_quiet!($expr, break $label)
362 };
363
364 ($expr:expr $(,)?) => {
365 $crate::__unwrap_or_quiet!($expr, break)
366 };
367}
368
369#[doc(hidden)]
371#[macro_export]
372macro_rules! __unwrap_or_log_once {
373 ($expr:expr, $else:expr) => {
374 match $crate::IntoResult::into_result($expr) {
375 ::core::result::Result::Ok(x) => x,
376 ::core::result::Result::Err(__err) => {
377 static __SHOULD_LOG: ::core::sync::atomic::AtomicBool =
378 ::core::sync::atomic::AtomicBool::new(true);
379 if __SHOULD_LOG.swap(false, ::core::sync::atomic::Ordering::Relaxed) {
380 $crate::__log_bail!($expr, __err);
381 }
382 $else;
383 }
384 }
385 };
386}
387
388#[macro_export]
392macro_rules! or_return_log_once {
393 ($return:expr, $expr:expr $(,)?) => {
394 $crate::__unwrap_or_log_once!($expr, return $return)
395 };
396
397 ($expr:expr $(,)?) => {
398 $crate::__unwrap_or_log_once!($expr, return ::core::default::Default::default())
399 };
400}
401
402#[macro_export]
406macro_rules! or_continue_log_once {
407 ($label:tt, $expr:expr $(,)?) => {
408 $crate::__unwrap_or_log_once!($expr, continue $label)
409 };
410
411 ($expr:expr $(,)?) => {
412 $crate::__unwrap_or_log_once!($expr, continue)
413 };
414}
415
416#[macro_export]
420macro_rules! or_break_log_once {
421 ($label:tt, $expr:expr $(,)?) => {
422 $crate::__unwrap_or_log_once!($expr, break $label)
423 };
424
425 ($expr:expr $(,)?) => {
426 $crate::__unwrap_or_log_once!($expr, break)
427 };
428}
429
430#[cfg(test)]
431mod tests {
432 use std::fmt::Debug;
433
434 use super::IntoResult;
435
436 #[test]
437 fn r() {
438 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E>, inner: T) -> i32 {
439 assert_eq!(or_return!(outer), inner);
440 2
441 }
442
443 let success = 2;
445 assert_eq!(bail(true, true), success);
446 assert_eq!(bail(Some(-1), -1), success);
447 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
448
449 let failure = 0;
451 assert_eq!(bail(false, true), failure);
452 assert_eq!(bail(None, -1), failure);
453 assert_eq!(bail(Err(()), -1), failure);
454 }
455
456 #[test]
457 fn r_with_value() {
458 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E>, inner: T) -> i32 {
459 assert_eq!(or_return!(1, outer), inner);
460 2
461 }
462
463 let success = 2;
465 assert_eq!(bail(true, true), success);
466 assert_eq!(bail(Some(-1), -1), success);
467 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
468
469 let failure = 1;
471 assert_eq!(bail(false, true), failure);
472 assert_eq!(bail(None, -1), failure);
473 assert_eq!(bail(Err(()), -1), failure);
474 }
475
476 #[test]
477 fn rq() {
478 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E>, inner: T) -> i32 {
479 assert_eq!(or_return_quiet!(outer), inner);
480 2
481 }
482
483 let success = 2;
485 assert_eq!(bail(true, true), success);
486 assert_eq!(bail(Some(-1), -1), success);
487 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
488
489 let failure = 0;
491 assert_eq!(bail(false, true), failure);
492 assert_eq!(bail(None, -1), failure);
493 assert_eq!(bail(Err(()), -1), failure);
494 }
495
496 #[test]
497 fn rq_with_value() {
498 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E>, inner: T) -> i32 {
499 assert_eq!(or_return_quiet!(1, outer), inner);
500 2
501 }
502
503 let success = 2;
505 assert_eq!(bail(true, true), success);
506 assert_eq!(bail(Some(-1), -1), success);
507 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
508
509 let failure = 1;
511 assert_eq!(bail(false, true), failure);
512 assert_eq!(bail(None, -1), failure);
513 assert_eq!(bail(Err(()), -1), failure);
514 }
515
516 #[test]
517 fn ro() {
518 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E>, inner: T) -> i32 {
519 assert_eq!(or_return_log_once!(outer), inner);
520 2
521 }
522
523 let success = 2;
525 assert_eq!(bail(true, true), success);
526 assert_eq!(bail(Some(-1), -1), success);
527 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
528
529 let failure = 0;
531 assert_eq!(bail(false, true), failure);
532 assert_eq!(bail(None, -1), failure);
533 assert_eq!(bail(Err(()), -1), failure);
534 }
535
536 #[test]
537 fn ro_with_value() {
538 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E>, inner: T) -> i32 {
539 assert_eq!(or_return_log_once!(1, outer), inner);
540 2
541 }
542
543 let success = 2;
545 assert_eq!(bail(true, true), success);
546 assert_eq!(bail(Some(-1), -1), success);
547 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
548
549 let failure = 1;
551 assert_eq!(bail(false, true), failure);
552 assert_eq!(bail(None, -1), failure);
553 assert_eq!(bail(Err(()), -1), failure);
554 }
555
556 #[test]
557 fn c() {
558 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E> + Copy, inner: T) -> i32 {
559 let mut val = 0;
560 '_a: for _ in 0..2 {
561 val += 1;
562 for _ in 0..2 {
563 val += 1;
564 assert_eq!(or_continue!(outer), inner);
565 val += 1;
566 }
567 val += 1;
568 }
569 val
570 }
571
572 let success = 12;
574 assert_eq!(bail(true, true), success);
575 assert_eq!(bail(Some(-1), -1), success);
576 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
577
578 let failure = 8;
580 assert_eq!(bail(false, true), failure);
581 assert_eq!(bail(None, -1), failure);
582 assert_eq!(bail(Err(()), -1), failure);
583 }
584
585 #[test]
586 fn c_with_label() {
587 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E> + Copy, inner: T) -> i32 {
588 let mut val = 0;
589 '_a: for _ in 0..2 {
590 val += 1;
591 for _ in 0..2 {
592 val += 1;
593 assert_eq!(or_continue!('_a, outer), inner);
594 val += 1;
595 }
596 val += 1;
597 }
598 val
599 }
600
601 let success = 12;
603 assert_eq!(bail(true, true), success);
604 assert_eq!(bail(Some(-1), -1), success);
605 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
606
607 let failure = 4;
609 assert_eq!(bail(false, true), failure);
610 assert_eq!(bail(None, -1), failure);
611 assert_eq!(bail(Err(()), -1), failure);
612 }
613
614 #[test]
615 fn cq() {
616 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E> + Copy, inner: T) -> i32 {
617 let mut val = 0;
618 '_a: for _ in 0..2 {
619 val += 1;
620 for _ in 0..2 {
621 val += 1;
622 assert_eq!(or_continue_quiet!(outer), inner);
623 val += 1;
624 }
625 val += 1;
626 }
627 val
628 }
629
630 let success = 12;
632 assert_eq!(bail(true, true), success);
633 assert_eq!(bail(Some(-1), -1), success);
634 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
635
636 let failure = 8;
638 assert_eq!(bail(false, true), failure);
639 assert_eq!(bail(None, -1), failure);
640 assert_eq!(bail(Err(()), -1), failure);
641 }
642
643 #[test]
644 fn cq_with_label() {
645 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E> + Copy, inner: T) -> i32 {
646 let mut val = 0;
647 '_a: for _ in 0..2 {
648 val += 1;
649 for _ in 0..2 {
650 val += 1;
651 assert_eq!(or_continue_quiet!('_a, outer), inner);
652 val += 1;
653 }
654 val += 1;
655 }
656 val
657 }
658
659 let success = 12;
661 assert_eq!(bail(true, true), success);
662 assert_eq!(bail(Some(-1), -1), success);
663 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
664
665 let failure = 4;
667 assert_eq!(bail(false, true), failure);
668 assert_eq!(bail(None, -1), failure);
669 assert_eq!(bail(Err(()), -1), failure);
670 }
671
672 #[test]
673 fn co() {
674 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E> + Copy, inner: T) -> i32 {
675 let mut val = 0;
676 '_a: for _ in 0..2 {
677 val += 1;
678 for _ in 0..2 {
679 val += 1;
680 assert_eq!(or_continue_log_once!(outer), inner);
681 val += 1;
682 }
683 val += 1;
684 }
685 val
686 }
687
688 let success = 12;
690 assert_eq!(bail(true, true), success);
691 assert_eq!(bail(Some(-1), -1), success);
692 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
693
694 let failure = 8;
696 assert_eq!(bail(false, true), failure);
697 assert_eq!(bail(None, -1), failure);
698 assert_eq!(bail(Err(()), -1), failure);
699 }
700
701 #[test]
702 fn co_with_label() {
703 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E> + Copy, inner: T) -> i32 {
704 let mut val = 0;
705 '_a: for _ in 0..2 {
706 val += 1;
707 for _ in 0..2 {
708 val += 1;
709 assert_eq!(or_continue_log_once!('_a, outer), inner);
710 val += 1;
711 }
712 val += 1;
713 }
714 val
715 }
716
717 let success = 12;
719 assert_eq!(bail(true, true), success);
720 assert_eq!(bail(Some(-1), -1), success);
721 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
722
723 let failure = 4;
725 assert_eq!(bail(false, true), failure);
726 assert_eq!(bail(None, -1), failure);
727 assert_eq!(bail(Err(()), -1), failure);
728 }
729 #[test]
730 fn b() {
731 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E> + Copy, inner: T) -> i32 {
732 let mut val = 0;
733 '_a: for _ in 0..2 {
734 val += 1;
735 for _ in 0..2 {
736 val += 1;
737 assert_eq!(or_break!(outer), inner);
738 val += 1;
739 }
740 val += 1;
741 }
742 val
743 }
744
745 let success = 12;
747 assert_eq!(bail(true, true), success);
748 assert_eq!(bail(Some(-1), -1), success);
749 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
750
751 let failure = 6;
753 assert_eq!(bail(false, true), failure);
754 assert_eq!(bail(None, -1), failure);
755 assert_eq!(bail(Err(()), -1), failure);
756 }
757
758 #[test]
759 fn b_with_label() {
760 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E> + Copy, inner: T) -> i32 {
761 let mut val = 0;
762 '_a: for _ in 0..2 {
763 val += 1;
764 for _ in 0..2 {
765 val += 1;
766 assert_eq!(or_break!('_a, outer), inner);
767 val += 1;
768 }
769 val += 1;
770 }
771 val
772 }
773
774 let success = 12;
776 assert_eq!(bail(true, true), success);
777 assert_eq!(bail(Some(-1), -1), success);
778 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
779
780 let failure = 2;
782 assert_eq!(bail(false, true), failure);
783 assert_eq!(bail(None, -1), failure);
784 assert_eq!(bail(Err(()), -1), failure);
785 }
786
787 #[test]
788 fn bq() {
789 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E> + Copy, inner: T) -> i32 {
790 let mut val = 0;
791 '_a: for _ in 0..2 {
792 val += 1;
793 for _ in 0..2 {
794 val += 1;
795 assert_eq!(or_break_quiet!(outer), inner);
796 val += 1;
797 }
798 val += 1;
799 }
800 val
801 }
802
803 let success = 12;
805 assert_eq!(bail(true, true), success);
806 assert_eq!(bail(Some(-1), -1), success);
807 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
808
809 let failure = 6;
811 assert_eq!(bail(false, true), failure);
812 assert_eq!(bail(None, -1), failure);
813 assert_eq!(bail(Err(()), -1), failure);
814 }
815
816 #[test]
817 fn bq_with_label() {
818 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E> + Copy, inner: T) -> i32 {
819 let mut val = 0;
820 '_a: for _ in 0..2 {
821 val += 1;
822 for _ in 0..2 {
823 val += 1;
824 assert_eq!(or_break_quiet!('_a, outer), inner);
825 val += 1;
826 }
827 val += 1;
828 }
829 val
830 }
831
832 let success = 12;
834 assert_eq!(bail(true, true), success);
835 assert_eq!(bail(Some(-1), -1), success);
836 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
837
838 let failure = 2;
840 assert_eq!(bail(false, true), failure);
841 assert_eq!(bail(None, -1), failure);
842 assert_eq!(bail(Err(()), -1), failure);
843 }
844
845 #[test]
846 fn bo() {
847 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E> + Copy, inner: T) -> i32 {
848 let mut val = 0;
849 '_a: for _ in 0..2 {
850 val += 1;
851 for _ in 0..2 {
852 val += 1;
853 assert_eq!(or_break_log_once!(outer), inner);
854 val += 1;
855 }
856 val += 1;
857 }
858 val
859 }
860
861 let success = 12;
863 assert_eq!(bail(true, true), success);
864 assert_eq!(bail(Some(-1), -1), success);
865 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
866
867 let failure = 6;
869 assert_eq!(bail(false, true), failure);
870 assert_eq!(bail(None, -1), failure);
871 assert_eq!(bail(Err(()), -1), failure);
872 }
873
874 #[test]
875 fn bo_with_label() {
876 fn bail<T: Eq + Debug, E: Debug>(outer: impl IntoResult<T, E> + Copy, inner: T) -> i32 {
877 let mut val = 0;
878 '_a: for _ in 0..2 {
879 val += 1;
880 for _ in 0..2 {
881 val += 1;
882 assert_eq!(or_break_log_once!('_a, outer), inner);
883 val += 1;
884 }
885 val += 1;
886 }
887 val
888 }
889
890 let success = 12;
892 assert_eq!(bail(true, true), success);
893 assert_eq!(bail(Some(-1), -1), success);
894 assert_eq!(bail(Ok::<_, ()>(-1), -1), success);
895
896 let failure = 2;
898 assert_eq!(bail(false, true), failure);
899 assert_eq!(bail(None, -1), failure);
900 assert_eq!(bail(Err(()), -1), failure);
901 }
902}