async-foundation 0.2.1

Foundational async primitives for Rust - timers, networking, and common utilities
Documentation
use std::{fmt::Debug, task::Waker};

pub struct ReadyFutureState<T> {
    pub(crate) waker: Option<Waker>,
    pub(crate) result: ReadyFutureResult<T>,
}

impl<T> ReadyFutureState<T> {
    pub fn new() -> ReadyFutureState<T> {
        ReadyFutureState {
            waker: None,
            result: ReadyFutureResult::Pending,
        }
    }

    pub fn new_completed(value: T) -> ReadyFutureState<T> {
        ReadyFutureState {
            waker: None,
            result: ReadyFutureResult::Completed(value),
        }
    }

    pub fn is_fulfilled(&self) -> bool {
        !self.is_pending()
    }

    pub fn is_aborted(&self) -> bool {
        matches!(self.result, ReadyFutureResult::Aborted)
    }

    pub fn is_timeouted(&self) -> bool {
        matches!(self.result, ReadyFutureResult::Timeout)
    }

    pub fn is_terminated(&self) -> bool {
        matches!(self.result, ReadyFutureResult::Terminated)
    }

    pub fn is_pending(&self) -> bool {
        matches!(self.result, ReadyFutureResult::Pending)
    }

    pub fn is_completed(&self) -> bool {
        matches!(self.result, ReadyFutureResult::Completed(_))
    }

    pub fn abort(&mut self) {
        self.result = ReadyFutureResult::Aborted;
        self.wake();
    }

    pub fn timeout(&mut self) {
        self.result = ReadyFutureResult::Timeout;
        self.wake();
    }

    pub fn complete(&mut self, val: T) {
        self.result = ReadyFutureResult::Completed(val);
        self.wake();
    }

    pub(crate) fn wake(&mut self) {
        if let Some(waker) = self.waker.take() {
            waker.wake()
        }
    }

    pub fn terminate(&mut self) {
        self.result = ReadyFutureResult::Terminated;
    }
}

#[derive(Clone, Debug)]
pub enum ReadyFutureResult<T> {
    Completed(T),
    Timeout,
    Aborted,
    Pending,
    Terminated,
}

