use std::fmt;
use super::component::{Header, Status};
mod conversion;
mod error;
mod extension;
mod headers;
pub use conversion::IntoResponse;
pub use error::{Error, Result};
pub use extension::ResponseExt;
pub use headers::Headers;
#[derive(Clone, Debug)]
pub struct Response {
pub status: Status,
pub headers: Headers,
pub body: Vec<u8>,
}
impl Response {
#[inline]
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn into_bytes(self) -> Vec<u8> {
let capacity = (8 + 2)
+ 4 + 32 + 2 + self.headers.len() * 64 + 2 + self.body.len();
let mut buffer = Vec::with_capacity(capacity);
buffer.extend_from_slice(b"HTTP/1.1 ");
buffer.extend_from_slice(self.status.to_string().as_bytes());
buffer.extend_from_slice(b"\r\n");
for (header, value) in &self.headers {
buffer.extend_from_slice(header.name().as_bytes());
buffer.extend_from_slice(b": ");
buffer.extend_from_slice(value.as_bytes());
buffer.extend_from_slice(b"\r\n");
}
buffer.extend_from_slice(b"\r\n");
if !self.body.is_empty() {
buffer.extend_from_slice(&self.body);
}
buffer
}
}
impl Response {
#[inline]
#[must_use]
pub fn status(mut self, status: Status) -> Self {
self.status = status;
self
}
#[inline]
#[must_use]
pub fn header<V>(mut self, header: Header, value: V) -> Self
where
V: ToString,
{
self.headers.put(header, value);
self
}
#[inline]
#[must_use]
pub fn body<B>(mut self, body: B) -> Self
where
B: Into<Vec<u8>>,
{
self.body = body.into();
self
}
}
impl Default for Response {
#[inline]
fn default() -> Self {
Self {
status: Status::Ok,
headers: Headers::default(),
body: Vec::default(),
}
}
}
impl fmt::Display for Response {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "HTTP/1.1 {}\r\n", self.status)?;
write!(f, "{}\r\n", self.headers)?;
write!(f, "[Body: {} bytes]\r\n", self.body.len())
}
}