use crate::{
error::Result,
helpers::{
self, BufReadExt, SliceU8Ext,
MatchConfig::{ Required, Trim }
}
};
use std::{
collections::BTreeMap, iter::FromIterator, ops::Deref,
io::{ BufRead, Write }
};
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct Header {
start_line: HeaderStartLine,
fields: HeaderFields
}
impl Header {
pub const fn new(start_line: HeaderStartLine, fields: HeaderFields) -> Self {
Self { start_line, fields }
}
pub fn start_line(&self) -> &HeaderStartLine {
&self.start_line
}
pub fn start_line_mut(&mut self) -> &mut HeaderStartLine {
&mut self.start_line
}
pub fn fields(&self) -> &HeaderFields {
&self.fields
}
pub fn fields_mut(&mut self) -> &mut HeaderFields {
&mut self.fields
}
pub fn read<T>(source: &mut T) -> Result<Self> where T: BufRead {
let header = source.read_word("\r\n\r\n", [Required])?;
let mut header = helpers::memreader(header);
let start_line = HeaderStartLine::read(&mut header)?;
let fields = HeaderFields::read(&mut header)?;
Ok(Self { start_line, fields })
}
pub fn write_all(&self, output: &mut dyn Write) -> Result {
self.start_line.write_all(output)?;
self.fields.write_all(output)?;
output.flush()?;
Ok(())
}
}
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct HeaderStartLine {
field0: Vec<u8>,
field1: Vec<u8>,
field2: Vec<u8>,
}
impl HeaderStartLine {
pub fn new_request<T, U>(method: T, target: U) -> Self where T: Into<Vec<u8>>, U: Into<Vec<u8>> {
Self {
field0: method.into(),
field1: target.into(),
field2: "HTTP/1.1".into()
}
}
pub fn new_response<T>(status: u16, reason: T) -> Self where T: Into<Vec<u8>> {
Self {
field0: "HTTP/1.1".into(),
field1: status.to_string().into(),
field2: reason.into()
}
}
pub fn request_method(&self) -> &[u8] {
&self.field0
}
pub fn request_method_mut(&mut self) -> &mut Vec<u8> {
&mut self.field0
}
pub fn request_target(&self) -> &[u8] {
&self.field1
}
pub fn request_target_mut(&mut self) -> &mut Vec<u8> {
&mut self.field1
}
pub fn response_binstatus(&self) -> &[u8] {
&self.field1
}
pub fn response_binstatus_mut(&mut self) -> &mut Vec<u8> {
&mut self.field1
}
pub fn response_reason(&self) -> &[u8] {
&self.field2
}
pub fn response_reason_mut(&mut self) -> &mut Vec<u8> {
&mut self.field2
}
pub fn read<T>(source: &mut T) -> Result<Self> where T: BufRead {
let line = source.read_word("\r\n", [Required, Trim])?;
let mut line = helpers::memreader(line);
let this = Self {
field0: line.read_word(" ", [Required, Trim])?,
field1: line.read_word(" ", [Required, Trim])?,
field2: line.read_all([Required])?
};
Ok(this)
}
pub fn write_all(&self, output: &mut dyn Write) -> Result {
output.write_all(&self.field0)?;
output.write_all(b" ")?;
output.write_all(&self.field1)?;
output.write_all(b" ")?;
output.write_all(&self.field2)?;
output.write_all(b"\r\n")?;
Ok(())
}
}
#[derive(Debug, Default, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct HeaderFields {
fields: BTreeMap<Vec<u8>, Vec<u8>>
}
impl HeaderFields {
pub fn new() -> Self {
Self { fields: BTreeMap::new() }
}
pub fn get<T>(&self, name: T) -> Option<&[u8]> where T: AsRef<[u8]> {
let name = name.as_ascii_lowercase();
self.fields.get(name.as_ref()).map(|s| s.as_ref())
}
pub fn set<A, B>(&mut self, name: A, value: B) where A: AsRef<[u8]>, B: Into<Vec<u8>> {
let name = name.as_ascii_lowercase();
self.fields.insert(name.into(), value.into());
}
pub fn read<T>(source: &mut T) -> Result<Self> where T: BufRead {
let mut this = HeaderFields::new();
'read_lines: loop {
let mut line = match source.read_word("\r\n", [Required, Trim])? {
line if line.is_empty() => break 'read_lines,
line => helpers::memreader(line)
};
let key = line.read_word(":", [Required, Trim])?;
let value = line.read_all([Required])?;
let leading_whitespace = value.iter().take_while(|b| **b == b' ').count();
let value = &value[leading_whitespace..];
this.set(key, value);
}
Ok(this)
}
pub fn write_all(&self, output: &mut dyn Write) -> Result {
for (key, value) in self.fields.iter() {
output.write_all(key)?;
output.write_all(b": ")?;
output.write_all(value)?;
output.write_all(b"\r\n")?;
}
output.write_all(b"\r\n")?;
Ok(())
}
}
impl Deref for HeaderFields {
type Target = BTreeMap<Vec<u8>, Vec<u8>>;
fn deref(&self) -> &Self::Target {
&self.fields
}
}
impl<K, V> FromIterator<(K, V)> for HeaderFields where K: Into<Vec<u8>>, V: Into<Vec<u8>> {
fn from_iter<T: IntoIterator<Item = (K, V)>>(pairs: T) -> Self {
let fields = pairs.into_iter()
.map(|(k, v)| (k.into(), v.into()))
.map(|(k, v)| (k.to_ascii_lowercase(), v))
.collect();
Self { fields }
}
}
impl IntoIterator for HeaderFields {
type Item = <BTreeMap<Vec<u8>, Vec<u8>> as IntoIterator>::Item;
type IntoIter = <BTreeMap<Vec<u8>, Vec<u8>> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.fields.into_iter()
}
}