impl<T: Debug> Debug for ReadyFutureState<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("ReadyFutureState")
            .field("waker", &self.waker)
            .field("result", &self.result)
            .finish()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::atomic::{AtomicBool, Ordering};
    use std::task::Wake;

    struct TestWaker {
        woken: std::sync::Arc<AtomicBool>,
    }

    impl Wake for TestWaker {
        fn wake(self: std::sync::Arc<Self>) {
            self.woken.store(true, Ordering::SeqCst);
        }
    }

    #[test]
    fn test_new_state() {
        let state = ReadyFutureState::<i32>::new();
        assert!(state.is_pending());
        assert!(!state.is_fulfilled());
        assert!(!state.is_completed());
        assert!(!state.is_aborted());
        assert!(!state.is_timeouted());
        assert!(!state.is_terminated());
        assert!(state.waker.is_none());
    }

    #[test]
    fn test_new_completed_state() {
        let state = ReadyFutureState::new_completed(42);
        assert!(!state.is_pending());
        assert!(state.is_fulfilled());
        assert!(state.is_completed());
        assert!(!state.is_aborted());
        assert!(!state.is_timeouted());
        assert!(!state.is_terminated());
        assert!(state.waker.is_none());
    }

    #[test]
    fn test_abort() {
        let mut state = ReadyFutureState::<i32>::new();
        assert!(state.is_pending());
        
        state.abort();
        assert!(!state.is_pending());
        assert!(state.is_fulfilled());
        assert!(state.is_aborted());
        assert!(!state.is_completed());
        assert!(!state.is_timeouted());
        assert!(!state.is_terminated());
    }

    #[test]
    fn test_timeout() {
        let mut state = ReadyFutureState::<i32>::new();
        assert!(state.is_pending());
        
        state.timeout();
        assert!(!state.is_pending());
        assert!(state.is_fulfilled());
        assert!(state.is_timeouted());
        assert!(!state.is_completed());
        assert!(!state.is_aborted());
        assert!(!state.is_terminated());
    }

    #[test]
    fn test_complete() {
        let mut state = ReadyFutureState::<i32>::new();
        assert!(state.is_pending());
        
        state.complete(123);
        assert!(!state.is_pending());
        assert!(state.is_fulfilled());
        assert!(state.is_completed());
        assert!(!state.is_aborted());
        assert!(!state.is_timeouted());
        assert!(!state.is_terminated());
    }

    #[test]
    fn test_terminate() {
        let mut state = ReadyFutureState::<i32>::new();
        assert!(state.is_pending());
        
        state.terminate();
        assert!(!state.is_pending());
        assert!(state.is_fulfilled());
        assert!(state.is_terminated());
        assert!(!state.is_completed());
        assert!(!state.is_aborted());
        assert!(!state.is_timeouted());
    }

    #[test]
    fn test_waker_invocation_on_abort() {
        let mut state = ReadyFutureState::<i32>::new();
        let woken = std::sync::Arc::new(AtomicBool::new(false));
        let waker = std::sync::Arc::new(TestWaker {
            woken: woken.clone(),
        });
        let waker = std::task::Waker::from(waker);
        
        state.waker = Some(waker);
        assert!(!woken.load(Ordering::SeqCst));
        
        state.abort();
        assert!(woken.load(Ordering::SeqCst));
        assert!(state.waker.is_none()); // Waker should be consumed
    }

    #[test]
    fn test_waker_invocation_on_timeout() {
        let mut state = ReadyFutureState::<i32>::new();
        let woken = std::sync::Arc::new(AtomicBool::new(false));
        let waker = std::sync::Arc::new(TestWaker {
            woken: woken.clone(),
        });
        let waker = std::task::Waker::from(waker);
        
        state.waker = Some(waker);
        assert!(!woken.load(Ordering::SeqCst));
        
        state.timeout();
        assert!(woken.load(Ordering::SeqCst));
        assert!(state.waker.is_none()); // Waker should be consumed
    }

    #[test]
    fn test_waker_invocation_on_complete() {
        let mut state = ReadyFutureState::<i32>::new();
        let woken = std::sync::Arc::new(AtomicBool::new(false));
        let waker = std::sync::Arc::new(TestWaker {
            woken: woken.clone(),
        });
        let waker = std::task::Waker::from(waker);
        
        state.waker = Some(waker);
        assert!(!woken.load(Ordering::SeqCst));
        
        state.complete(456);
        assert!(woken.load(Ordering::SeqCst));
        assert!(state.waker.is_none()); // Waker should be consumed
    }

    #[test]
    fn test_no_waker_no_invocation() {
        let mut state = ReadyFutureState::<i32>::new();
        let woken = std::sync::Arc::new(AtomicBool::new(false));
        let waker = std::sync::Arc::new(TestWaker {
            woken: woken.clone(),
        });
        let _waker = std::task::Waker::from(waker);
        
        assert!(state.waker.is_none());
        assert!(!woken.load(Ordering::SeqCst));
        
        state.abort();
        assert!(!woken.load(Ordering::SeqCst)); // Should not invoke waker
    }

    #[test]
    fn test_ready_future_result_debug() {
        let result = ReadyFutureResult::Completed(42);
        let debug_str = format!("{:?}", result);
        assert!(debug_str.contains("Completed"));
        assert!(debug_str.contains("42"));
        
        let result = ReadyFutureResult::<i32>::Pending;
        let debug_str = format!("{:?}", result);
        assert!(debug_str.contains("Pending"));
        
        let result = ReadyFutureResult::<i32>::Aborted;
        let debug_str = format!("{:?}", result);
        assert!(debug_str.contains("Aborted"));
        
        let result = ReadyFutureResult::<i32>::Timeout;
        let debug_str = format!("{:?}", result);
        assert!(debug_str.contains("Timeout"));
        
        let result = ReadyFutureResult::<i32>::Terminated;
        let debug_str = format!("{:?}", result);
        assert!(debug_str.contains("Terminated"));
    }

    #[test]
    fn test_ready_future_result_clone() {
        let result1 = ReadyFutureResult::Completed(42);
        let result2 = result1.clone();
        
        match (result1, result2) {
            (ReadyFutureResult::Completed(v1), ReadyFutureResult::Completed(v2)) => {
                assert_eq!(v1, v2);
            }
            _ => panic!("Clone should preserve the value"),
        }
        
        let result1 = ReadyFutureResult::<i32>::Pending;
        let result2 = result1.clone();
        assert!(matches!(result1, ReadyFutureResult::Pending));
        assert!(matches!(result2, ReadyFutureResult::Pending));
    }

    #[test]
    fn test_state_debug_formatting() {
        let state = ReadyFutureState::<i32>::new();
        let debug_str = format!("{:?}", state);
        assert!(debug_str.contains("ReadyFutureState"));
        assert!(debug_str.contains("waker"));
        assert!(debug_str.contains("result"));
    }
}