use headers::Header;
use crate::headers::{HeaderName, HeaderValue, Headers, CACHE_CONTROL};
use crate::{cache::CacheDirective, headers};
use std::fmt::{self, Debug, Write};
use std::iter::Iterator;
use std::slice;
pub struct CacheControl {
entries: Vec<CacheDirective>,
}
impl CacheControl {
pub fn new() -> Self {
Self { entries: vec![] }
}
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
let mut entries = vec![];
let headers = match headers.as_ref().get(CACHE_CONTROL) {
Some(headers) => headers,
None => return Ok(None),
};
for value in headers {
for part in value.as_str().trim().split(',') {
if let Some(entry) = CacheDirective::from_str(part)? {
entries.push(entry);
}
}
}
Ok(Some(Self { entries }))
}
pub fn push(&mut self, directive: CacheDirective) {
self.entries.push(directive);
}
pub fn iter(&self) -> Iter<'_> {
Iter {
inner: self.entries.iter(),
}
}
pub fn iter_mut(&mut self) -> IterMut<'_> {
IterMut {
inner: self.entries.iter_mut(),
}
}
}
impl Header for CacheControl {
fn header_name(&self) -> HeaderName {
CACHE_CONTROL
}
fn header_value(&self) -> HeaderValue {
let mut output = String::new();
for (n, directive) in self.entries.iter().enumerate() {
let directive: HeaderValue = directive.clone().into();
match n {
0 => write!(output, "{}", directive).unwrap(),
_ => write!(output, ", {}", directive).unwrap(),
};
}
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
}
}
impl IntoIterator for CacheControl {
type Item = CacheDirective;
type IntoIter = IntoIter;
#[inline]
fn into_iter(self) -> Self::IntoIter {
IntoIter {
inner: self.entries.into_iter(),
}
}
}
impl<'a> IntoIterator for &'a CacheControl {
type Item = &'a CacheDirective;
type IntoIter = Iter<'a>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> IntoIterator for &'a mut CacheControl {
type Item = &'a mut CacheDirective;
type IntoIter = IterMut<'a>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
#[derive(Debug)]
pub struct IntoIter {
inner: std::vec::IntoIter<CacheDirective>,
}
impl Iterator for IntoIter {
type Item = CacheDirective;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
#[derive(Debug)]
pub struct Iter<'a> {
inner: slice::Iter<'a, CacheDirective>,
}
impl<'a> Iterator for Iter<'a> {
type Item = &'a CacheDirective;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
#[derive(Debug)]
pub struct IterMut<'a> {
inner: slice::IterMut<'a, CacheDirective>,
}
impl<'a> Iterator for IterMut<'a> {
type Item = &'a mut CacheDirective;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
impl Debug for CacheControl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut list = f.debug_list();
for directive in &self.entries {
list.entry(directive);
}
list.finish()
}
}