1#![warn(missing_docs)]
3
4#[cfg(feature = "dfir_macro")]
5#[cfg_attr(docsrs, doc(cfg(feature = "dfir_macro")))]
6pub mod demux_enum;
7pub mod multiset;
8pub mod sparse_vec;
9#[cfg(feature = "tokio")]
10pub mod unsync;
11
12mod monotonic;
13pub use monotonic::*;
14
15#[cfg(feature = "tokio")]
16mod udp;
17#[cfg(feature = "tokio")]
18#[cfg(not(target_arch = "wasm32"))]
19pub use udp::*;
20
21#[cfg(feature = "tokio")]
22mod tcp;
23#[cfg(feature = "tokio")]
24#[cfg(not(target_arch = "wasm32"))]
25pub use tcp::*;
26
27#[cfg(feature = "tokio")]
28#[cfg(unix)]
29mod socket;
30use std::net::SocketAddr;
31#[cfg(feature = "tokio")]
32use std::num::NonZeroUsize;
33use std::task::{Context, Poll};
34
35use futures::Stream;
36use serde::de::DeserializeOwned;
37use serde::ser::Serialize;
38#[cfg(feature = "tokio")]
39#[cfg(unix)]
40pub use socket::*;
41
42#[derive(Clone, Debug, Eq, Hash, PartialEq)]
44pub enum Persistence<T> {
45 Persist(T),
47 Delete(T),
49}
50
51#[derive(Clone, Debug, Eq, Hash, PartialEq)]
53pub enum PersistenceKeyed<K, V> {
54 Persist(K, V),
56 Delete(K),
58}
59
60#[cfg(feature = "tokio")]
62pub fn unbounded_channel<T>() -> (
63 tokio::sync::mpsc::UnboundedSender<T>,
64 tokio_stream::wrappers::UnboundedReceiverStream<T>,
65) {
66 let (send, recv) = tokio::sync::mpsc::unbounded_channel();
67 let recv = tokio_stream::wrappers::UnboundedReceiverStream::new(recv);
68 (send, recv)
69}
70
71#[cfg(feature = "tokio")]
73pub fn unsync_channel<T>(
74 capacity: Option<NonZeroUsize>,
75) -> (unsync::mpsc::Sender<T>, unsync::mpsc::Receiver<T>) {
76 unsync::mpsc::channel(capacity)
77}
78
79pub fn ready_iter<S>(stream: S) -> impl Iterator<Item = S::Item>
81where
82 S: Stream,
83{
84 let mut stream = Box::pin(stream);
85 std::iter::from_fn(move || {
86 match stream
87 .as_mut()
88 .poll_next(&mut Context::from_waker(futures::task::noop_waker_ref()))
89 {
90 Poll::Ready(opt) => opt,
91 Poll::Pending => None,
92 }
93 })
94}
95
96#[cfg(feature = "tokio")]
101pub fn collect_ready<C, S>(stream: S) -> C
102where
103 C: FromIterator<S::Item>,
104 S: Stream,
105{
106 assert!(
107 tokio::runtime::Handle::try_current().is_err(),
108 "Calling `collect_ready` from an async runtime may cause incorrect results, use `collect_ready_async` instead."
109 );
110 ready_iter(stream).collect()
111}
112
113#[cfg(feature = "tokio")]
118pub async fn collect_ready_async<C, S>(stream: S) -> C
119where
120 C: Default + Extend<S::Item>,
121 S: Stream,
122{
123 use std::sync::atomic::Ordering;
124
125 tokio::task::yield_now().await;
127
128 let got_any_items = std::sync::atomic::AtomicBool::new(true);
129 let mut unfused_iter =
130 ready_iter(stream).inspect(|_| got_any_items.store(true, Ordering::Relaxed));
131 let mut out = C::default();
132 while got_any_items.swap(false, Ordering::Relaxed) {
133 out.extend(unfused_iter.by_ref());
134 tokio::task::yield_now().await;
137 }
138 out
139}
140
141pub fn serialize_to_bytes<T>(msg: T) -> bytes::Bytes
143where
144 T: Serialize,
145{
146 bytes::Bytes::from(bincode::serialize(&msg).unwrap())
147}
148
149pub fn deserialize_from_bytes<T>(msg: impl AsRef<[u8]>) -> bincode::Result<T>
151where
152 T: DeserializeOwned,
153{
154 bincode::deserialize(msg.as_ref())
155}
156
157pub fn ipv4_resolve(addr: &str) -> Result<SocketAddr, std::io::Error> {
159 use std::net::ToSocketAddrs;
160 let mut addrs = addr.to_socket_addrs()?;
161 let result = addrs.find(|addr| addr.is_ipv4());
162 match result {
163 Some(addr) => Ok(addr),
164 None => Err(std::io::Error::other("Unable to resolve IPv4 address")),
165 }
166}
167
168#[cfg(feature = "tokio")]
171#[cfg(not(target_arch = "wasm32"))]
172pub async fn bind_udp_bytes(addr: SocketAddr) -> (UdpSink, UdpStream, SocketAddr) {
173 let socket = tokio::net::UdpSocket::bind(addr).await.unwrap();
174 udp_bytes(socket)
175}
176
177#[cfg(feature = "tokio")]
180#[cfg(not(target_arch = "wasm32"))]
181pub async fn bind_udp_lines(addr: SocketAddr) -> (UdpLinesSink, UdpLinesStream, SocketAddr) {
182 let socket = tokio::net::UdpSocket::bind(addr).await.unwrap();
183 udp_lines(socket)
184}
185
186#[cfg(feature = "tokio")]
193#[cfg(not(target_arch = "wasm32"))]
194pub async fn bind_tcp_bytes(
195 addr: SocketAddr,
196) -> (
197 unsync::mpsc::Sender<(bytes::Bytes, SocketAddr)>,
198 unsync::mpsc::Receiver<Result<(bytes::BytesMut, SocketAddr), std::io::Error>>,
199 SocketAddr,
200) {
201 bind_tcp(addr, tokio_util::codec::LengthDelimitedCodec::new())
202 .await
203 .unwrap()
204}
205
206#[cfg(feature = "tokio")]
208#[cfg(not(target_arch = "wasm32"))]
209pub async fn bind_tcp_lines(
210 addr: SocketAddr,
211) -> (
212 unsync::mpsc::Sender<(String, SocketAddr)>,
213 unsync::mpsc::Receiver<Result<(String, SocketAddr), tokio_util::codec::LinesCodecError>>,
214 SocketAddr,
215) {
216 bind_tcp(addr, tokio_util::codec::LinesCodec::new())
217 .await
218 .unwrap()
219}
220
221#[cfg(feature = "tokio")]
226#[cfg(not(target_arch = "wasm32"))]
227pub fn connect_tcp_bytes() -> (
228 TcpFramedSink<bytes::Bytes>,
229 TcpFramedStream<tokio_util::codec::LengthDelimitedCodec>,
230) {
231 connect_tcp(tokio_util::codec::LengthDelimitedCodec::new())
232}
233
234#[cfg(feature = "tokio")]
236#[cfg(not(target_arch = "wasm32"))]
237pub fn connect_tcp_lines() -> (
238 TcpFramedSink<String>,
239 TcpFramedStream<tokio_util::codec::LinesCodec>,
240) {
241 connect_tcp(tokio_util::codec::LinesCodec::new())
242}
243
244pub fn sort_unstable_by_key_hrtb<T, F, K>(slice: &mut [T], f: F)
249where
250 F: for<'a> Fn(&'a T) -> &'a K,
251 K: Ord,
252{
253 slice.sort_unstable_by(|a, b| f(a).cmp(f(b)))
254}
255
256pub fn iter_batches_stream<I>(
263 iter: I,
264 n: usize,
265) -> futures::stream::PollFn<impl FnMut(&mut Context<'_>) -> Poll<Option<I::Item>>>
266where
267 I: IntoIterator + Unpin,
268{
269 let mut count = 0;
270 let mut iter = iter.into_iter();
271 futures::stream::poll_fn(move |ctx| {
272 count += 1;
273 if n < count {
274 count = 0;
275 ctx.waker().wake_by_ref();
276 Poll::Pending
277 } else {
278 Poll::Ready(iter.next())
279 }
280 })
281}
282
283#[cfg(test)]
284mod test {
285 use super::*;
286
287 #[test]
288 pub fn test_collect_ready() {
289 let (send, mut recv) = unbounded_channel::<usize>();
290 for x in 0..1000 {
291 send.send(x).unwrap();
292 }
293 assert_eq!(1000, collect_ready::<Vec<_>, _>(&mut recv).len());
294 }
295
296 #[crate::test]
297 pub async fn test_collect_ready_async() {
298 let (send, mut recv) = unbounded_channel::<usize>();
300 for x in 0..1000 {
301 send.send(x).unwrap();
302 }
303 assert_eq!(
304 1000,
305 collect_ready_async::<Vec<_>, _>(&mut recv).await.len()
306 );
307 }
308}