1#![doc(html_logo_url = "https://avatars.githubusercontent.com/u/104781277?s=96&v=4")]
2#![doc = include_str!("../README.md")]
3#![deny(
8 clippy::expect_used,
9 clippy::explicit_deref_methods,
10 clippy::option_if_let_else,
11 clippy::await_holding_lock,
12 clippy::cloned_instead_of_copied,
13 clippy::explicit_into_iter_loop,
14 clippy::flat_map_option,
15 clippy::fn_params_excessive_bools,
16 clippy::implicit_clone,
17 clippy::inefficient_to_string,
18 clippy::large_types_passed_by_value,
19 clippy::manual_ok_or,
20 clippy::map_flatten,
21 clippy::map_unwrap_or,
22 clippy::must_use_candidate,
23 clippy::needless_for_each,
24 clippy::needless_pass_by_value,
25 clippy::option_option,
26 clippy::redundant_else,
27 clippy::semicolon_if_nothing_returned,
28 clippy::too_many_lines,
29 clippy::trivially_copy_pass_by_ref,
30 clippy::unnested_or_patterns,
31 clippy::future_not_send,
32 clippy::useless_let_if_seq,
33 clippy::str_to_string,
34 clippy::inherent_to_string,
35 clippy::let_and_return,
36 clippy::string_to_string,
37 clippy::try_err,
38 clippy::if_then_some_else_none,
39 bad_style,
40 clashing_extern_declarations,
41 const_err,
42 dead_code,
43 deprecated,
44 explicit_outlives_requirements,
45 improper_ctypes,
46 invalid_value,
47 missing_copy_implementations,
48 missing_debug_implementations,
49 mutable_transmutes,
50 no_mangle_generic_items,
51 non_shorthand_field_patterns,
52 overflowing_literals,
53 path_statements,
54 patterns_in_fns_without_body,
55 private_in_public,
56 trivial_bounds,
57 trivial_casts,
58 trivial_numeric_casts,
59 type_alias_bounds,
60 unconditional_recursion,
61 unreachable_pub,
62 unsafe_code,
63 unstable_features,
64 unused,
65 unused_allocation,
66 unused_comparisons,
67 unused_import_braces,
68 unused_parens,
69 unused_qualifications,
70 while_true,
71 missing_docs
72)]
73#![allow(unused_attributes)]
74#![allow()]
77
78#[macro_export]
79macro_rules! ensure {
82 ($cond:expr, $msg:literal $(,)?) => {
83 if !$cond {
84 return Err($msg.into());
85 }
86 };
87 ($cond:expr, $err:expr $(,)?) => {
88 if !$cond {
89 return Err($err);
90 }
91 };
92 ($cond:expr, $fmt:expr, $($arg:tt)*) => {
93 if !$cond {
94 return Err(format!($fmt, $($arg)*));
95 }
96 };
97}
98
99#[macro_export]
100macro_rules! map_wrapper {
103 ($cond:ident, $t:ty, $($arg:tt)*) => {
104 impl $cond {
105
106 #[must_use]
107 fn get<K: AsRef<str>>(&self, field: K) -> Option<&$t> {
109 self.0.get(field.as_ref())
110 }
111
112 #[must_use]
113 fn contains_key<K: AsRef<str>>(&self, field: K) -> bool {
115 self.0.contains_key(field.as_ref())
116 }
117
118 fn insert<K: AsRef<str>>(&mut self, field: K, value: $t) {
120 self.0.insert(field.as_ref().to_owned(), value);
121 }
122
123 $($arg)*
124 }
125 };
126}
127
128#[macro_export]
129macro_rules! kv_impl {
132 ($t:ty) => {
133 kv_impl!{$t, pub(self)}
134 };
135 ($t:ty, $v:vis) => {
136 #[must_use]
137 #[allow(unused, unreachable_pub)]
138 $v fn get<K: AsRef<str>>(&self, field: K) -> Option<&$t> {
140 self.0.get(field.as_ref())
141 }
142
143 #[must_use]
144 #[allow(unused, unreachable_pub)]
145 $v fn get_mut<K: AsRef<str>>(&mut self, field: K) -> Option<&mut $t> {
147 self.0.get_mut(field.as_ref())
148 }
149
150 #[must_use]
151 #[allow(unused, unreachable_pub)]
152 $v fn contains_key<K: AsRef<str>>(&self, field: K) -> bool {
154 self.0.contains_key(field.as_ref())
155 }
156
157 #[allow(unused, unreachable_pub)]
159 $v fn insert<K: AsRef<str>>(&mut self, field: K, value: $t) {
160 self.0.insert(field.as_ref().to_owned(), value);
161 }
162
163 #[must_use]
164 #[allow(unused, unreachable_pub)]
165 $v fn remove(&mut self, key:&str) -> Option<$t> {
167 self.0.remove(key)
168 }
169
170 #[must_use]
171 #[allow(unused, unreachable_pub)]
172 $v fn names(&self) -> Vec<String> {
174 self.0.keys().cloned().collect()
175 }
176
177 #[must_use]
178 #[allow(unused, unreachable_pub)]
179 $v fn is_empty(&self) -> bool {
181 self.0.is_empty()
182 }
183
184 #[must_use]
186 #[allow(unused, unreachable_pub)]
187 $v fn into_inner(self) -> std::collections::HashMap<String, $t> {
188 self.0
189 }
190
191 #[must_use]
193 #[allow(unused, unreachable_pub)]
194 $v fn inner(&self) -> &std::collections::HashMap<String, $t> {
195 &self.0
196 }
197
198 #[must_use]
199 #[allow(unused, unreachable_pub)]
200 $v fn len(&self) -> usize {
202 self.0.len()
203 }
204 };
205}
206
207#[cfg(test)]
208mod test {
209 use anyhow::Result;
210
211 #[test]
212 fn map_wrapper() -> Result<()> {
213 #[derive(Default)]
214 struct MyMap(std::collections::HashMap<String, u32>);
215 impl MyMap {
216 fn custom_len(&self) -> usize {
217 self.0.len() * 10
218 }
219 kv_impl! {u32}
220 }
221
222 let mut map = MyMap::default();
223 map.insert("hey", 0);
224
225 assert_eq!(map.custom_len(), 10);
226 Ok(())
227 }
228}