trillium_static_compiled/
encoding.rs1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9pub enum Encoding {
10 Brotli,
12 Zstd,
14 Gzip,
16}
17
18impl Encoding {
19 pub const fn token(self) -> &'static str {
21 match self {
22 Self::Brotli => "br",
23 Self::Zstd => "zstd",
24 Self::Gzip => "gzip",
25 }
26 }
27}
28
29pub(crate) fn accept_encoding_allows(accept: &str, encoding: &str) -> bool {
33 let mut wildcard_ok = false;
34 let mut named_ok = None;
35 for part in accept.split(',') {
36 let mut iter = part.trim().split(';');
37 let token = iter.next().unwrap_or("").trim();
38 let q = iter
39 .find_map(|p| {
40 p.trim()
41 .strip_prefix("q=")
42 .and_then(|q| q.parse::<f32>().ok())
43 })
44 .unwrap_or(1.0);
45 if token.eq_ignore_ascii_case(encoding) {
46 named_ok = Some(q > 0.0);
47 } else if token == "*" && named_ok.is_none() {
48 wildcard_ok = q > 0.0;
49 }
50 }
51 named_ok.unwrap_or(wildcard_ok)
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57
58 #[test]
59 fn token_round_trip() {
60 assert_eq!(Encoding::Brotli.token(), "br");
61 assert_eq!(Encoding::Zstd.token(), "zstd");
62 assert_eq!(Encoding::Gzip.token(), "gzip");
63 }
64
65 #[test]
66 fn accept_encoding_basics() {
67 assert!(accept_encoding_allows("br, gzip", "br"));
68 assert!(accept_encoding_allows("br, gzip", "gzip"));
69 assert!(!accept_encoding_allows("br, gzip", "zstd"));
70 }
71
72 #[test]
73 fn accept_encoding_q_values() {
74 assert!(accept_encoding_allows("br;q=0.5, gzip", "br"));
75 assert!(!accept_encoding_allows("br;q=0, gzip", "br"));
76 assert!(accept_encoding_allows("br;q=0, gzip", "gzip"));
77 }
78
79 #[test]
80 fn accept_encoding_wildcard() {
81 assert!(accept_encoding_allows("*", "br"));
82 assert!(!accept_encoding_allows("*;q=0", "br"));
83 assert!(accept_encoding_allows("*, br;q=0", "gzip"));
84 assert!(!accept_encoding_allows("*, br;q=0", "br"));
85 }
86
87 #[test]
88 fn accept_encoding_case_insensitive() {
89 assert!(accept_encoding_allows("BR, GZIP", "br"));
90 assert!(accept_encoding_allows("Br", "br"));
91 }
92}