mod util;
use std::future::Future;
pub use crate::util::{MaybeSend, MaybeSync};
use bytes::{Buf, BufMut, Bytes, BytesMut};
pub trait Error: std::error::Error + MaybeSend + MaybeSync + 'static {
fn session_error(&self) -> Option<(u32, String)>;
fn stream_error(&self) -> Option<u32> {
None
}
}
pub trait Session: Clone + MaybeSend + MaybeSync + 'static {
type SendStream: SendStream;
type RecvStream: RecvStream;
type Error: Error;
fn accept_uni(&self)
-> impl Future<Output = Result<Self::RecvStream, Self::Error>> + MaybeSend;
fn accept_bi(
&self,
) -> impl Future<Output = Result<(Self::SendStream, Self::RecvStream), Self::Error>> + MaybeSend;
fn open_bi(
&self,
) -> impl Future<Output = Result<(Self::SendStream, Self::RecvStream), Self::Error>> + MaybeSend;
fn open_uni(&self) -> impl Future<Output = Result<Self::SendStream, Self::Error>> + MaybeSend;
fn send_datagram(&self, payload: Bytes) -> Result<(), Self::Error>;
fn recv_datagram(&self) -> impl Future<Output = Result<Bytes, Self::Error>> + MaybeSend;
fn max_datagram_size(&self) -> usize;
fn protocol(&self) -> Option<&str> {
None
}
fn close(&self, code: u32, reason: &str);
fn closed(&self) -> impl Future<Output = Self::Error> + MaybeSend;
}
pub trait SendStream: MaybeSend {
type Error: Error;
fn write(&mut self, buf: &[u8])
-> impl Future<Output = Result<usize, Self::Error>> + MaybeSend;
fn write_buf<B: Buf + MaybeSend>(
&mut self,
buf: &mut B,
) -> impl Future<Output = Result<usize, Self::Error>> + MaybeSend {
async move {
let chunk = buf.chunk();
let size = self.write(chunk).await?;
buf.advance(size);
Ok(size)
}
}
fn write_chunk(
&mut self,
chunk: Bytes,
) -> impl Future<Output = Result<(), Self::Error>> + MaybeSend {
async move {
let mut c = chunk;
self.write_buf(&mut c).await?;
Ok(())
}
}
fn write_all(
&mut self,
buf: &[u8],
) -> impl Future<Output = Result<(), Self::Error>> + MaybeSend {
async move {
let mut pos = 0;
while pos < buf.len() {
pos += self.write(&buf[pos..]).await?;
}
Ok(())
}
}
fn write_all_buf<B: Buf + MaybeSend>(
&mut self,
buf: &mut B,
) -> impl Future<Output = Result<(), Self::Error>> + MaybeSend {
async move {
while buf.has_remaining() {
self.write_buf(buf).await?;
}
Ok(())
}
}
fn set_priority(&mut self, order: u8);
fn finish(&mut self) -> Result<(), Self::Error>;
fn reset(&mut self, code: u32);
fn closed(&mut self) -> impl Future<Output = Result<(), Self::Error>> + MaybeSend;
}
pub trait RecvStream: MaybeSend {
type Error: Error;
fn read(
&mut self,
dst: &mut [u8],
) -> impl Future<Output = Result<Option<usize>, Self::Error>> + MaybeSend;
fn read_buf<B: BufMut + MaybeSend>(
&mut self,
buf: &mut B,
) -> impl Future<Output = Result<Option<usize>, Self::Error>> + MaybeSend {
async move {
let dst = unsafe {
std::mem::transmute::<&mut bytes::buf::UninitSlice, &mut [u8]>(buf.chunk_mut())
};
let size = match self.read(dst).await? {
Some(size) if size > 0 => size,
_ => return Ok(None),
};
unsafe { buf.advance_mut(size) };
Ok(Some(size))
}
}
fn read_chunk(
&mut self,
max: usize,
) -> impl Future<Output = Result<Option<Bytes>, Self::Error>> + MaybeSend {
async move {
let mut buf = BytesMut::with_capacity(max.min(8 * 1024));
Ok(self.read_buf(&mut buf).await?.map(|_| buf.freeze()))
}
}
fn stop(&mut self, code: u32);
fn closed(&mut self) -> impl Future<Output = Result<(), Self::Error>> + MaybeSend;
fn read_all(&mut self) -> impl Future<Output = Result<Bytes, Self::Error>> + MaybeSend {
async move {
let mut buf = BytesMut::new();
self.read_all_buf(&mut buf).await?;
Ok(buf.freeze())
}
}
fn read_all_buf<B: BufMut + MaybeSend>(
&mut self,
buf: &mut B,
) -> impl Future<Output = Result<usize, Self::Error>> + MaybeSend {
async move {
let mut size = 0;
while buf.has_remaining_mut() {
match self.read_buf(buf).await? {
Some(n) if n > 0 => size += n,
_ => break,
}
}
Ok(size)
}
}
}