1#![feature(decl_macro)]
14#![feature(try_trait_v2)]
15#![warn(missing_docs)]
16
17pub mod macros;
18
19#[doc(hidden)]
20pub use log as __log;
21
22use log::{error, info, warn};
23use std::{
24 fmt::{Debug, Display},
25 ops::{ControlFlow, Try},
26};
27
28pub trait TryLog<T, R: Debug> {
30 fn inspect_or_log(self, msg: &str) -> Self;
32
33 fn inspect_or_log_with<M: Display>(self, f: impl FnOnce() -> M) -> Self;
37
38 fn unwrap_or_default_log(self, msg: &str) -> T
41 where
42 T: Default;
43
44 fn unwrap_or_default_log_with<M: Display>(self, f: impl FnOnce() -> M) -> T
49 where
50 T: Default;
51
52 fn unwrap_or_log(self, msg: &str) -> T;
55
56 fn unwrap_or_log_with<M: Display>(self, f: impl FnOnce() -> M) -> T;
61}
62
63#[inline(always)]
64fn inspect_or_and<T: Try>(t: T, f: impl FnOnce(&T::Residual)) -> T {
65 match t.branch() {
66 ControlFlow::Continue(v) => T::from_output(v),
67 ControlFlow::Break(e) => {
68 f(&e);
69 T::from_residual(e)
70 }
71 }
72}
73
74#[inline(always)]
75fn unwrap_or_default_and<T: Try>(t: T, f: impl FnOnce(&T::Residual)) -> T::Output
76where
77 T::Output: Default,
78{
79 match t.branch() {
80 ControlFlow::Continue(v) => v,
81 ControlFlow::Break(e) => {
82 f(&e);
83 Default::default()
84 }
85 }
86}
87
88#[inline(always)]
89fn unwrap_or_and<T: Try>(t: T, f: impl FnOnce(&T::Residual) -> String) -> T::Output {
90 match t.branch() {
91 ControlFlow::Continue(v) => v,
92 ControlFlow::Break(e) => {
93 let msg = f(&e);
94 error!("{}", msg);
95 panic!("{}", msg)
96 }
97 }
98}
99
100impl<T, R: Debug, Tr: Try<Output = T, Residual = R>> TryLog<T, R> for Tr {
101 #[inline(always)]
102 fn inspect_or_log(self, msg: &str) -> Self {
103 inspect_or_and(self, |e| info!("{msg}: {e:?}"))
104 }
105
106 #[inline(always)]
107 fn inspect_or_log_with<M: Display>(self, f: impl FnOnce() -> M) -> Self {
108 inspect_or_and(self, |e| info!("{}: {e:?}", f()))
109 }
110
111 #[inline(always)]
112 fn unwrap_or_default_log(self, msg: &str) -> T
113 where
114 T: Default,
115 {
116 unwrap_or_default_and(self, |e| warn!("{msg}: {e:?}"))
117 }
118
119 #[inline(always)]
120 fn unwrap_or_default_log_with<M: Display>(self, f: impl FnOnce() -> M) -> T
121 where
122 T: Default,
123 {
124 unwrap_or_default_and(self, |e| warn!("{}: {e:?}", f()))
125 }
126
127 #[inline(always)]
128 fn unwrap_or_log(self, msg: &str) -> T {
129 unwrap_or_and(self, |e| format!("{msg}: {e:?}"))
130 }
131
132 #[inline(always)]
133 fn unwrap_or_log_with<M: Display>(self, f: impl FnOnce() -> M) -> T {
134 unwrap_or_and(self, |e| format!("{}: {e:?}", f()))
135 }
136}