slog_unwrap/slog.rs
1use std::fmt;
2
3//
4// Extension trait for Result types.
5//
6
7/// Extension trait for Result types.
8pub trait ResultExt<T, E> {
9 /// Unwraps a result, yielding the content of an [`Ok`].
10 ///
11 /// # Panics
12 ///
13 /// Panics if the value is an [`Err`], logging a message provided by the
14 /// [`Err`]'s value to a [`slog::Logger`] at a [`Critical`] level.
15 ///
16 /// [`Critical`]: /slog/2/slog/enum.Level.html#variant.Critical
17 fn unwrap_or_log(self, log: &slog::Logger) -> T
18 where
19 E: fmt::Debug;
20
21 /// Unwraps a result, yielding the content of an [`Ok`].
22 ///
23 /// # Panics
24 ///
25 /// Panics if the value is an [`Err`], logging the passed message and the
26 /// content of the [`Err`] to a [`slog::Logger`] at a [`Critical`] level.
27 ///
28 /// [`Critical`]: /slog/2/slog/enum.Level.html#variant.Critical
29 fn expect_or_log(self, log: &slog::Logger, msg: &str) -> T
30 where
31 E: fmt::Debug;
32
33 /// Unwraps a result, yielding the content of an [`Err`].
34 ///
35 /// # Panics
36 ///
37 /// Panics if the value is an [`Ok`], logging a message provided by the
38 /// [`Ok`]'s value to a [`slog::Logger`] at a [`Critical`] level.
39 ///
40 /// [`Critical`]: /slog/2/slog/enum.Level.html#variant.Critical
41 fn unwrap_err_or_log(self, log: &slog::Logger) -> E
42 where
43 T: fmt::Debug;
44
45 /// Unwraps a result, yielding the content of an [`Err`].
46 ///
47 /// # Panics
48 ///
49 /// Panics if the value is an [`Ok`], logging the passed message and the
50 /// content of the [`Ok`] to a [`slog::Logger`] at a [`Critical`] level.
51 ///
52 /// [`Critical`]: /slog/2/slog/enum.Level.html#variant.Critical
53 fn expect_err_or_log(self, log: &slog::Logger, msg: &str) -> E
54 where
55 T: fmt::Debug;
56}
57
58impl<T, E> ResultExt<T, E> for Result<T, E> {
59 #[inline]
60 #[track_caller]
61 fn unwrap_or_log(self, log: &slog::Logger) -> T
62 where
63 E: fmt::Debug,
64 {
65 match self {
66 Ok(t) => t,
67 Err(e) => failed_with(
68 log,
69 "called `Result::unwrap_or_log()` on an `Err` value",
70 &e,
71 ),
72 }
73 }
74
75 #[inline]
76 #[track_caller]
77 fn expect_or_log(self, log: &slog::Logger, msg: &str) -> T
78 where
79 E: fmt::Debug,
80 {
81 match self {
82 Ok(t) => t,
83 Err(e) => failed_with(log, msg, &e),
84 }
85 }
86
87 #[inline]
88 #[track_caller]
89 fn unwrap_err_or_log(self, log: &slog::Logger) -> E
90 where
91 T: fmt::Debug,
92 {
93 match self {
94 Ok(t) => failed_with(
95 log,
96 "called `Result::unwrap_err_or_log()` on an `Ok` value",
97 &t,
98 ),
99 Err(e) => e,
100 }
101 }
102
103 #[inline]
104 #[track_caller]
105 fn expect_err_or_log(self, log: &slog::Logger, msg: &str) -> E
106 where
107 T: fmt::Debug,
108 {
109 match self {
110 Ok(t) => failed_with(log, msg, &t),
111 Err(e) => e,
112 }
113 }
114}
115
116//
117// Extension trait for Option types.
118//
119
120/// Extension trait for Option types.
121pub trait OptionExt<T> {
122 /// Moves the value `v` out of the `Option<T>` if it is [`Some(v)`].
123 ///
124 /// In general, because this function may panic, its use is discouraged.
125 /// Instead, prefer to use pattern matching and handle the [`None`]
126 /// case explicitly.
127 ///
128 /// # Panics
129 ///
130 /// Panics if the self value equals [`None`], logging an error message to a
131 /// [`slog::Logger`] at a [`Critical`] level.
132 fn unwrap_or_log(self, log: &slog::Logger) -> T;
133
134 /// Unwraps an option, yielding the content of a [`Some`].
135 ///
136 /// # Panics
137 ///
138 /// Panics if the value is a [`None`], logging the passed message to a
139 /// [`slog::Logger`] at a [`Critical`] level.
140 fn expect_or_log(self, log: &slog::Logger, msg: &str) -> T;
141
142 /// Unwraps an option, expecting [`None`] and returning nothing.
143 ///
144 /// # Panics
145 ///
146 /// Panics if the value is a [`Some`], logging a message derived from the
147 /// [`Some`]'s value to a [`slog::Logger`] at a [`Critical`] level.
148 fn unwrap_none_or_log(self, log: &slog::Logger)
149 where
150 T: fmt::Debug;
151
152 /// Unwraps an option, expecting [`None`] and returning nothing.
153 ///
154 /// # Panics
155 ///
156 /// Panics if the value is a [`Some`], logging the passed message and the
157 /// content of the [`Some`] to a [`slog::Logger`] at a [`Critical`] level.
158 fn expect_none_or_log(self, log: &slog::Logger, msg: &str)
159 where
160 T: fmt::Debug;
161}
162
163impl<T> OptionExt<T> for Option<T> {
164 fn unwrap_or_log(self, log: &slog::Logger) -> T {
165 match self {
166 Some(val) => val,
167 None => failed(log, "called `Option::unwrap_or_log()` on a `None` value"),
168 }
169 }
170
171 #[inline]
172 #[track_caller]
173 fn expect_or_log(self, log: &slog::Logger, msg: &str) -> T {
174 match self {
175 Some(val) => val,
176 None => failed(log, msg),
177 }
178 }
179
180 #[inline]
181 #[track_caller]
182 fn unwrap_none_or_log(self, log: &slog::Logger)
183 where
184 T: fmt::Debug,
185 {
186 if let Some(val) = self {
187 failed_with(
188 log,
189 "called `Option::unwrap_none_or_log()` on a `Some` value",
190 &val,
191 );
192 }
193 }
194
195 #[inline]
196 #[track_caller]
197 fn expect_none_or_log(self, log: &slog::Logger, msg: &str)
198 where
199 T: fmt::Debug,
200 {
201 if let Some(val) = self {
202 failed_with(log, msg, &val);
203 }
204 }
205}
206
207//
208// Helper functions.
209//
210
211#[inline(never)]
212#[cold]
213#[track_caller]
214fn failed(log: &slog::Logger, msg: &str) -> ! {
215 slog::crit!(log, "{}", msg);
216
217 #[cfg(feature = "panic-quiet")]
218 panic!();
219 #[cfg(not(feature = "panic-quiet"))]
220 panic!("{}", msg)
221}
222
223#[inline(never)]
224#[cold]
225#[track_caller]
226fn failed_with(log: &slog::Logger, msg: &str, value: &dyn fmt::Debug) -> ! {
227 slog::crit!(log, "{}: {:?}", msg, &value);
228
229 #[cfg(feature = "panic-quiet")]
230 panic!();
231 #[cfg(not(feature = "panic-quiet"))]
232 panic!("{}: {:?}", msg, &value);
233}