1use core::mem;
2
3use crate::{
4 field::{
5 head::{Error, Flags, Name, parse},
6 text::Ascii,
7 },
8 h1::{
9 field,
10 head::{line::Version, request},
11 },
12};
13
14#[derive(Clone, Copy, PartialEq, Eq)]
15pub enum Known {
16 AcceptEncoding,
17 ContentLength,
18 TransferEncoding,
19 Expect,
20 Host,
21 Connection,
22 Upgrade,
23}
24
25#[derive(Clone, Copy, PartialEq, Eq)]
26pub struct Bounds {
27 tail: usize,
28 start: usize,
29 end: usize,
30}
31
32impl Bounds {
33 pub(super) const fn new(tail: usize, start: usize, end: usize) -> Self {
34 Self { tail, start, end }
35 }
36
37 pub const fn tail(self) -> usize {
38 self.tail
39 }
40
41 pub const fn start(self) -> usize {
42 self.start
43 }
44
45 pub const fn end(self) -> usize {
46 self.end
47 }
48
49 pub(super) fn value(self, raw: &[u8]) -> &[u8] {
50 unsafe { raw.get_unchecked(self.start..self.end) }
53 }
54}
55
56const _: () = {
57 assert!(mem::size_of::<Bounds>() == 3 * mem::size_of::<usize>());
58 assert!(mem::size_of::<Option<Bounds>>() == 4 * mem::size_of::<usize>());
59 assert!(!mem::needs_drop::<Bounds>());
60};
61
62fn parse_connection(raw: &[u8]) -> Result<field::Connection, Error> {
63 field::Connection::default()
64 .try_push(raw)
65 .map_err(Error::Connection)
66}
67
68impl Known {
69 const PREFIX_INITIALS: u32 = {
70 let mut initials = 0;
71 let mut index = 0;
72 while index < Name::H1.len() {
73 let first = Name::H1[index].wire()[0];
74 assert!(first.is_ascii_lowercase(), "initial");
75 initials |= 1 << (first - b'a');
76 index += 1;
77 }
78 initials
79 };
80
81 pub fn from_name(name: &[u8]) -> Option<Self> {
82 Self::from_kind(Name::from_h1(name)?)
83 }
84
85 pub fn from_prefix(raw: &[u8]) -> Option<(Self, usize)> {
88 let first = raw.first()?.to_ascii_lowercase();
89 let initial = 1u32.checked_shl(u32::from(first.wrapping_sub(b'a')))?;
90 if Self::PREFIX_INITIALS & initial == 0 {
91 return None;
92 }
93 for name in Name::H1 {
94 let wire = name.wire();
95 if wire.first() == Some(&first)
96 && raw.get(wire.len()) == Some(&b':')
97 && raw[..wire.len()].eq_ignore_ascii_case(wire)
98 {
99 return Self::from_kind(name).map(|known| (known, wire.len()));
100 }
101 }
102 None
103 }
104
105 fn from_kind(name: Name) -> Option<Self> {
106 match name {
107 Name::AcceptEncoding => Some(Self::AcceptEncoding),
108 Name::ContentLength => Some(Self::ContentLength),
109 Name::TransferEncoding => Some(Self::TransferEncoding),
110 Name::Expect => Some(Self::Expect),
111 Name::Host => Some(Self::Host),
112 Name::Connection => Some(Self::Connection),
113 Name::Upgrade => Some(Self::Upgrade),
114 Name::Invalid
115 | Name::Method
116 | Name::Scheme
117 | Name::Path
118 | Name::Status
119 | Name::Authority
120 | Name::Protocol
121 | Name::Te
122 | Name::KeepAlive
123 | Name::ProxyConnection
124 | Name::Regular => None,
125 }
126 }
127
128 pub fn apply(
129 self,
130 scan: &mut request::Fields,
131 flags: &mut Flags,
132 value: &[u8],
133 version: Version,
134 ) -> Result<(), Error> {
135 match self {
136 Self::AcceptEncoding => parse::ae_value(scan, flags, value),
137 Self::ContentLength => {
138 let len = Ascii::new(crate::field::Error::trim_ows(value))
139 .parse_usize()
140 .map_err(Error::ContentLength)?;
141 scan.message = scan.message.try_length(len).map_err(Error::Message)?;
142 Ok(())
143 }
144 Self::TransferEncoding => {
145 let parsed = field::Transfer::default()
146 .parse(value)
147 .map_err(Error::TransferEncoding)?;
148 scan.message = scan.message.try_append(parsed).map_err(Error::Message)?;
149 Ok(())
150 }
151 Self::Expect => {
152 scan.message = scan.message.with_expect(value);
153 Ok(())
154 }
155 Self::Host => {
156 scan.routing.authority = scan
157 .routing
158 .authority
159 .try_host(value)
160 .map_err(Error::Host)?;
161 Ok(())
162 }
163 Self::Connection => {
164 let value = parse_connection(value)?;
165 scan.routing.connection.append(value);
166 Ok(())
167 }
168 Self::Upgrade => {
169 scan.routing = scan
170 .routing
171 .try_upgrade(value, version)
172 .map_err(Error::Upgrade)?;
173 Ok(())
174 }
175 }
176 }
177
178 pub fn scan_line(
179 self,
180 scan: &mut request::Fields,
181 flags: &mut Flags,
182 raw: &[u8],
183 version: Version,
184 ) -> Result<Option<Bounds>, Error> {
185 match self {
186 Self::AcceptEncoding => parse::ae_line(scan, flags, raw),
187 Self::ContentLength => parse::clen_line(scan, raw),
188 Self::TransferEncoding => parse::te_line(scan, raw),
189 Self::Expect => expect_line(scan, raw),
190 Self::Host => host_line(scan, raw),
191 Self::Connection => conn_line(scan, raw),
192 Self::Upgrade => upgrade_line(scan, raw, version),
193 }
194 }
195}
196
197fn host_line(scan: &mut request::Fields, raw: &[u8]) -> Result<Option<Bounds>, Error> {
198 let Some(bounds) = parse::trim_line(raw)? else {
199 return Ok(None);
200 };
201 scan.routing.authority = scan
202 .routing
203 .authority
204 .try_host(bounds.value(raw))
205 .map_err(Error::Host)?;
206 Ok(Some(bounds))
207}
208
209fn upgrade_line(
210 scan: &mut request::Fields,
211 raw: &[u8],
212 version: Version,
213) -> Result<Option<Bounds>, Error> {
214 let Some(bounds) = parse::trim_line(raw)? else {
215 return Ok(None);
216 };
217 scan.routing = scan
218 .routing
219 .try_upgrade(bounds.value(raw), version)
220 .map_err(Error::Upgrade)?;
221 Ok(Some(bounds))
222}
223
224fn expect_line(scan: &mut request::Fields, raw: &[u8]) -> Result<Option<Bounds>, Error> {
225 let (bounds, value) = match parse::try_token_line_lit(raw, b"100-continue") {
226 Some(bounds) => (bounds, b"100-continue".as_slice()),
227 None => {
228 let Some(bounds) = parse::trim_line(raw)? else {
229 return Ok(None);
230 };
231 (bounds, bounds.value(raw))
232 }
233 };
234 scan.message = scan.message.with_expect(value);
235 Ok(Some(bounds))
236}
237
238fn conn_line(scan: &mut request::Fields, raw: &[u8]) -> Result<Option<Bounds>, Error> {
239 let (value, bounds) = if let Some(bounds) = parse::try_token_line_lit(raw, b"keep-alive") {
240 (field::Connection::KEEP_ALIVE, bounds)
241 } else if let Some(bounds) = parse::try_token_line_lit(raw, b"close") {
242 (field::Connection::CLOSE, bounds)
243 } else {
244 let Some(bounds) = parse::trim_line(raw)? else {
245 return Ok(None);
246 };
247 let value = parse_connection(bounds.value(raw))?;
248 (value, bounds)
249 };
250 scan.routing.connection.append(value);
251 Ok(Some(bounds))
252}