viceroy_lib/cache/
variance.rs1use std::{collections::HashSet, str::FromStr};
13
14use bytes::{Bytes, BytesMut};
15pub use http::HeaderName;
16use http::{header::InvalidHeaderName, HeaderMap};
17
18use crate::Error;
19
20#[derive(Debug, Clone, PartialEq, Eq, Default)]
27pub struct VaryRule {
28 headers: Vec<HeaderName>,
29}
30
31impl FromStr for VaryRule {
32 type Err = Error;
33
34 fn from_str(s: &str) -> Result<Self, Self::Err> {
35 let headers: Result<Vec<HeaderName>, InvalidHeaderName> =
36 s.split(" ").map(HeaderName::try_from).collect();
37 Ok(VaryRule::new(headers?.iter()))
38 }
39}
40
41impl VaryRule {
42 pub fn new<'a>(headers: impl IntoIterator<Item = &'a HeaderName>) -> VaryRule {
43 let headers: HashSet<HeaderName> = headers.into_iter().cloned().collect();
45 let mut headers: Vec<HeaderName> = headers.into_iter().collect();
46 headers.sort_by(|a, b| a.as_str().cmp(b.as_str()));
47 VaryRule { headers }
48 }
49
50 pub fn variant(&self, headers: &HeaderMap) -> Variant {
53 let mut buf = BytesMut::new();
54 buf.extend_from_slice(format!("[headers: {}]", self.headers.len()).as_bytes());
56
57 for header in self.headers.iter() {
58 buf.extend_from_slice(format!("[header: {}]", header.as_str().len()).as_bytes());
59 buf.extend_from_slice(header.as_str().as_bytes());
60
61 let values = headers.get_all(header);
62 buf.extend_from_slice(format!("[values: {}]", values.iter().count()).as_bytes());
63
64 for value in values.iter() {
65 buf.extend_from_slice(format!("[value: {}]", value.as_bytes().len()).as_bytes());
66 buf.extend_from_slice(value.as_bytes());
67 }
68 }
69 Variant {
70 signature: buf.into(),
71 }
72 }
73}
74
75#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default, Clone)]
80pub struct Variant {
81 signature: Bytes,
85}
86
87#[cfg(test)]
88mod tests {
89 use super::VaryRule;
90
91 #[test]
92 fn vary_rule_uniqe_sorted() {
93 let vary1: VaryRule = "unknown-header Accept content-type".parse().unwrap();
94 let vary2: VaryRule = "content-type unknown-header unknown-header Accept"
95 .parse()
96 .unwrap();
97 assert_eq!(vary1, vary2);
98 }
99}