1#[cfg(feature = "test-support")]
2pub mod test;
3
4use futures::Future;
5use std::{
6 cmp::Ordering,
7 pin::Pin,
8 task::{Context, Poll},
9};
10
11pub fn post_inc(value: &mut usize) -> usize {
12 let prev = *value;
13 *value += 1;
14 prev
15}
16
17/// Extend a sorted vector with a sorted sequence of items, maintaining the vector's sort order and
18/// enforcing a maximum length. Sort the items according to the given callback. Before calling this,
19/// both `vec` and `new_items` should already be sorted according to the `cmp` comparator.
20pub fn extend_sorted<T, I, F>(vec: &mut Vec<T>, new_items: I, limit: usize, mut cmp: F)
21where
22 I: IntoIterator<Item = T>,
23 F: FnMut(&T, &T) -> Ordering,
24{
25 let mut start_index = 0;
26 for new_item in new_items {
27 if let Err(i) = vec[start_index..].binary_search_by(|m| cmp(m, &new_item)) {
28 let index = start_index + i;
29 if vec.len() < limit {
30 vec.insert(index, new_item);
31 } else if index < vec.len() {
32 vec.pop();
33 vec.insert(index, new_item);
34 }
35 start_index = index;
36 }
37 }
38}
39pub trait ResultExt {
40 type Ok;
41
42 fn log_err(self) -> Option<Self::Ok>;
43 fn warn_on_err(self) -> Option<Self::Ok>;
44}
45
46impl<T, E> ResultExt for Result<T, E>
47where
48 E: std::fmt::Debug,
49{
50 type Ok = T;
51
52 fn log_err(self) -> Option<T> {
53 match self {
54 Ok(value) => Some(value),
55 Err(error) => {
56 log::error!("{:?}", error);
57 None
58 }
59 }
60 }
61
62 fn warn_on_err(self) -> Option<T> {
63 match self {
64 Ok(value) => Some(value),
65 Err(error) => {
66 log::warn!("{:?}", error);
67 None
68 }
69 }
70 }
71}
72
73pub trait TryFutureExt {
74 fn log_err(self) -> LogErrorFuture<Self>
75 where
76 Self: Sized;
77 fn warn_on_err(self) -> LogErrorFuture<Self>
78 where
79 Self: Sized;
80}
81
82impl<F, T> TryFutureExt for F
83where
84 F: Future<Output = anyhow::Result<T>>,
85{
86 fn log_err(self) -> LogErrorFuture<Self>
87 where
88 Self: Sized,
89 {
90 LogErrorFuture(self, log::Level::Error)
91 }
92
93 fn warn_on_err(self) -> LogErrorFuture<Self>
94 where
95 Self: Sized,
96 {
97 LogErrorFuture(self, log::Level::Warn)
98 }
99}
100
101pub struct LogErrorFuture<F>(F, log::Level);
102
103impl<F, T> Future for LogErrorFuture<F>
104where
105 F: Future<Output = anyhow::Result<T>>,
106{
107 type Output = Option<T>;
108
109 fn poll(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
110 let level = self.1;
111 let inner = unsafe { Pin::new_unchecked(&mut self.get_unchecked_mut().0) };
112 match inner.poll(cx) {
113 Poll::Ready(output) => Poll::Ready(match output {
114 Ok(output) => Some(output),
115 Err(error) => {
116 log::log!(level, "{:?}", error);
117 None
118 }
119 }),
120 Poll::Pending => Poll::Pending,
121 }
122 }
123}
124
125#[cfg(test)]
126mod tests {
127 use super::*;
128
129 #[test]
130 fn test_extend_sorted() {
131 let mut vec = vec![];
132
133 extend_sorted(&mut vec, vec![21, 17, 13, 8, 1, 0], 5, |a, b| b.cmp(a));
134 assert_eq!(vec, &[21, 17, 13, 8, 1]);
135
136 extend_sorted(&mut vec, vec![101, 19, 17, 8, 2], 8, |a, b| b.cmp(a));
137 assert_eq!(vec, &[101, 21, 19, 17, 13, 8, 2, 1]);
138
139 extend_sorted(&mut vec, vec![1000, 19, 17, 9, 5], 8, |a, b| b.cmp(a));
140 assert_eq!(vec, &[1000, 101, 21, 19, 17, 13, 9, 8]);
141 }
142}
143
144// Allow surf Results to accept context like other Results do when
145// using anyhow.
146pub trait SurfResultExt {
147 fn context<C>(self, cx: C) -> Self
148 where
149 C: std::fmt::Display + Send + Sync + 'static;
150
151 fn with_context<C, F>(self, f: F) -> Self
152 where
153 C: std::fmt::Display + Send + Sync + 'static,
154 F: FnOnce() -> C;
155}
156
157impl<T> SurfResultExt for surf::Result<T> {
158 fn context<C>(self, cx: C) -> Self
159 where
160 C: std::fmt::Display + Send + Sync + 'static,
161 {
162 self.map_err(|e| surf::Error::new(e.status(), e.into_inner().context(cx)))
163 }
164
165 fn with_context<C, F>(self, f: F) -> Self
166 where
167 C: std::fmt::Display + Send + Sync + 'static,
168 F: FnOnce() -> C,
169 {
170 self.map_err(|e| surf::Error::new(e.status(), e.into_inner().context(f())))
171 }
172}