use std::fmt::{Debug, Display};
use std::sync::Arc;
use std::task::{self, Poll};
use bytes::Buf;
use crate::error::Code;
pub use crate::proto::stream::{InvalidStreamId, StreamId};
pub use crate::stream::WriteBuf;
#[derive(Clone)]
pub enum ConnectionErrorIncoming {
ApplicationClose {
error_code: u64,
},
Timeout,
InternalError(String),
Undefined(Arc<dyn std::error::Error + Send + Sync>),
}
impl Debug for ConnectionErrorIncoming {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::ApplicationClose { error_code } => {
let error_code = Code::from(*error_code);
write!(f, "ApplicationClose({})", error_code)
}
Self::Timeout => write!(f, "Timeout"),
Self::InternalError(arg0) => f.debug_tuple("InternalError").field(arg0).finish(),
Self::Undefined(arg0) => f.debug_tuple("Undefined").field(arg0).finish(),
}
}
}
#[derive(Debug)]
pub enum StreamErrorIncoming {
ConnectionErrorIncoming {
connection_error: ConnectionErrorIncoming,
},
StreamTerminated {
error_code: u64,
},
Unknown(Box<dyn std::error::Error + Send + Sync>),
}
impl std::error::Error for StreamErrorIncoming {}
impl Display for StreamErrorIncoming {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
StreamErrorIncoming::ConnectionErrorIncoming { connection_error } => {
write!(f, "ConnectionError: {}", connection_error)
}
StreamErrorIncoming::StreamTerminated { error_code } => {
let error_code = Code::from(*error_code);
write!(f, "StreamClosed: {}", error_code)
}
StreamErrorIncoming::Unknown(error) => write!(f, "Error undefined by h3: {}", error),
}
}
}
impl Display for ConnectionErrorIncoming {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ConnectionErrorIncoming::ApplicationClose { error_code } => {
let error_code = Code::from(*error_code);
write!(f, "ApplicationClose: {}", error_code)
}
ConnectionErrorIncoming::Timeout => write!(f, "Timeout"),
ConnectionErrorIncoming::InternalError(error) => {
write!(
f,
"InternalError in the quic trait implementation: {}",
error
)
}
ConnectionErrorIncoming::Undefined(error) => {
write!(f, "Error undefined by h3: {}", error)
}
}
}
}
impl std::error::Error for ConnectionErrorIncoming {}
pub trait Connection<B: Buf>: OpenStreams<B> {
type RecvStream: RecvStream;
type OpenStreams: OpenStreams<B, SendStream = Self::SendStream, BidiStream = Self::BidiStream>;
fn poll_accept_recv(
&mut self,
cx: &mut task::Context<'_>,
) -> Poll<Result<Self::RecvStream, ConnectionErrorIncoming>>;
fn poll_accept_bidi(
&mut self,
cx: &mut task::Context<'_>,
) -> Poll<Result<Self::BidiStream, ConnectionErrorIncoming>>;
fn opener(&self) -> Self::OpenStreams;
}
pub trait OpenStreams<B: Buf> {
type BidiStream: SendStream<B> + RecvStream;
type SendStream: SendStream<B>;
fn poll_open_bidi(
&mut self,
cx: &mut task::Context<'_>,
) -> Poll<Result<Self::BidiStream, StreamErrorIncoming>>;
fn poll_open_send(
&mut self,
cx: &mut task::Context<'_>,
) -> Poll<Result<Self::SendStream, StreamErrorIncoming>>;
fn close(&mut self, code: crate::error::Code, reason: &[u8]);
}
pub trait SendStream<B: Buf> {
fn poll_ready(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), StreamErrorIncoming>>;
fn send_data<T: Into<WriteBuf<B>>>(&mut self, data: T) -> Result<(), StreamErrorIncoming>;
fn poll_finish(&mut self, cx: &mut task::Context<'_>) -> Poll<Result<(), StreamErrorIncoming>>;
fn reset(&mut self, reset_code: u64);
fn send_id(&self) -> StreamId;
}
pub trait SendStreamUnframed<B: Buf>: SendStream<B> {
fn poll_send<D: Buf>(
&mut self,
cx: &mut task::Context<'_>,
buf: &mut D,
) -> Poll<Result<usize, StreamErrorIncoming>>;
}
pub trait RecvStream {
type Buf: Buf;
fn poll_data(
&mut self,
cx: &mut task::Context<'_>,
) -> Poll<Result<Option<Self::Buf>, StreamErrorIncoming>>;
fn stop_sending(&mut self, error_code: u64);
fn recv_id(&self) -> StreamId;
}
pub trait BidiStream<B: Buf>: SendStream<B> + RecvStream {
type SendStream: SendStream<B>;
type RecvStream: RecvStream;
fn split(self) -> (Self::SendStream, Self::RecvStream);
}