nyquest-backend-winhttp 0.1.0

WinHTTP backend for nyquest
Documentation
use std::future::Future;
use std::ops::Deref;
use std::pin::Pin;
use std::task::{Context, Poll};

use crate::error::WinHttpError;
use crate::r#async::context::{RequestContext, RequestState};

pub struct StateFuture<C> {
    context: C,
    expected_states: RequestState,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct StateChangedResult {
    pub state: RequestState,
    pub bytes_transferred: usize,
}

impl<C: Deref<Target = RequestContext>> Future for StateFuture<C> {
    type Output = Result<StateChangedResult, WinHttpError>;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        poll_for_state(&self.context, self.expected_states, cx)
    }
}

fn poll_for_state(
    context: &RequestContext,
    expected_states: RequestState,
    cx: &mut Context<'_>,
) -> Poll<Result<StateChangedResult, WinHttpError>> {
    if let Some(error) = context.take_error() {
        return Poll::Ready(Err(error));
    }
    let mut inner = context.inner.lock().unwrap();
    let state = inner.state;
    if state.intersects(expected_states) {
        Poll::Ready(Ok(StateChangedResult {
            state,
            bytes_transferred: inner.buffer_range.end,
        }))
    } else {
        inner.waker.clone_from(cx.waker());
        Poll::Pending
    }
}

pub(super) fn wait_for_state<C>(context: C, expected_states: RequestState) -> StateFuture<C> {
    StateFuture {
        context,
        expected_states,
    }
}