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}