capybara_core/protocol/http/frame/
status_line.rs1use 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}