#![forbid(unsafe_code)]
#![deny(missing_debug_implementations)]
mod connection;
mod method;
mod state;
mod status;
mod wire;
pub use connection::Connection;
pub use method::{InvalidMethod, Method};
pub use state::{Role, State};
pub use status::{InvalidStatusCode, StatusCode};
use std::{error::Error as StdError, fmt};
const DEFAULT_MAX_HEAD_BYTES: usize = 64 * 1024;
const DEFAULT_MAX_HEADER_COUNT: usize = 100;
pub type Header = (Vec<u8>, Vec<u8>);
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Version {
Http10,
Http11,
}
impl Version {
pub(crate) const fn wire(self) -> &'static [u8] {
match self {
Self::Http10 => b"1.0",
Self::Http11 => b"1.1",
}
}
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Request {
pub method: Method,
pub target: Vec<u8>,
pub headers: Vec<Header>,
pub http_version: Version,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Response {
pub status: StatusCode,
pub reason: Vec<u8>,
pub headers: Vec<Header>,
pub http_version: Version,
}
pub type InformationalResponse = Response;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Data {
pub data: Vec<u8>,
pub chunk_start: bool,
pub chunk_end: bool,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct DataParts<T> {
pub prefix: Vec<u8>,
pub data: T,
pub suffix: Vec<u8>,
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct EndOfMessage {
pub trailers: Vec<Header>,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Event {
Request(Request),
InformationalResponse(InformationalResponse),
Response(Response),
Data(Data),
EndOfMessage(EndOfMessage),
ConnectionClosed,
}
#[derive(Clone, Debug, Eq, PartialEq)]
pub enum NextEvent {
Event(Event),
NeedData,
Paused,
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Limits {
max_head_bytes: usize,
max_header_count: usize,
}
impl Limits {
pub const fn new(head: usize, headers: usize) -> Result<Self, InvalidLimits> {
if head == 0 || headers == 0 {
Err(InvalidLimits)
} else {
Ok(Self {
max_head_bytes: head,
max_header_count: headers,
})
}
}
}
impl Default for Limits {
fn default() -> Self {
Self {
max_head_bytes: DEFAULT_MAX_HEAD_BYTES,
max_header_count: DEFAULT_MAX_HEADER_COUNT,
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct InvalidLimits;
impl fmt::Display for InvalidLimits {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("HTTP limits must be non-zero")
}
}
impl StdError for InvalidLimits {}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LocalProtocolError(pub(crate) String);
impl fmt::Display for LocalProtocolError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
impl StdError for LocalProtocolError {}
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct RemoteProtocolError {
pub(crate) message: String,
pub(crate) suggested_status_code: Option<u16>,
}
impl RemoteProtocolError {
#[must_use]
pub const fn suggested_status_code(&self) -> Option<u16> {
self.suggested_status_code
}
}
impl fmt::Display for RemoteProtocolError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.message)
}
}
impl StdError for RemoteProtocolError {}