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;
8#[cfg(feature = "tokio")]
9pub mod unsync;
10
11mod monotonic;
12pub use monotonic::*;
13
14#[cfg(feature = "tokio")]
15mod udp;
16#[cfg(feature = "tokio")]
17#[cfg(not(target_arch = "wasm32"))]
18pub use udp::*;
19
20#[cfg(feature = "tokio")]
21mod tcp;
22#[cfg(feature = "tokio")]
23#[cfg(not(target_arch = "wasm32"))]
24pub use tcp::*;
25
26#[cfg(feature = "tokio")]
27#[cfg(unix)]
28mod socket;
29use std::net::SocketAddr;
30#[cfg(feature = "tokio")]
31use std::num::NonZeroUsize;
32use std::task::{Context, Poll};
33
34use futures::Stream;
35use serde::de::DeserializeOwned;
36use serde::ser::Serialize;
37#[cfg(feature = "tokio")]
38#[cfg(unix)]
39pub use socket::*;
40
41#[cfg(feature = "tokio")]
43pub fn unbounded_channel<T>() -> (
44 tokio::sync::mpsc::UnboundedSender<T>,
45 tokio_stream::wrappers::UnboundedReceiverStream<T>,
46) {
47 let (send, recv) = tokio::sync::mpsc::unbounded_channel();
48 let recv = tokio_stream::wrappers::UnboundedReceiverStream::new(recv);
49 (send, recv)
50}
51
52#[cfg(feature = "tokio")]
54pub fn unsync_channel<T>(
55 capacity: Option<NonZeroUsize>,
56) -> (unsync::mpsc::Sender<T>, unsync::mpsc::Receiver<T>) {
57 unsync::mpsc::channel(capacity)
58}
59
60pub fn ready_iter<S>(stream: S) -> impl Iterator<Item = S::Item>
62where
63 S: Stream,
64{
65 let mut stream = Box::pin(stream);
66 std::iter::from_fn(move || {
67 match stream
68 .as_mut()
69 .poll_next(&mut Context::from_waker(futures::task::noop_waker_ref()))
70 {
71 Poll::Ready(opt) => opt,
72 Poll::Pending => None,
73 }
74 })
75}
76
77#[cfg(feature = "tokio")]
82pub fn collect_ready<C, S>(stream: S) -> C
83where
84 C: FromIterator<S::Item>,
85 S: Stream,
86{
87 assert!(
88 tokio::runtime::Handle::try_current().is_err(),
89 "Calling `collect_ready` from an async runtime may cause incorrect results, use `collect_ready_async` instead."
90 );
91 ready_iter(stream).collect()
92}
93
94#[cfg(feature = "tokio")]
99pub async fn collect_ready_async<C, S>(stream: S) -> C
100where
101 C: Default + Extend<S::Item>,
102 S: Stream,
103{
104 use std::sync::atomic::Ordering;
105
106 tokio::task::yield_now().await;
108
109 let got_any_items = std::sync::atomic::AtomicBool::new(true);
110 let mut unfused_iter =
111 ready_iter(stream).inspect(|_| got_any_items.store(true, Ordering::Relaxed));
112 let mut out = C::default();
113 while got_any_items.swap(false, Ordering::Relaxed) {
114 out.extend(unfused_iter.by_ref());
115 tokio::task::yield_now().await;
118 }
119 out
120}
121
122pub fn serialize_to_bytes<T>(msg: T) -> bytes::Bytes
124where
125 T: Serialize,
126{
127 bytes::Bytes::from(bincode::serialize(&msg).unwrap())
128}
129
130pub fn deserialize_from_bytes<T>(msg: impl AsRef<[u8]>) -> bincode::Result<T>
132where
133 T: DeserializeOwned,
134{
135 bincode::deserialize(msg.as_ref())
136}
137
138pub fn ipv4_resolve(addr: &str) -> Result<SocketAddr, std::io::Error> {
140 use std::net::ToSocketAddrs;
141 let mut addrs = addr.to_socket_addrs()?;
142 let result = addrs.find(|addr| addr.is_ipv4());
143 match result {
144 Some(addr) => Ok(addr),
145 None => Err(std::io::Error::other("Unable to resolve IPv4 address")),
146 }
147}
148
149#[cfg(feature = "tokio")]
152#[cfg(not(target_arch = "wasm32"))]
153pub async fn bind_udp_bytes(addr: SocketAddr) -> (UdpSink, UdpStream, SocketAddr) {
154 let socket = tokio::net::UdpSocket::bind(addr).await.unwrap();
155 udp_bytes(socket)
156}
157
158#[cfg(feature = "tokio")]
161#[cfg(not(target_arch = "wasm32"))]
162pub async fn bind_udp_lines(addr: SocketAddr) -> (UdpLinesSink, UdpLinesStream, SocketAddr) {
163 let socket = tokio::net::UdpSocket::bind(addr).await.unwrap();
164 udp_lines(socket)
165}
166
167#[cfg(feature = "tokio")]
174#[cfg(not(target_arch = "wasm32"))]
175pub async fn bind_tcp_bytes(
176 addr: SocketAddr,
177) -> (
178 unsync::mpsc::Sender<(bytes::Bytes, SocketAddr)>,
179 unsync::mpsc::Receiver<Result<(bytes::BytesMut, SocketAddr), std::io::Error>>,
180 SocketAddr,
181) {
182 bind_tcp(addr, tokio_util::codec::LengthDelimitedCodec::new())
183 .await
184 .unwrap()
185}
186
187#[cfg(feature = "tokio")]
189#[cfg(not(target_arch = "wasm32"))]
190pub async fn bind_tcp_lines(
191 addr: SocketAddr,
192) -> (
193 unsync::mpsc::Sender<(String, SocketAddr)>,
194 unsync::mpsc::Receiver<Result<(String, SocketAddr), tokio_util::codec::LinesCodecError>>,
195 SocketAddr,
196) {
197 bind_tcp(addr, tokio_util::codec::LinesCodec::new())
198 .await
199 .unwrap()
200}
201
202#[cfg(feature = "tokio")]
207#[cfg(not(target_arch = "wasm32"))]
208pub fn connect_tcp_bytes() -> (
209 TcpFramedSink<bytes::Bytes>,
210 TcpFramedStream<tokio_util::codec::LengthDelimitedCodec>,
211) {
212 connect_tcp(tokio_util::codec::LengthDelimitedCodec::new())
213}
214
215#[cfg(feature = "tokio")]
217#[cfg(not(target_arch = "wasm32"))]
218pub fn connect_tcp_lines() -> (
219 TcpFramedSink<String>,
220 TcpFramedStream<tokio_util::codec::LinesCodec>,
221) {
222 connect_tcp(tokio_util::codec::LinesCodec::new())
223}
224
225pub fn sort_unstable_by_key_hrtb<T, F, K>(slice: &mut [T], f: F)
230where
231 F: for<'a> Fn(&'a T) -> &'a K,
232 K: Ord,
233{
234 slice.sort_unstable_by(|a, b| f(a).cmp(f(b)))
235}
236
237pub fn iter_batches_stream<I>(
244 iter: I,
245 n: usize,
246) -> futures::stream::PollFn<impl FnMut(&mut Context<'_>) -> Poll<Option<I::Item>>>
247where
248 I: IntoIterator + Unpin,
249{
250 let mut count = 0;
251 let mut iter = iter.into_iter();
252 futures::stream::poll_fn(move |ctx| {
253 count += 1;
254 if n < count {
255 count = 0;
256 ctx.waker().wake_by_ref();
257 Poll::Pending
258 } else {
259 Poll::Ready(iter.next())
260 }
261 })
262}
263
264#[cfg(test)]
265mod test {
266 use super::*;
267
268 #[test]
269 pub fn test_collect_ready() {
270 let (send, mut recv) = unbounded_channel::<usize>();
271 for x in 0..1000 {
272 send.send(x).unwrap();
273 }
274 assert_eq!(1000, collect_ready::<Vec<_>, _>(&mut recv).len());
275 }
276
277 #[crate::test]
278 pub async fn test_collect_ready_async() {
279 let (send, mut recv) = unbounded_channel::<usize>();
281 for x in 0..1000 {
282 send.send(x).unwrap();
283 }
284 assert_eq!(
285 1000,
286 collect_ready_async::<Vec<_>, _>(&mut recv).await.len()
287 );
288 }
289}