1use std::{
2 borrow::Borrow,
3 collections::{
4 btree_map,
5 hash_map::{Entry, OccupiedEntry},
6 BTreeMap, HashMap,
7 },
8 convert::TryInto,
9 fmt::Display,
10 hash::Hash,
11 ops::Add,
12 time::Duration,
13};
14
15pub fn hashmap_get_mut<'m, K: Eq + Hash, P: Eq + Hash + ?Sized, V>(
20 m: &'m mut HashMap<K, V>,
21 k: &P,
22) -> Result<&'m mut V, &'m mut HashMap<K, V>>
23where
24 K: Borrow<P>,
25{
26 let pm: *mut _ = m;
27 if let Some(v) = unsafe { &mut *pm }.get_mut(k) {
31 Ok(v)
32 } else {
33 Err(unsafe { &mut *pm })
34 }
35}
36
37pub fn btreemap_get_mut<'m, K: Ord, P: Ord + ?Sized, V>(
39 m: &'m mut BTreeMap<K, V>,
40 k: &P,
41) -> Result<&'m mut V, &'m mut BTreeMap<K, V>>
42where
43 K: Borrow<P>,
44{
45 let pm: *mut _ = m;
46 if let Some(v) = unsafe { &mut *pm }.get_mut(k) {
50 Ok(v)
51 } else {
52 Err(unsafe { &mut *pm })
53 }
54}
55
56pub fn hashmap_try_insert<'m, K: Eq + Hash, V>(
62 m: &'m mut HashMap<K, V>,
63 key: K,
64 value: V,
65) -> Result<&'m mut V, OccupiedEntry<'m, K, V>> {
66 match m.entry(key) {
67 Entry::Occupied(entry) => Err(entry),
68 Entry::Vacant(entry) => Ok(entry.insert(value)),
69 }
70}
71
72pub fn btreemap_try_insert<'m, K: Ord, V>(
77 m: &'m mut BTreeMap<K, V>,
78 key: K,
79 value: V,
80) -> Result<&'m mut V, btree_map::OccupiedEntry<'m, K, V>> {
81 match m.entry(key) {
82 btree_map::Entry::Occupied(entry) => Err(entry),
83 btree_map::Entry::Vacant(entry) => Ok(entry.insert(value)),
84 }
85}
86
87pub fn hashmap_get_mut_vivify<'m, K: Eq + Hash + Clone, V>(
88 m: &'m mut HashMap<K, V>,
89 k: &K,
90 create: impl FnOnce() -> V,
91) -> &'m mut V {
92 match hashmap_get_mut(m, k) {
93 Ok(val) => val,
94 Err(m) => {
95 m.insert(k.clone(), create());
96 m.get_mut(k).expect("just inserted")
97 }
98 }
99}
100
101pub fn hashmap_add<K: Hash + Eq, V: Add<Output = V> + Copy>(
104 m: &mut HashMap<K, V>,
105 k: K,
106 v: V,
107) {
108 match hashmap_get_mut(m, &k) {
109 Ok(oldv) => {
110 *oldv = oldv.add(v);
112 }
113 Err(m) => {
114 m.insert(k, v);
115 }
116 }
117}
118
119pub fn duration_mul_div(
121 orig: Duration,
122 multiplier: u64,
123 divider: u64,
124) -> Option<Duration> {
125 let nanos: u64 = orig
126 .as_nanos()
127 .checked_mul(multiplier as u128)?
128 .checked_div(divider as u128)?
129 .try_into()
130 .ok()?;
131 Some(Duration::from_nanos(nanos))
132}
133
134pub fn first<T>(items: &[T]) -> &T {
135 &items[0]
136}
137
138pub fn rest<T>(items: &[T]) -> &[T] {
139 &items[1..]
140}
141
142pub fn debug_stringlikes<S: Display>(v: &[S]) -> Vec<String> {
143 v.iter().map(|s| s.to_string()).collect()
144}
145
146#[macro_export]
150macro_rules! loop_try {
151 ( $($body_parts:tt)* ) => {{
152 let default_error_sleep_duration = Duration::from_millis(500);
153 let mut error_sleep_duration = default_error_sleep_duration;
154 loop {
155 match (|| -> Result<()> { $($body_parts)* })() {
156 Ok(()) => {
157 error_sleep_duration = default_error_sleep_duration;
158 }
159 Err(e) => {
160 eprintln!("loop_try: got error {e:#}, sleeping for \
161 {error_sleep_duration:?}");
162 thread::sleep(error_sleep_duration);
163 error_sleep_duration =
164 $crate::util::duration_mul_div(error_sleep_duration,
165 1200,
166 1000)
167 .unwrap_or(default_error_sleep_duration);
168 }
169 }
170 }
171 }}
172}
173
174#[macro_export]
177macro_rules! tryoption {
178 ($e:expr) => {{
179 let res = $e;
180 if let Some(val) = res {
181 val
182 } else {
183 return Ok(None);
184 }
185 }};
186}
187
188#[macro_export]
189macro_rules! try_do {
190 ( $($b:tt)* ) => ( (|| { $($b)* })() )
191}
192
193#[macro_export]
194macro_rules! try_result {
195 ( $($b:tt)* ) => ( (|| -> Result<_> { $($b)* })() )
196}
197
198#[macro_export]
199macro_rules! try_option {
200 ( $($b:tt)* ) => ( (|| -> Option<_> { $($b)* })() )
201}
202
203#[macro_export]
205macro_rules! gen_try_result {
206 ( $e:expr, $co:expr ) => {
207 match $e {
208 Ok(v) => v,
209 Err(e) => {
210 $co.yield_(Err(e)).await;
211 return;
212 }
213 }
214 };
215}