use std::time::Duration;
#[derive(Debug, Clone)]
pub struct CacheControlValue {
max_age: Option<Duration>,
must_revalidate: Option<bool>,
visibility: Option<CacheVisibility>,
}
impl CacheControlValue {
pub fn new() -> Self {
Self {
max_age: None,
must_revalidate: None,
visibility: None,
}
}
pub fn max_age(mut self, max_age: Duration) -> Self {
self.max_age = Some(max_age);
self
}
pub fn must_revalidate(mut self) -> Self {
self.must_revalidate = Some(true);
self
}
pub fn public(mut self) -> Self {
self.visibility = Some(CacheVisibility::Public);
self
}
#[allow(dead_code)]
pub fn private(mut self) -> Self {
self.visibility = Some(CacheVisibility::Private);
self
}
}
#[allow(clippy::to_string_trait_impl)]
impl ToString for CacheControlValue {
fn to_string(&self) -> String {
let mut v = Vec::new();
if let Some(visibility) = &self.visibility {
v.push(visibility.to_string());
}
if let Some(max_age) = &self.max_age {
v.push(format!("max-age={}", max_age.as_secs()));
}
if let Some(true) = &self.must_revalidate {
v.push("must-revalidate".to_string());
}
if v.is_empty() {
v.push("no-cache".to_string());
}
let s = v.join(", ");
s
}
}
#[derive(Debug, Clone)]
pub enum CacheVisibility {
Public,
Private,
}
#[allow(clippy::to_string_trait_impl)]
impl ToString for CacheVisibility {
fn to_string(&self) -> String {
match self {
CacheVisibility::Public => "public".to_string(),
CacheVisibility::Private => "private".to_string(),
}
}
}
#[cfg(test)]
mod test {
use std::time::Duration;
use crate::cache_control::CacheControlValue;
#[test]
fn cache_control_correct_concat() {
let cc = CacheControlValue::new().max_age(Duration::from_secs(1000));
assert_eq!("max-age=1000", &cc.to_string());
let cc = cc.must_revalidate();
assert_eq!("max-age=1000, must-revalidate", &cc.to_string());
let cc = cc.public();
assert_eq!("public, max-age=1000, must-revalidate", &cc.to_string());
let cc = cc.private();
assert_eq!("private, max-age=1000, must-revalidate", &cc.to_string());
}
}