Skip to content

Commit b68fbe1

Browse files
committed
progress
1 parent c940f57 commit b68fbe1

File tree

6 files changed

+349
-71
lines changed

6 files changed

+349
-71
lines changed

src/cache/cache_control.rs

Lines changed: 0 additions & 70 deletions
This file was deleted.
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
use crate::cache::CacheDirective;
2+
use crate::headers::{HeaderName, HeaderValue, Headers, ToHeaderValues, CACHE_CONTROL};
3+
4+
use std::fmt::{self, Debug, Write};
5+
use std::iter::Iterator;
6+
use std::option;
7+
use std::slice;
8+
9+
/// A Cache-Control header.
10+
pub struct CacheControl {
11+
entries: Vec<CacheDirective>,
12+
}
13+
14+
impl CacheControl {
15+
/// Create a new instance of `ServerTiming`.
16+
pub fn new() -> Self {
17+
Self { entries: vec![] }
18+
}
19+
20+
/// Create a new instance from headers.
21+
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
22+
let mut entries = vec![];
23+
let headers = match headers.as_ref().get(CACHE_CONTROL) {
24+
Some(headers) => headers,
25+
None => return Ok(None),
26+
};
27+
28+
for value in headers {
29+
for part in value.as_str().trim().split(',') {
30+
// Try and parse a directive from a str. If the directive is
31+
// unkown we skip it.
32+
if let Some(entry) = CacheDirective::from_str(part.trim_start())? {
33+
entries.push(entry);
34+
}
35+
}
36+
}
37+
Ok(Some(Self { entries }))
38+
}
39+
40+
/// Sets the `Server-Timing` header.
41+
pub fn apply(&self, mut headers: impl AsMut<Headers>) {
42+
headers.as_mut().insert(CACHE_CONTROL, self.value());
43+
}
44+
45+
/// Get the `HeaderName`.
46+
pub fn name(&self) -> HeaderName {
47+
CACHE_CONTROL
48+
}
49+
50+
/// Get the `HeaderValue`.
51+
pub fn value(&self) -> HeaderValue {
52+
let mut output = String::new();
53+
for (n, timing) in self.entries.iter().enumerate() {
54+
let timing: HeaderValue = timing.clone().into();
55+
match n {
56+
0 => write!(output, "{}", timing).unwrap(),
57+
_ => write!(output, ", {}", timing).unwrap(),
58+
};
59+
}
60+
61+
// SAFETY: the internal string is validated to be ASCII.
62+
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
63+
}
64+
/// Push a directive into the list of entries.
65+
pub fn push(&mut self, directive: CacheDirective) {
66+
self.entries.push(directive);
67+
}
68+
69+
/// An iterator visiting all server entries.
70+
pub fn into_iter(self) -> IntoIter {
71+
IntoIter {
72+
inner: self.entries.into_iter(),
73+
}
74+
}
75+
76+
/// An iterator visiting all server entries.
77+
pub fn iter(&self) -> Iter<'_> {
78+
Iter {
79+
inner: self.entries.iter(),
80+
}
81+
}
82+
83+
/// An iterator visiting all server entries.
84+
pub fn iter_mut(&mut self) -> IterMut<'_> {
85+
IterMut {
86+
inner: self.entries.iter_mut(),
87+
}
88+
}
89+
}
90+
91+
impl IntoIterator for CacheControl {
92+
type Item = CacheDirective;
93+
type IntoIter = IntoIter;
94+
95+
#[inline]
96+
fn into_iter(self) -> Self::IntoIter {
97+
self.into_iter()
98+
}
99+
}
100+
101+
impl<'a> IntoIterator for &'a CacheControl {
102+
type Item = &'a CacheDirective;
103+
type IntoIter = Iter<'a>;
104+
105+
// #[inline]serv
106+
fn into_iter(self) -> Self::IntoIter {
107+
self.iter()
108+
}
109+
}
110+
111+
impl<'a> IntoIterator for &'a mut CacheControl {
112+
type Item = &'a mut CacheDirective;
113+
type IntoIter = IterMut<'a>;
114+
115+
#[inline]
116+
fn into_iter(self) -> Self::IntoIter {
117+
self.iter_mut()
118+
}
119+
}
120+
121+
/// A borrowing iterator over entries in `CacheControl`.
122+
#[derive(Debug)]
123+
pub struct IntoIter {
124+
inner: std::vec::IntoIter<CacheDirective>,
125+
}
126+
127+
impl Iterator for IntoIter {
128+
type Item = CacheDirective;
129+
130+
fn next(&mut self) -> Option<Self::Item> {
131+
self.inner.next()
132+
}
133+
134+
#[inline]
135+
fn size_hint(&self) -> (usize, Option<usize>) {
136+
self.inner.size_hint()
137+
}
138+
}
139+
140+
/// A lending iterator over entries in `CacheControl`.
141+
#[derive(Debug)]
142+
pub struct Iter<'a> {
143+
inner: slice::Iter<'a, CacheDirective>,
144+
}
145+
146+
impl<'a> Iterator for Iter<'a> {
147+
type Item = &'a CacheDirective;
148+
149+
fn next(&mut self) -> Option<Self::Item> {
150+
self.inner.next()
151+
}
152+
153+
#[inline]
154+
fn size_hint(&self) -> (usize, Option<usize>) {
155+
self.inner.size_hint()
156+
}
157+
}
158+
159+
/// A mutable iterator over entries in `CacheControl`.
160+
#[derive(Debug)]
161+
pub struct IterMut<'a> {
162+
inner: slice::IterMut<'a, CacheDirective>,
163+
}
164+
165+
impl<'a> Iterator for IterMut<'a> {
166+
type Item = &'a mut CacheDirective;
167+
168+
fn next(&mut self) -> Option<Self::Item> {
169+
self.inner.next()
170+
}
171+
172+
#[inline]
173+
fn size_hint(&self) -> (usize, Option<usize>) {
174+
self.inner.size_hint()
175+
}
176+
}
177+
178+
impl ToHeaderValues for CacheControl {
179+
type Iter = option::IntoIter<HeaderValue>;
180+
fn to_header_values(&self) -> crate::Result<Self::Iter> {
181+
// A HeaderValue will always convert into itself.
182+
Ok(self.value().to_header_values().unwrap())
183+
}
184+
}
185+
186+
impl Debug for CacheControl {
187+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188+
let mut list = f.debug_list();
189+
for directive in &self.entries {
190+
list.entry(directive);
191+
}
192+
list.finish()
193+
}
194+
}

0 commit comments

Comments
 (0)