1use std::{
2 collections::hash_map::DefaultHasher,
3 future::Future,
4 hash::{Hash, Hasher},
5};
6
7pub fn state() -> u64 {
9 let mut hash = DefaultHasher::new();
10
11 if let Ok(ifaces) = ifaces::Interface::get_all() {
12 for iface in ifaces {
13 iface.addr.hash(&mut hash);
14 }
15 }
16
17 hash.finish()
18}
19
20pub async fn watch_change() {
22 let current = state();
23
24 loop {
25 tokio::time::sleep(std::time::Duration::from_secs(1)).await;
26 let new = state();
27 if new != current {
28 break;
29 }
30 }
31}
32
33pub async fn reconnect_on_change<Func, Fut, Res, Retry, Cont>(func: Func, cont: Retry) -> Res
35where
36 Func: Fn() -> Fut,
37 Fut: Future<Output = Res>,
38 Retry: Fn() -> Cont,
39 Cont: Future<Output = Option<Res>>,
40{
41 loop {
42 let changed = watch_change();
43 let future = func();
44
45 futures::pin_mut!(future);
46 futures::pin_mut!(changed);
47
48 use futures::future::Either;
49
50 match futures::future::select(future, changed).await {
51 Either::Left((result, _)) => break result,
52 Either::Right(_) => {
53 if let Some(result) = cont().await {
54 break result;
55 }
56 }
57 }
58 }
59}