Files
cow-mail/src/headers.rs
T
2024-06-16 01:48:33 +02:00

119 lines
4.0 KiB
Rust

use crate::header::{Header, parse_header};
pub trait HeaderMap<'a, H: Header<'a>> {
fn get_all_headers(&self, key: &str) -> Vec<&H>;
fn get_all_headers_mut(&mut self, key: &str) -> Vec<&mut H>;
fn get_first_header(&self, key: &str) -> Option<&H>;
fn get_first_header_mut(&mut self, key: &str) -> Option<&mut H>;
fn get_all_values(&self, key: &str) -> Vec<String>;
fn get_first_value(&self, key: &str) -> Option<String>;
fn add_header<K: ToString, V: ToString>(&mut self, key: K, value: V);
fn insert_header<K: ToString, V: ToString>(&mut self, key: K, value: V, index: usize);
fn replace_header<K: ToString, V: ToString>(&mut self, key: K, value: V, index: usize);
fn replace_all_headers<K: ToString, V: ToString>(&mut self, key: K, value: V);
fn remove_header(&mut self, key: &str, index: usize);
fn remove_all_headers(&mut self, key: &str);
}
impl<'a, H: Header<'a>> HeaderMap<'a, H> for Vec<H> {
fn get_all_headers(&self, key: &str) -> Vec<&H> {
self.iter().filter(|h| h.get_key().eq_ignore_ascii_case(key)).collect()
}
fn get_all_headers_mut(&mut self, key: &str) -> Vec<&mut H> {
self.iter_mut()
.filter(|h| h.get_key().eq_ignore_ascii_case(key))
.collect()
}
fn get_first_header(&self, key: &str) -> Option<&H> {
self.iter().find(|h| h.get_key().eq_ignore_ascii_case(key))
}
fn get_first_header_mut(&mut self, key: &str) -> Option<&mut H> {
self.iter_mut().find(|h| h.get_key().eq_ignore_ascii_case(key))
}
fn get_all_values(&self, key: &str) -> Vec<String> {
self.get_all_headers(key).into_iter().map(|h| h.get_value()).collect()
}
fn get_first_value(&self, key: &str) -> Option<String> {
self.get_first_header(key).map(|h| h.get_value())
}
fn add_header<K: ToString, V: ToString>(&mut self, key: K, value: V) {
self.push(H::new(key, value))
}
fn insert_header<K: ToString, V: ToString>(&mut self, key: K, value: V, index: usize) {
let index = std::cmp::min(index, self.len());
let header = H::new(key, value);
self.insert(index, header);
}
fn replace_all_headers<K: ToString, V: ToString>(&mut self, key: K, value: V) {
let key = key.to_string();
for header in self {
if !header.get_key().eq_ignore_ascii_case(&key) {
continue;
}
header.set_value(value.to_string());
}
}
fn replace_header<K: ToString, V: ToString>(&mut self, key: K, value: V, index: usize) {
let key = key.to_string();
let mut count: usize = 0;
for header in self {
if !header.get_key().eq_ignore_ascii_case(&key) {
continue;
}
if count == index {
header.set_value(value);
break;
}
count += 1;
}
}
fn remove_all_headers(&mut self, key: &str) {
self.retain(|h| !h.get_key().eq_ignore_ascii_case(key));
}
fn remove_header(&mut self, key: &str, index: usize) {
if let Some((index, _)) = self
.iter()
.enumerate()
.filter(move |h| h.1.get_key().eq_ignore_ascii_case(key))
.nth(index)
{
self.remove(index);
}
}
}
pub fn parse_headers<'a, H: Header<'a>>(raw_data: &'a [u8]) -> Result<(Vec<H>, usize), &'static str> {
let mut headers: Vec<H> = Vec::new();
let mut ix = 0;
loop {
if ix >= raw_data.len() {
break;
} else if raw_data[ix] == b'\n' {
ix += 1;
break;
} else if raw_data[ix] == b'\r' {
if ix + 1 < raw_data.len() && raw_data[ix + 1] == b'\n' {
ix += 2;
break;
} else {
return Err("Headers were followed by an unexpected lone CR character!");
}
}
let (header, ix_next) = parse_header(&raw_data[ix..]).unwrap();
headers.push(header);
ix += ix_next;
}
Ok((headers, ix))
}