use std::task::{Context, Poll};
use bytes::Bytes;
use crate::h3::error::TransportError;
pub trait RecvStream: Unpin + Send {
fn poll_recv(&mut self, cx: &mut Context<'_>) -> Poll<Result<Option<Bytes>, TransportError>>;
fn id(&self) -> u64;
}
pub trait SendStream: Unpin + Send {
fn poll_send(&mut self, cx: &mut Context<'_>, data: &[u8]) -> Poll<Result<(), TransportError>>;
fn poll_finish(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), TransportError>>;
fn poll_reset(&mut self, cx: &mut Context<'_>, code: u64) -> Poll<Result<(), TransportError>>;
fn poll_stop_sending(
&mut self,
cx: &mut Context<'_>,
code: u64,
) -> Poll<Result<(), TransportError>>;
}
pub trait BidiStream: RecvStream + SendStream {}
pub trait UniStream: RecvStream + SendStream {}
pub trait OpenStreams {
fn poll_open_uni(
&mut self,
cx: &mut Context<'_>,
) -> Poll<Result<Box<dyn UniStream>, TransportError>>;
}
pub trait Accept {
fn poll_accept(
&mut self,
cx: &mut Context<'_>,
) -> Poll<Result<Option<Box<dyn BidiStream>>, TransportError>>;
fn poll_accept_uni(
&mut self,
cx: &mut Context<'_>,
) -> Poll<Result<Option<Box<dyn UniStream>>, TransportError>>;
}
pub trait Connection: OpenStreams + Accept {
fn is_handshake_complete(&self) -> bool;
fn poll_shutdown(
&mut self,
cx: &mut Context<'_>,
error_code: u64,
) -> Poll<Result<(), TransportError>>;
}
#[cfg(test)]
mod tests {
use super::*;
use futures_util::task::noop_waker_ref;
fn cx() -> Context<'static> {
Context::from_waker(noop_waker_ref())
}
struct Mock {
data: Option<Bytes>,
}
impl RecvStream for Mock {
#[inline]
fn poll_recv(
&mut self,
_cx: &mut Context<'_>,
) -> Poll<Result<Option<Bytes>, TransportError>> {
Poll::Ready(Ok(self.data.take()))
}
#[inline]
fn id(&self) -> u64 {
0
}
}
impl SendStream for Mock {
#[inline]
fn poll_send(
&mut self,
_cx: &mut Context<'_>,
_data: &[u8],
) -> Poll<Result<(), TransportError>> {
Poll::Ready(Ok(()))
}
#[inline]
fn poll_finish(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), TransportError>> {
Poll::Ready(Ok(()))
}
#[inline]
fn poll_reset(
&mut self,
_cx: &mut Context<'_>,
_code: u64,
) -> Poll<Result<(), TransportError>> {
Poll::Ready(Ok(()))
}
#[inline]
fn poll_stop_sending(
&mut self,
_cx: &mut Context<'_>,
_code: u64,
) -> Poll<Result<(), TransportError>> {
Poll::Ready(Ok(()))
}
}
impl BidiStream for Mock {}
impl UniStream for Mock {}
#[test]
fn bidi_stream_object_drains() {
let mut stream: Box<dyn BidiStream> = Box::new(Mock {
data: Some(Bytes::from_static(b"hi")),
});
let mut cx = cx();
assert_eq!(
stream.poll_recv(&mut cx),
Poll::Ready(Ok(Some(Bytes::from_static(b"hi"))))
);
assert_eq!(stream.poll_recv(&mut cx), Poll::Ready(Ok(None)));
assert!(stream.poll_send(&mut cx, b"x").is_ready());
assert!(stream.poll_finish(&mut cx).is_ready());
assert!(stream.poll_reset(&mut cx, 0x10c).is_ready());
assert!(stream.poll_stop_sending(&mut cx, 0x10c).is_ready());
}
#[test]
fn uni_stream_object_drains() {
let mut stream: Box<dyn UniStream> = Box::new(Mock { data: None });
let mut cx = cx();
assert_eq!(stream.poll_recv(&mut cx), Poll::Ready(Ok(None)));
assert!(stream.poll_send(&mut cx, b"y").is_ready());
assert!(stream.poll_finish(&mut cx).is_ready());
}
}