async-foundation 0.2.1

Foundational async primitives for Rust - timers, networking, and common utilities
Documentation
#![cfg(feature = "net")]
//! Async networking primitives built on top of non-async `mio`.
//!
//! This module provides:
//!
//! - [`tcp_stream`] – async-friendly wrappers around `mio::net::TcpStream`, exposing
//!   `AsyncRead`/`AsyncWrite` and configurable timeouts.
//! - [`udp_socket`] – a UDP wrapper that integrates with the shared event listener
//!   and also implements `AsyncRead`/`AsyncWrite`.
//! - [`io_event_listener`] and [`timeouts`] – internal pieces used to multiplex I/O
//!   readiness and timeout handling.
//!
//! The implementation is intentionally thin so you can use these building blocks
//! directly or as part of a custom async runtime.

use std::{mem::MaybeUninit, time::Instant};

use mio::Token;

use crate::net::io_event_listener::IOEventListener;
pub mod io_event_listener;
pub mod io_event_listener_state;
pub mod tcp_stream;
pub mod timeouts;
pub mod udp_socket;

pub fn event_listener() -> &'static mut IOEventListener {
    static mut SINGLETON: MaybeUninit<IOEventListener> = MaybeUninit::uninit();
    static ONCE: std::sync::Once = std::sync::Once::new();
    unsafe {
        ONCE.call_once(|| {
            SINGLETON =
                MaybeUninit::new(IOEventListener::new().expect("Can't create IOEventListener"));
        });
        let singleton_ref = &raw mut SINGLETON;
        (*singleton_ref).assume_init_mut()
    }
}

#[derive(PartialEq, Debug)]
pub struct TokenTimeout {
    pub token: Token,
    pub timeout: Instant,
}

impl TokenTimeout {
    pub fn new(token: Token, timeout: Instant) -> Self {
        TokenTimeout { token, timeout }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::time::Duration;

    #[test]
    fn test_token_timeout_new() {
        let token = Token(42);
        let timeout = Instant::now();
        let token_timeout = TokenTimeout::new(token, timeout);
        
        assert_eq!(token_timeout.token, token);
        assert_eq!(token_timeout.timeout, timeout);
    }

    #[test]
    fn test_token_timeout_debug() {
        let token = Token(123);
        let timeout = Instant::now();
        let token_timeout = TokenTimeout::new(token, timeout);
        
        let debug_str = format!("{:?}", token_timeout);
        assert!(debug_str.contains("TokenTimeout"));
        assert!(debug_str.contains("123"));
    }

    #[test]
    fn test_token_timeout_partial_eq() {
        let token1 = Token(1);
        let token2 = Token(2);
        let timeout1 = Instant::now();
        let timeout2 = timeout1 + Duration::from_secs(1);
        
        let tt1 = TokenTimeout::new(token1, timeout1);
        let tt2 = TokenTimeout::new(token1, timeout1);
        let tt3 = TokenTimeout::new(token2, timeout1);
        let tt4 = TokenTimeout::new(token1, timeout2);
        
        assert_eq!(tt1, tt2); // Same token and timeout
        assert_ne!(tt1, tt3); // Different token
        assert_ne!(tt1, tt4); // Different timeout
    }

    #[test]
    fn test_mio_waker_token_constant() {
        use crate::net::io_event_listener_state::MIO_WAKER_TOKEN;
        assert_eq!(MIO_WAKER_TOKEN, Token(0));
    }
}