1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 /// [Pseudo-Header fields] that may appear in http2 header fields.
15 ///
16 /// [Pseudo-Header fields]: https://httpwg.org/specs/rfc9113.html#PseudoHeaderFields
17 ///
18 /// # Note
19 /// The current structure is not responsible for checking every value.
20 // TODO: 考虑将 PseudoHeaders 拆分成 `RequestPseudo` 和 `ResponsePseudo`.
21 #[derive(Clone, PartialEq, Eq)]
22 pub struct PseudoHeaders {
23     authority: Option<String>,
24     method: Option<String>,
25     path: Option<String>,
26     scheme: Option<String>,
27     status: Option<String>,
28 }
29 
30 // TODO: 去掉冗余的方法。
31 impl PseudoHeaders {
32     /// Create a new `PseudoHeaders`.
new() -> Self33     pub(crate) fn new() -> Self {
34         Self {
35             authority: None,
36             method: None,
37             path: None,
38             scheme: None,
39             status: None,
40         }
41     }
42 
is_empty(&self) -> bool43     pub(crate) fn is_empty(&self) -> bool {
44         self.authority.is_none()
45             && self.method.is_none()
46             && self.path.is_none()
47             && self.scheme.is_none()
48             && self.status.is_none()
49     }
50 
51     /// Check if it contains `Authority`.
contains_authority(&self) -> bool52     pub(crate) fn contains_authority(&self) -> bool {
53         self.authority.is_some()
54     }
55 
56     /// Get the `&str` value of `Authority`.
authority(&self) -> Option<&str>57     pub fn authority(&self) -> Option<&str> {
58         self.authority.as_deref()
59     }
60 
61     /// Set the value of `Authority`.
set_authority(&mut self, authority: Option<String>)62     pub fn set_authority(&mut self, authority: Option<String>) {
63         self.authority = authority;
64     }
65 
66     /// Take the `String` value of `Authority`.
take_authority(&mut self) -> Option<String>67     pub(crate) fn take_authority(&mut self) -> Option<String> {
68         self.authority.take()
69     }
70 
71     /// Check if it contains `Method`.
contains_method(&self) -> bool72     pub(crate) fn contains_method(&self) -> bool {
73         self.method.is_some()
74     }
75 
76     /// Get the `&str` value of `Method`.
method(&self) -> Option<&str>77     pub fn method(&self) -> Option<&str> {
78         self.method.as_deref()
79     }
80 
81     /// Set the value of `Method`.
set_method(&mut self, method: Option<String>)82     pub fn set_method(&mut self, method: Option<String>) {
83         self.method = method;
84     }
85 
86     /// Take the `String` value of `Method`.
take_method(&mut self) -> Option<String>87     pub(crate) fn take_method(&mut self) -> Option<String> {
88         self.method.take()
89     }
90 
91     /// Check if it contains `Path`.
contains_path(&self) -> bool92     pub(crate) fn contains_path(&self) -> bool {
93         self.path.is_some()
94     }
95 
96     /// Get the `&str` value of `Path`.
path(&self) -> Option<&str>97     pub fn path(&self) -> Option<&str> {
98         self.path.as_deref()
99     }
100 
101     /// Set the value of `Path`.
set_path(&mut self, path: Option<String>)102     pub fn set_path(&mut self, path: Option<String>) {
103         self.path = path;
104     }
105 
106     /// Take the `String` value of `Path`.
take_path(&mut self) -> Option<String>107     pub(crate) fn take_path(&mut self) -> Option<String> {
108         self.path.take()
109     }
110 
111     /// Check if it contains `Scheme`.
contains_scheme(&self) -> bool112     pub(crate) fn contains_scheme(&self) -> bool {
113         self.scheme.is_some()
114     }
115 
116     /// Get the `&str` value of `Scheme`.
scheme(&self) -> Option<&str>117     pub fn scheme(&self) -> Option<&str> {
118         self.scheme.as_deref()
119     }
120 
121     /// Set the value of `Scheme`.
set_scheme(&mut self, scheme: Option<String>)122     pub fn set_scheme(&mut self, scheme: Option<String>) {
123         self.scheme = scheme;
124     }
125 
126     /// Take the `String` value of `Scheme`.
take_scheme(&mut self) -> Option<String>127     pub(crate) fn take_scheme(&mut self) -> Option<String> {
128         self.scheme.take()
129     }
130 
131     /// Check if it contains `Status`.
contains_status(&self) -> bool132     pub(crate) fn contains_status(&self) -> bool {
133         self.status.is_some()
134     }
135 
136     /// Get the `&str` value of `Status`.
status(&self) -> Option<&str>137     pub fn status(&self) -> Option<&str> {
138         self.status.as_deref()
139     }
140 
141     /// Set the value of `Status`.
set_status(&mut self, status: Option<String>)142     pub fn set_status(&mut self, status: Option<String>) {
143         self.status = status;
144     }
145 
146     /// Take the `String` value of `Status`.
take_status(&mut self) -> Option<String>147     pub(crate) fn take_status(&mut self) -> Option<String> {
148         self.status.take()
149     }
150 }
151 
152 impl Default for PseudoHeaders {
default() -> Self153     fn default() -> Self {
154         PseudoHeaders::new()
155     }
156 }
157 
158 #[cfg(test)]
159 mod ut_pseudo_headers {
160     use crate::h2::pseudo::PseudoHeaders;
161 
162     /// UT test cases for `PseudoHeaders::new`.
163     ///
164     /// # Brief
165     /// 1. Calls `PseudoHeaders::new` to create a `PseudoHeaders`.
166     /// 2. Checks if the result has a default value.
167     #[test]
ut_pseudo_headers_new()168     fn ut_pseudo_headers_new() {
169         let pseudo = PseudoHeaders::new();
170         assert!(pseudo.authority.is_none());
171         assert!(pseudo.method.is_none());
172         assert!(pseudo.path.is_none());
173         assert!(pseudo.scheme.is_none());
174         assert!(pseudo.status.is_none());
175     }
176 
177     /// UT test cases for `PseudoHeaders::contains_authority`.
178     ///
179     /// # Brief
180     /// 1. Creates a `PseudoHeaders`.
181     /// 2. Calls `PseudoHeaders::contains_authority` of it.
182     /// 3. Calls `PseudoHeaders::contains_authority` of it after its `authority`
183     ///    is set.
184     /// 4. Checks the results.
185     #[test]
ut_pseudo_headers_contains_authority()186     fn ut_pseudo_headers_contains_authority() {
187         let mut pseudo = PseudoHeaders::new();
188         assert!(!pseudo.contains_authority());
189 
190         pseudo.authority = Some(String::from("authority"));
191         assert!(pseudo.contains_authority());
192     }
193 
194     /// UT test cases for `PseudoHeaders::authority`.
195     ///
196     /// # Brief
197     /// 1. Creates a `PseudoHeaders`.
198     /// 2. Calls `PseudoHeaders::authority` of it.
199     /// 3. Calls `PseudoHeaders::authority` of it after its `authority` is set.
200     /// 4. Checks the results.
201     #[test]
ut_pseudo_headers_authority()202     fn ut_pseudo_headers_authority() {
203         let mut pseudo = PseudoHeaders::new();
204         assert!(pseudo.authority().is_none());
205 
206         pseudo.authority = Some(String::from("authority"));
207         assert_eq!(pseudo.authority(), Some("authority"));
208     }
209 
210     /// UT test cases for `PseudoHeaders::set_authority`.
211     ///
212     /// # Brief
213     /// 1. Creates a `PseudoHeaders`.
214     /// 2. Calls `PseudoHeaders::set_authority` of it to set `authority` a
215     ///    value.
216     /// 3. Checks the results.
217     #[test]
ut_pseudo_headers_set_authority()218     fn ut_pseudo_headers_set_authority() {
219         let mut pseudo = PseudoHeaders::new();
220         assert!(pseudo.authority().is_none());
221 
222         pseudo.set_authority(Some(String::from("authority")));
223         assert_eq!(pseudo.authority(), Some("authority"));
224 
225         pseudo.set_authority(None);
226         assert!(pseudo.authority().is_none());
227     }
228 
229     /// UT test cases for `PseudoHeaders::take_authority`.
230     ///
231     /// # Brief
232     /// 1. Creates a `PseudoHeaders`.
233     /// 2. Calls `PseudoHeaders::take_authority` of it.
234     /// 3. Calls `PseudoHeaders::take_authority` of it after its `authority` is
235     ///    set.
236     /// 4. Checks the results.
237     #[test]
ut_pseudo_headers_take_authority()238     fn ut_pseudo_headers_take_authority() {
239         let mut pseudo = PseudoHeaders::new();
240         assert!(pseudo.take_authority().is_none());
241 
242         pseudo.authority = Some(String::from("authority"));
243         assert_eq!(pseudo.take_authority(), Some(String::from("authority")));
244     }
245 
246     /// UT test cases for `PseudoHeaders::contains_method`.
247     ///
248     /// # Brief
249     /// 1. Creates a `PseudoHeaders`.
250     /// 2. Calls `PseudoHeaders::contains_method` of it.
251     /// 3. Calls `PseudoHeaders::contains_method` of it after its `method` is
252     ///    set.
253     /// 4. Checks the results.
254     #[test]
ut_pseudo_headers_contains_method()255     fn ut_pseudo_headers_contains_method() {
256         let mut pseudo = PseudoHeaders::new();
257         assert!(!pseudo.contains_method());
258 
259         pseudo.method = Some(String::from("method"));
260         assert!(pseudo.contains_method());
261     }
262 
263     /// UT test cases for `PseudoHeaders::method`.
264     ///
265     /// # Brief
266     /// 1. Creates a `PseudoHeaders`.
267     /// 2. Calls `PseudoHeaders::method` of it.
268     /// 3. Calls `PseudoHeaders::method` of it after its `method` is set.
269     /// 4. Checks the results.
270     #[test]
ut_pseudo_headers_method()271     fn ut_pseudo_headers_method() {
272         let mut pseudo = PseudoHeaders::new();
273         assert!(pseudo.method().is_none());
274 
275         pseudo.method = Some(String::from("method"));
276         assert_eq!(pseudo.method(), Some("method"));
277     }
278 
279     /// UT test cases for `PseudoHeaders::set_method`.
280     ///
281     /// # Brief
282     /// 1. Creates a `PseudoHeaders`.
283     /// 2. Calls `PseudoHeaders::set_method` of it to set `method` a value.
284     /// 3. Checks the results.
285     #[test]
ut_pseudo_headers_set_method()286     fn ut_pseudo_headers_set_method() {
287         let mut pseudo = PseudoHeaders::new();
288         assert!(pseudo.method().is_none());
289 
290         pseudo.set_method(Some(String::from("method")));
291         assert_eq!(pseudo.method(), Some("method"));
292 
293         pseudo.set_method(None);
294         assert!(pseudo.method().is_none());
295     }
296 
297     /// UT test cases for `PseudoHeaders::take_method`.
298     ///
299     /// # Brief
300     /// 1. Creates a `PseudoHeaders`.
301     /// 2. Calls `PseudoHeaders::take_method` of it.
302     /// 3. Calls `PseudoHeaders::take_method` of it after its `method` is set.
303     /// 4. Checks the results.
304     #[test]
ut_pseudo_headers_take_method()305     fn ut_pseudo_headers_take_method() {
306         let mut pseudo = PseudoHeaders::new();
307         assert!(pseudo.take_method().is_none());
308 
309         pseudo.method = Some(String::from("method"));
310         assert_eq!(pseudo.take_method(), Some(String::from("method")));
311     }
312 
313     /// UT test cases for `PseudoHeaders::contains_path`.
314     ///
315     /// # Brief
316     /// 1. Creates a `PseudoHeaders`.
317     /// 2. Calls `PseudoHeaders::contains_path` of it.
318     /// 3. Calls `PseudoHeaders::contains_path` of it after its `path` is set.
319     /// 4. Checks the results.
320     #[test]
ut_pseudo_headers_contains_path()321     fn ut_pseudo_headers_contains_path() {
322         let mut pseudo = PseudoHeaders::new();
323         assert!(!pseudo.contains_path());
324 
325         pseudo.path = Some(String::from("path"));
326         assert!(pseudo.contains_path());
327     }
328 
329     /// UT test cases for `PseudoHeaders::path`.
330     ///
331     /// # Brief
332     /// 1. Creates a `PseudoHeaders`.
333     /// 2. Calls `PseudoHeaders::path` of it.
334     /// 3. Calls `PseudoHeaders::path` of it after its `path` is set.
335     /// 4. Checks the results.
336     #[test]
ut_pseudo_headers_path()337     fn ut_pseudo_headers_path() {
338         let mut pseudo = PseudoHeaders::new();
339         assert!(pseudo.path().is_none());
340 
341         pseudo.path = Some(String::from("path"));
342         assert_eq!(pseudo.path(), Some("path"));
343     }
344 
345     /// UT test cases for `PseudoHeaders::set_path`.
346     ///
347     /// # Brief
348     /// 1. Creates a `PseudoHeaders`.
349     /// 2. Calls `PseudoHeaders::set_path` of it to set `path` a value.
350     /// 3. Checks the results.
351     #[test]
ut_pseudo_headers_set_path()352     fn ut_pseudo_headers_set_path() {
353         let mut pseudo = PseudoHeaders::new();
354         assert!(pseudo.path().is_none());
355 
356         pseudo.set_path(Some(String::from("path")));
357         assert_eq!(pseudo.path(), Some("path"));
358 
359         pseudo.set_path(None);
360         assert!(pseudo.path().is_none());
361     }
362 
363     /// UT test cases for `PseudoHeaders::take_path`.
364     ///
365     /// # Brief
366     /// 1. Creates a `PseudoHeaders`.
367     /// 2. Calls `PseudoHeaders::take_path` of it.
368     /// 3. Calls `PseudoHeaders::take_path` of it after its `path` is set.
369     /// 4. Checks the results.
370     #[test]
ut_pseudo_headers_take_path()371     fn ut_pseudo_headers_take_path() {
372         let mut pseudo = PseudoHeaders::new();
373         assert!(pseudo.take_path().is_none());
374 
375         pseudo.path = Some(String::from("path"));
376         assert_eq!(pseudo.take_path(), Some(String::from("path")));
377     }
378 
379     /// UT test cases for `PseudoHeaders::contains_scheme`.
380     ///
381     /// # Brief
382     /// 1. Creates a `PseudoHeaders`.
383     /// 2. Calls `PseudoHeaders::contains_scheme` of it.
384     /// 3. Calls `PseudoHeaders::contains_scheme` of it after its `scheme` is
385     ///    set.
386     /// 4. Checks the results.
387     #[test]
ut_pseudo_headers_contains_scheme()388     fn ut_pseudo_headers_contains_scheme() {
389         let mut pseudo = PseudoHeaders::new();
390         assert!(!pseudo.contains_scheme());
391 
392         pseudo.scheme = Some(String::from("scheme"));
393         assert!(pseudo.contains_scheme());
394     }
395 
396     /// UT test cases for `PseudoHeaders::scheme`.
397     ///
398     /// # Brief
399     /// 1. Creates a `PseudoHeaders`.
400     /// 2. Calls `PseudoHeaders::scheme` of it.
401     /// 3. Calls `PseudoHeaders::scheme` of it after its `scheme` is set.
402     /// 4. Checks the results.
403     #[test]
ut_pseudo_headers_scheme()404     fn ut_pseudo_headers_scheme() {
405         let mut pseudo = PseudoHeaders::new();
406         assert!(pseudo.scheme().is_none());
407 
408         pseudo.scheme = Some(String::from("scheme"));
409         assert_eq!(pseudo.scheme(), Some("scheme"));
410     }
411 
412     /// UT test cases for `PseudoHeaders::set_scheme`.
413     ///
414     /// # Brief
415     /// 1. Creates a `PseudoHeaders`.
416     /// 2. Calls `PseudoHeaders::set_scheme` of it to set `scheme` a value.
417     /// 3. Checks the results.
418     #[test]
ut_pseudo_headers_set_scheme()419     fn ut_pseudo_headers_set_scheme() {
420         let mut pseudo = PseudoHeaders::new();
421         assert!(pseudo.scheme().is_none());
422 
423         pseudo.set_scheme(Some(String::from("scheme")));
424         assert_eq!(pseudo.scheme(), Some("scheme"));
425 
426         pseudo.set_scheme(None);
427         assert!(pseudo.scheme().is_none());
428     }
429 
430     /// UT test cases for `PseudoHeaders::take_scheme`.
431     ///
432     /// # Brief
433     /// 1. Creates a `PseudoHeaders`.
434     /// 2. Calls `PseudoHeaders::take_scheme` of it.
435     /// 3. Calls `PseudoHeaders::take_scheme` of it after its `scheme` is set.
436     /// 4. Checks the results.
437     #[test]
ut_pseudo_headers_take_scheme()438     fn ut_pseudo_headers_take_scheme() {
439         let mut pseudo = PseudoHeaders::new();
440         assert!(pseudo.take_scheme().is_none());
441 
442         pseudo.scheme = Some(String::from("scheme"));
443         assert_eq!(pseudo.take_scheme(), Some(String::from("scheme")));
444     }
445 
446     /// UT test cases for `PseudoHeaders::contains_status`.
447     ///
448     /// # Brief
449     /// 1. Creates a `PseudoHeaders`.
450     /// 2. Calls `PseudoHeaders::contains_status` of it.
451     /// 3. Calls `PseudoHeaders::contains_status` of it after its `status` is
452     ///    set.
453     /// 4. Checks the results.
454     #[test]
ut_pseudo_headers_contains_status()455     fn ut_pseudo_headers_contains_status() {
456         let mut pseudo = PseudoHeaders::new();
457         assert!(!pseudo.contains_status());
458 
459         pseudo.status = Some(String::from("status"));
460         assert!(pseudo.contains_status());
461     }
462 
463     /// UT test cases for `PseudoHeaders::status`.
464     ///
465     /// # Brief
466     /// 1. Creates a `PseudoHeaders`.
467     /// 2. Calls `PseudoHeaders::status` of it.
468     /// 3. Calls `PseudoHeaders::status` of it after its `status` is set.
469     /// 4. Checks the results.
470     #[test]
ut_pseudo_headers_status()471     fn ut_pseudo_headers_status() {
472         let mut pseudo = PseudoHeaders::new();
473         assert!(pseudo.status().is_none());
474 
475         pseudo.status = Some(String::from("status"));
476         assert_eq!(pseudo.status(), Some("status"));
477     }
478 
479     /// UT test cases for `PseudoHeaders::set_status`.
480     ///
481     /// # Brief
482     /// 1. Creates a `PseudoHeaders`.
483     /// 2. Calls `PseudoHeaders::set_status` of it to set `status` a value.
484     /// 3. Checks the results.
485     #[test]
ut_pseudo_headers_set_status()486     fn ut_pseudo_headers_set_status() {
487         let mut pseudo = PseudoHeaders::new();
488         assert!(pseudo.status().is_none());
489 
490         pseudo.set_status(Some(String::from("status")));
491         assert_eq!(pseudo.status(), Some("status"));
492 
493         pseudo.set_status(None);
494         assert!(pseudo.status().is_none());
495     }
496 
497     /// UT test cases for `PseudoHeaders::take_status`.
498     ///
499     /// # Brief
500     /// 1. Creates a `PseudoHeaders`.
501     /// 2. Calls `PseudoHeaders::take_status` of it.
502     /// 3. Calls `PseudoHeaders::take_status` of it after its `status` is set.
503     /// 4. Checks the results.
504     #[test]
ut_pseudo_headers_take_status()505     fn ut_pseudo_headers_take_status() {
506         let mut pseudo = PseudoHeaders::new();
507         assert!(pseudo.take_status().is_none());
508 
509         pseudo.status = Some(String::from("status"));
510         assert_eq!(pseudo.take_status(), Some(String::from("status")));
511     }
512 }
513