async_foundation/net/
mod.rs

1#![cfg(feature = "net")]
2//! Async networking primitives built on top of non-async `mio`.
3//!
4//! This module provides:
5//!
6//! - [`tcp_stream`] – async-friendly wrappers around `mio::net::TcpStream`, exposing
7//!   `AsyncRead`/`AsyncWrite` and configurable timeouts.
8//! - [`udp_socket`] – a UDP wrapper that integrates with the shared event listener
9//!   and also implements `AsyncRead`/`AsyncWrite`.
10//! - [`io_event_listener`] and [`timeouts`] – internal pieces used to multiplex I/O
11//!   readiness and timeout handling.
12//!
13//! The implementation is intentionally thin so you can use these building blocks
14//! directly or as part of a custom async runtime.
15
16use std::{mem::MaybeUninit, time::Instant};
17
18use mio::Token;
19
20use crate::net::io_event_listener::IOEventListener;
21pub mod io_event_listener;
22pub mod io_event_listener_state;
23pub mod tcp_stream;
24pub mod timeouts;
25pub mod udp_socket;
26
27pub fn event_listener() -> &'static mut IOEventListener {
28    static mut SINGLETON: MaybeUninit<IOEventListener> = MaybeUninit::uninit();
29    static ONCE: std::sync::Once = std::sync::Once::new();
30    unsafe {
31        ONCE.call_once(|| {
32            SINGLETON =
33                MaybeUninit::new(IOEventListener::new().expect("Can't create IOEventListener"));
34        });
35        let singleton_ref = &raw mut SINGLETON;
36        (*singleton_ref).assume_init_mut()
37    }
38}
39
40#[derive(PartialEq, Debug)]
41pub struct TokenTimeout {
42    pub token: Token,
43    pub timeout: Instant,
44}
45
46impl TokenTimeout {
47    pub fn new(token: Token, timeout: Instant) -> Self {
48        TokenTimeout { token, timeout }
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55    use std::time::Duration;
56
57    #[test]
58    fn test_token_timeout_new() {
59        let token = Token(42);
60        let timeout = Instant::now();
61        let token_timeout = TokenTimeout::new(token, timeout);
62        
63        assert_eq!(token_timeout.token, token);
64        assert_eq!(token_timeout.timeout, timeout);
65    }
66
67    #[test]
68    fn test_token_timeout_debug() {
69        let token = Token(123);
70        let timeout = Instant::now();
71        let token_timeout = TokenTimeout::new(token, timeout);
72        
73        let debug_str = format!("{:?}", token_timeout);
74        assert!(debug_str.contains("TokenTimeout"));
75        assert!(debug_str.contains("123"));
76    }
77
78    #[test]
79    fn test_token_timeout_partial_eq() {
80        let token1 = Token(1);
81        let token2 = Token(2);
82        let timeout1 = Instant::now();
83        let timeout2 = timeout1 + Duration::from_secs(1);
84        
85        let tt1 = TokenTimeout::new(token1, timeout1);
86        let tt2 = TokenTimeout::new(token1, timeout1);
87        let tt3 = TokenTimeout::new(token2, timeout1);
88        let tt4 = TokenTimeout::new(token1, timeout2);
89        
90        assert_eq!(tt1, tt2); // Same token and timeout
91        assert_ne!(tt1, tt3); // Different token
92        assert_ne!(tt1, tt4); // Different timeout
93    }
94
95    #[test]
96    fn test_mio_waker_token_constant() {
97        use crate::net::io_event_listener_state::MIO_WAKER_TOKEN;
98        assert_eq!(MIO_WAKER_TOKEN, Token(0));
99    }
100}