1use crate::{Error, Result, SlicePos, State, Status, iter::Bytes, simd, utils};
2
3#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
5pub struct Header {
6 pub name: SlicePos,
10 pub value: SlicePos,
15}
16
17#[derive(Copy, Clone, Debug, PartialEq, Eq)]
19pub enum HeaderParsed {
20 Header(usize),
21 Eof(usize),
22}
23
24impl Header {
25 pub fn parse(&mut self, src: &[u8]) -> Result<HeaderParsed> {
42 let mut st = State::default();
43 let mut bytes = Bytes::new(src, &mut st);
44 parse_header_iter_uninit(&mut bytes, self)
45 }
46
47 pub fn parse_with_state(&mut self, src: &[u8], st: &mut State) -> Result<HeaderParsed> {
48 parse_header_iter_uninit(&mut Bytes::new(src, st), self)
49 }
50}
51
52fn parse_header_iter_uninit(
53 bytes: &mut Bytes<'_, '_>,
54 header: &mut Header,
55) -> Result<HeaderParsed> {
56 if bytes.st.state == 0 {
58 let b = next!(bytes);
60 if b == b'\r' {
61 expect!(bytes.next() == b'\n' => Err(Error::NewLine));
62 return Ok(Status::Complete(HeaderParsed::Eof(
63 bytes.cursor() - bytes.start(),
64 )));
65 } else if b == b'\n' {
66 return Ok(Status::Complete(HeaderParsed::Eof(
67 bytes.cursor() - bytes.start(),
68 )));
69 } else if !utils::is_header_name_token(b) {
70 return Err(Error::HeaderName);
71 }
72 bytes.st.state = 1;
73 header.name.start = bytes.cursor() - 1;
74 }
75
76 if bytes.st.state == 1 {
78 simd::match_header_name_vectored(bytes);
79 if next!(bytes) == b':' {
80 bytes.st.state = 2;
82 header.name.end = bytes.cursor() - 1;
83 } else {
84 return Err(Error::HeaderName);
85 }
86 }
87
88 let mut b;
89
90 if bytes.st.state == 2 {
92 'whitespace_after_colon: loop {
94 b = next!(bytes);
95 if b == b' ' || b == b'\t' {
96 continue 'whitespace_after_colon;
97 }
98 if utils::is_header_value_token(b) {
99 bytes.st.state = 3;
100 header.value.start = bytes.cursor() - 1;
101 break 'whitespace_after_colon;
102 }
103
104 if b == b'\r' {
105 expect!(bytes.next() == b'\n' => Err(Error::HeaderValue));
106 } else if b != b'\n' {
107 return Err(Error::HeaderValue);
108 }
109
110 header.value.reset();
113 bytes.st.state = 0;
114 bytes.commit();
115 return Ok(Status::Complete(HeaderParsed::Header(bytes.cursor())));
116 }
117 }
118
119 if bytes.st.state == 3 {
121 {
123 simd::match_header_value_vectored(bytes);
124
125 let b = next!(bytes);
127 if b == b'\r' {
128 expect!(bytes.next() == b'\n' => Err(Error::HeaderValue));
129 } else if b != b'\n' {
130 return Err(Error::HeaderValue);
131 }
132
133 let mut n = 1; while let Some(b) = bytes.peek_behind(n) {
136 if matches!(b, b' ' | b'\t' | b'\r' | b'\n') {
137 n += 1;
138 } else {
139 break;
140 }
141 }
142
143 header.value.end = bytes.cursor() - n + 1;
144 }
145 }
146 bytes.st.state = 0;
147 bytes.commit();
148
149 Ok(Status::Complete(HeaderParsed::Header(bytes.cursor())))
150}