libimagutil/log_result.rs
1//
2// imag - the personal information management suite for the commandline
3// Copyright (C) 2015-2020 Matthias Beyer <mail@beyermatthias.de> and contributors
4//
5// This library is free software; you can redistribute it and/or
6// modify it under the terms of the GNU Lesser General Public
7// License as published by the Free Software Foundation; version
8// 2.1 of the License.
9//
10// This library is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13// Lesser General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public
16// License along with this library; if not, write to the Free Software
17// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18//
19
20/// This macro is used to generate extensions for the `Result<T, U>` type which only have
21/// sideeffects.
22///
23/// This macro is then used to generate debug/info/log/warning/etc extensions.
24///
25/// It is exported, so other crates can use it to generate more specific extensions for
26/// `Result<T, U>` types
27///
28/// # Parameters
29///
30/// The documentation for the parameters of the macro follow.
31///
32/// ## `$name`
33///
34/// name of the trait to generate
35///
36/// ## `$map_name`
37///
38/// Name of the function which is generated to call the closure with.
39///
40/// This function gets `&T` from `Result<T, E>` and can now build the argument for
41/// `$closure`. So, this function can, for example, `|e| format!("Look here: {:?}", e)`, the
42/// result gets fed to `$closure`.
43///
44/// ## `$map_str_name`
45///
46/// Name of the function which is generated to call the closure with.
47///
48/// This function gets simply a `&str` which gets fed to the `$closure` later.
49/// So it can be used to `foo().$map_str_name("Something happened")`
50///
51/// ## `$map_err_name`
52///
53/// Same as `$map_name`, but gets `&E` from `Resul<T, E>`.
54///
55/// ## `$map_err_str_name`
56///
57/// Same as `$map_str_name`, but is called for error cases in `Result<T, E>` (though no
58/// argument is passed.
59///
60/// ## `$closure`
61///
62/// The closure which should be called when mapping.
63///
64/// This closure can now do things, but the return value of the closure is discarded.
65/// So, this closure can be used for its sideeffects (logging for example) only.
66///
67/// An example would be: `|element| debug!("Element: {:?}", element)`.
68///
69#[macro_export]
70macro_rules! generate_result_logging_extension {
71 {
72 $name: ident,
73 $map_name: ident,
74 $map_str_name: ident,
75 $map_err_name: ident,
76 $map_err_str_name: ident,
77 $closure: expr
78 } => {
79 pub trait $name<T, E> : Sized {
80
81 fn $map_name<F: FnOnce(&T) -> String>(self, f: F) -> Self;
82
83 fn $map_str_name(self, s: &str) -> Self {
84 self.$map_name(|_| format!("{}", s))
85 }
86
87 fn $map_err_name<F: FnOnce(&E) -> String>(self, f: F) -> Self;
88
89 fn $map_err_str_name(self, s: &str) -> Self {
90 self.$map_err_name(|_| format!("{}", s))
91 }
92
93 }
94
95 impl<T, E> $name<T, E> for Result<T, E> {
96
97 fn $map_name<F: FnOnce(&T) -> String>(self, f: F) -> Self {
98 self.map(|x| { $closure(f(&x)); x })
99 }
100
101 fn $map_err_name<F: FnOnce(&E) -> String>(self, f: F) -> Self {
102 self.map_err(|e| { $closure(f(&e)); e })
103 }
104
105 }
106
107 }
108}