use super::{super::weight::*, key::*};
use {
http::{header::*, uri::*, *},
kutil::{http::*, std::immutable::*},
std::{collections::*, fmt, hash::*},
};
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct CommonCacheKey {
pub method: Method,
pub path: Option<ImmutableString>,
pub query: Option<QueryMap>,
pub scheme: Option<Scheme>,
pub host: Option<ImmutableString>,
pub port: Option<u16>,
pub media_type: Option<MediaType>,
pub languages: Option<BTreeSet<Language>>,
pub extensions: Option<BTreeMap<ImmutableBytes, ImmutableBytes>>,
}
impl CommonCacheKey {
pub fn new(
method: Method,
path: Option<ImmutableString>,
query: Option<QueryMap>,
scheme: Option<Scheme>,
host: Option<ImmutableString>,
port: Option<u16>,
media_type: Option<MediaType>,
languages: Option<BTreeSet<Language>>,
extensions: Option<BTreeMap<ImmutableBytes, ImmutableBytes>>,
) -> Self {
Self {
method,
scheme,
host,
port,
path,
query,
media_type,
languages,
extensions,
}
}
}
impl CacheKey for CommonCacheKey {
fn for_request(method: &Method, uri: &Uri, _headers: &HeaderMap) -> Self {
let (path, query) = uri
.path_and_query()
.map(|path_and_query| {
(
Some(path_and_query.path().into()),
path_and_query.decoded_query_map(),
)
})
.unwrap_or_default();
Self::new(
method.clone(),
path,
query,
None,
None,
None,
None,
None,
None,
)
}
}
impl CacheWeight for CommonCacheKey {
fn cache_weight(&self) -> usize {
const SELF_SIZE: usize = size_of::<CommonCacheKey>();
let mut size = SELF_SIZE;
if let Some(host) = &self.host {
size += host.len();
}
if let Some(path) = &self.path {
size += path.len();
}
if let Some(query) = &self.query {
for (k, v) in query {
size += k.len() + v.len();
}
}
if let Some(media_type) = &self.media_type {
size += media_type.cache_weight();
}
if let Some(languages) = &self.languages {
for language in languages {
size += language.cache_weight();
}
}
if let Some(extensions) = &self.extensions {
for (k, v) in extensions {
size += k.len() + v.len();
}
}
size
}
}
impl fmt::Display for CommonCacheKey {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let scheme = self
.scheme
.as_ref()
.map(|scheme| scheme.as_str())
.unwrap_or_default();
let host = self
.host
.as_ref()
.map(|host| AsRef::<str>::as_ref(host))
.unwrap_or_default();
let port = self.port.map(|port| port.to_string()).unwrap_or_default();
let path = self
.path
.as_ref()
.map(|path| AsRef::<str>::as_ref(path))
.unwrap_or_default();
let query = self
.query
.as_ref()
.map(|parameter| {
let mut string = String::default();
for (key, values) in parameter {
for value in values {
if !string.is_empty() {
string += "&"
}
string += &format!("{}={}", key, value);
}
}
string
})
.unwrap_or_default();
let media_type = self
.media_type
.as_ref()
.map(|media_type| media_type.to_string())
.unwrap_or_default();
let languages = self
.languages
.as_ref()
.map(|languages| {
let languages: Vec<_> = languages
.iter()
.map(|language| language.to_string())
.collect();
languages.join(",")
})
.unwrap_or_default();
let extensions = self
.extensions
.as_ref()
.map(|extension| {
let mut string = String::default();
for (key, value) in extension {
if !string.is_empty() {
string += "&"
}
string += &format!("{}={}", key.len(), value.len());
}
string
})
.unwrap_or_default();
write!(
formatter,
"{}|{}|{}|{}|{}|{}|{}|{}|{}",
self.method, scheme, host, port, path, query, media_type, languages, extensions
)
}
}