use super::H2Connection;
use crate::Headers;
#[cfg(feature = "unstable")]
use std::{
future::Future,
io,
pin::Pin,
sync::atomic::Ordering,
task::{Context, Poll},
};
#[cfg(feature = "unstable")]
#[must_use = "futures do nothing unless awaited"]
#[derive(Debug)]
pub struct ResponseHeaders<'a> {
pub(super) connection: &'a H2Connection,
pub(super) stream_id: u32,
}
#[cfg(feature = "unstable")]
impl Future for ResponseHeaders<'_> {
type Output = io::Result<crate::headers::hpack::FieldSection<'static>>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let Some(state) = self.connection.streams_lock().get(&self.stream_id).cloned() else {
return Poll::Ready(Err(io::ErrorKind::NotConnected.into()));
};
let try_take = || {
state
.recv
.response_headers
.lock()
.expect("response_headers mutex poisoned")
.take()
};
if let Some(fs) = try_take() {
return Poll::Ready(Ok(fs));
}
if state.recv.eof.load(Ordering::Acquire) {
return Poll::Ready(Err(io::ErrorKind::ConnectionAborted.into()));
}
state.recv.response_headers_waker.register(cx.waker());
if let Some(fs) = try_take() {
return Poll::Ready(Ok(fs));
}
if state.recv.eof.load(Ordering::Acquire) {
return Poll::Ready(Err(io::ErrorKind::ConnectionAborted.into()));
}
Poll::Pending
}
}
impl H2Connection {
#[cfg(feature = "unstable")]
pub fn response_headers(&self, stream_id: u32) -> ResponseHeaders<'_> {
ResponseHeaders {
connection: self,
stream_id,
}
}
pub(crate) fn take_trailers(&self, stream_id: u32) -> Option<Headers> {
let stream = self.streams_lock().get(&stream_id).cloned()?;
stream
.recv
.trailers
.lock()
.expect("recv trailers mutex poisoned")
.take()
}
}