Skip to main content

capybara_core/protocol/http/frame/
status_line.rs

1use std::borrow::Cow;
2
3use bytes::{Bytes, BytesMut};
4
5use crate::protocol::http::misc;
6use crate::Result;
7
8#[derive(Debug, Clone, PartialEq)]
9pub struct StatusLine(pub(crate) Bytes);
10
11impl StatusLine {
12    #[inline]
13    pub fn read(buf: &mut BytesMut) -> Result<Option<StatusLine>> {
14        Ok(misc::readline(buf).map(StatusLine))
15    }
16
17    pub fn status_code(&self) -> u16 {
18        let mut code = 0;
19
20        for (i, v) in self.0[..].split(misc::is_space).enumerate() {
21            if i == 1 {
22                code = std::str::from_utf8(v).unwrap().parse::<u16>().unwrap();
23                break;
24            }
25        }
26        code
27    }
28
29    pub fn reason_phrase(&self) -> Cow<str> {
30        let pos = self.0.iter().rposition(|b| *b == b' ').unwrap();
31        String::from_utf8_lossy(&self.0[pos + 1..self.0.len() - 2])
32    }
33
34    pub fn version(&self) -> Cow<str> {
35        self.0
36            .split(misc::is_space)
37            .next()
38            .map(String::from_utf8_lossy)
39            .unwrap()
40    }
41}
42
43impl Into<Bytes> for StatusLine {
44    fn into(self) -> Bytes {
45        self.0
46    }
47}
48
49#[cfg(test)]
50mod status_line_tests {
51    use super::*;
52
53    fn init() {
54        pretty_env_logger::try_init_timed().ok();
55    }
56
57    #[test]
58    fn test_http_status_line() {
59        init();
60
61        let status_line = b"HTTP/1.1 200 OK\r\nHos";
62
63        let mut b = BytesMut::from(&status_line[..]);
64        let status_line = StatusLine::read(&mut b);
65        assert_eq!(3, b.len());
66        assert!(
67            status_line.as_ref().is_ok_and(|it| it.is_some()),
68            "should parse status line!"
69        );
70
71        let l = status_line.unwrap().unwrap();
72        assert_eq!("HTTP/1.1", l.version());
73        assert_eq!(200, l.status_code());
74        assert_eq!("OK", l.reason_phrase());
75    }
76}