kutil_http/cache/key/
common.rs1use super::{
2 super::{
3 super::{headers::*, uri::*},
4 weight::*,
5 },
6 key::*,
7};
8
9use {
10 bytes::*,
11 bytestring::*,
12 http::{header::*, uri::*, *},
13 std::{collections::*, fmt, hash::*},
14};
15
16#[derive(Clone, Debug, Eq, Hash, PartialEq)]
22pub struct CommonCacheKey {
23 pub method: Method,
25
26 pub path: Option<ByteString>,
28
29 pub query: Option<BTreeMap<ByteString, ByteString>>,
31
32 pub scheme: Option<Scheme>,
36
37 pub host: Option<ByteString>,
41
42 pub port: Option<u16>,
46
47 pub media_type: Option<MediaType>,
51
52 pub languages: Option<BTreeSet<Language>>,
56
57 pub extensions: Option<BTreeMap<Bytes, Bytes>>,
61}
62
63impl CommonCacheKey {
64 pub fn new(
66 method: Method,
67 path: Option<ByteString>,
68 query: Option<BTreeMap<ByteString, ByteString>>,
69 scheme: Option<Scheme>,
70 host: Option<ByteString>,
71 port: Option<u16>,
72 media_type: Option<MediaType>,
73 languages: Option<BTreeSet<Language>>,
74 extensions: Option<BTreeMap<Bytes, Bytes>>,
75 ) -> Self {
76 Self { method, scheme, host, port, path, query, media_type, languages, extensions }
77 }
78}
79
80impl CacheKey for CommonCacheKey {
81 fn for_request(method: &Method, uri: &Uri, _headers: &HeaderMap) -> Self {
82 let (path, query) = match uri.path_and_query() {
83 Some(path_and_query) => (Some(path_and_query.path().into()), path_and_query.decoded_query_map()),
84 None => (None, None),
85 };
86
87 Self::new(method.clone(), path, query, None, None, None, None, None, None)
88 }
89}
90
91impl CacheWeight for CommonCacheKey {
92 fn cache_weight(&self) -> usize {
93 const SELF_SIZE: usize = size_of::<CommonCacheKey>();
94
95 let mut size = SELF_SIZE;
96
97 if let Some(host) = &self.host {
98 size += host.len();
99 }
100
101 if let Some(path) = &self.path {
102 size += path.len();
103 }
104
105 if let Some(query) = &self.query {
106 for (k, v) in query {
107 size += k.len() + v.len();
108 }
109 }
110
111 if let Some(media_type) = &self.media_type {
112 size += media_type.cache_weight();
113 }
114
115 if let Some(languages) = &self.languages {
116 for language in languages {
117 size += language.cache_weight();
118 }
119 }
120
121 if let Some(extensions) = &self.extensions {
122 for (k, v) in extensions {
123 size += k.len() + v.len();
124 }
125 }
126
127 size
128 }
129}
130
131impl fmt::Display for CommonCacheKey {
132 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
133 let scheme = self.scheme.as_ref().map(|scheme| scheme.as_str()).unwrap_or_default();
134 let host = self.host.as_ref().map(|host| AsRef::<str>::as_ref(host)).unwrap_or_default();
135 let port = self.port.map(|port| port.to_string()).unwrap_or_default();
136 let path = self.path.as_ref().map(|path| AsRef::<str>::as_ref(path)).unwrap_or_default();
137
138 let query = self
139 .query
140 .as_ref()
141 .map(|parameter| {
142 let mut string = String::new();
143 for (k, v) in parameter {
144 if !string.is_empty() {
145 string += "&"
146 }
147 string += &format!("{}={}", k, v);
148 }
149 string
150 })
151 .unwrap_or_default();
152
153 let media_type = self.media_type.as_ref().map(|media_type| media_type.to_string()).unwrap_or_default();
154
155 let languages = self
156 .languages
157 .as_ref()
158 .map(|languages| {
159 let languages: Vec<_> = languages.iter().map(|language| language.to_string()).collect();
160 languages.join(",")
161 })
162 .unwrap_or_default();
163
164 let extensions = self
165 .extensions
166 .as_ref()
167 .map(|extension| {
168 let mut string = String::new();
169 for (k, v) in extension {
170 if !string.is_empty() {
171 string += "&"
172 }
173 string += &format!("{}={}", k.len(), v.len());
175 }
176 string
177 })
178 .unwrap_or_default();
179
180 write!(
181 formatter,
182 "{}|{}|{}|{}|{}|{}|{}|{}|{}",
183 self.method, scheme, host, port, path, query, media_type, languages, extensions
184 )
185 }
186}