1
+ //! Client header advertising available compression algorithms.
2
+
1
3
use crate :: content:: EncodingProposal ;
2
4
use crate :: headers:: { HeaderName , HeaderValue , Headers , ToHeaderValues , ACCEPT_ENCODING } ;
3
5
4
- use std:: fmt:: { self , Debug } ;
6
+ use std:: fmt:: { self , Debug , Write } ;
5
7
use std:: option;
6
8
use std:: slice;
7
9
8
- /// An Accept-Encoding header.
10
+ /// Client header advertising available compression algorithms .
9
11
pub struct AcceptEncoding {
12
+ wildcard : bool ,
10
13
entries : Vec < EncodingProposal > ,
11
14
}
12
15
13
16
impl AcceptEncoding {
14
17
/// Create a new instance of `AcceptEncoding`.
15
18
pub fn new ( ) -> Self {
16
- Self { entries : vec ! [ ] }
19
+ Self {
20
+ entries : vec ! [ ] ,
21
+ wildcard : false ,
22
+ }
17
23
}
18
24
19
25
/// Create an instance of `AcceptEncoding` from a `Headers` instance.
@@ -24,8 +30,20 @@ impl AcceptEncoding {
24
30
None => return Ok ( None ) ,
25
31
} ;
26
32
33
+ let mut wildcard = false ;
34
+
27
35
for value in headers {
28
36
for part in value. as_str ( ) . trim ( ) . split ( ',' ) {
37
+ let part = part. trim ( ) ;
38
+
39
+ // Handle empty strings, and wildcard directives.
40
+ if part. is_empty ( ) {
41
+ continue ;
42
+ } else if part == "*" {
43
+ wildcard = true ;
44
+ continue ;
45
+ }
46
+
29
47
// Try and parse a directive from a str. If the directive is
30
48
// unkown we skip it.
31
49
if let Some ( entry) = EncodingProposal :: from_str ( part) ? {
@@ -34,12 +52,22 @@ impl AcceptEncoding {
34
52
}
35
53
}
36
54
37
- Ok ( Some ( Self { entries } ) )
55
+ Ok ( Some ( Self { entries, wildcard } ) )
38
56
}
39
57
40
58
/// Push a directive into the list of entries.
41
- pub fn push ( & mut self , prop : EncodingProposal ) {
42
- self . entries . push ( prop) ;
59
+ pub fn push ( & mut self , prop : impl Into < EncodingProposal > ) {
60
+ self . entries . push ( prop. into ( ) ) ;
61
+ }
62
+
63
+ /// Returns `true` if a wildcard directive was passed.
64
+ pub fn wildcard ( & self ) -> bool {
65
+ self . wildcard
66
+ }
67
+
68
+ /// Set the wildcard directive.
69
+ pub fn set_wildcard ( & mut self , wildcard : bool ) {
70
+ self . wildcard = wildcard
43
71
}
44
72
45
73
/// Insert a `HeaderName` + `HeaderValue` pair into a `Headers` instance.
@@ -54,7 +82,17 @@ impl AcceptEncoding {
54
82
55
83
/// Get the `HeaderValue`.
56
84
pub fn value ( & self ) -> HeaderValue {
57
- todo ! ( ) ;
85
+ let mut output = String :: new ( ) ;
86
+ for ( n, directive) in self . entries . iter ( ) . enumerate ( ) {
87
+ let directive: HeaderValue = directive. clone ( ) . into ( ) ;
88
+ match n {
89
+ 0 => write ! ( output, "{}" , directive) . unwrap ( ) ,
90
+ _ => write ! ( output, ", {}" , directive) . unwrap ( ) ,
91
+ } ;
92
+ }
93
+
94
+ // SAFETY: the internal string is validated to be ASCII.
95
+ unsafe { HeaderValue :: from_bytes_unchecked ( output. into ( ) ) }
58
96
}
59
97
60
98
/// An iterator visiting all entries.
@@ -178,3 +216,24 @@ impl Debug for AcceptEncoding {
178
216
list. finish ( )
179
217
}
180
218
}
219
+
220
+ #[ cfg( test) ]
221
+ mod test {
222
+ use super :: * ;
223
+ use crate :: content:: Encoding ;
224
+ use crate :: Response ;
225
+
226
+ #[ test]
227
+ fn smoke ( ) -> crate :: Result < ( ) > {
228
+ let mut accept = AcceptEncoding :: new ( ) ;
229
+ accept. push ( Encoding :: Gzip ) ;
230
+
231
+ let mut headers = Response :: new ( 200 ) ;
232
+ accept. apply ( & mut headers) ;
233
+
234
+ let accept = AcceptEncoding :: from_headers ( headers) ?. unwrap ( ) ;
235
+ let mut accept = accept. iter ( ) ;
236
+ assert_eq ! ( accept. next( ) . unwrap( ) , Encoding :: Gzip ) ;
237
+ Ok ( ( ) )
238
+ }
239
+ }
0 commit comments