1use core::{marker, mem, num, ops::ControlFlow, ptr, slice};
2
3use scan::state;
4
5mod axis;
6pub mod ban;
7mod error;
8mod limit;
9pub(in crate::h1) mod scan;
10mod size;
11mod syntax;
12pub(in crate::h1) mod trailer;
13
14pub use axis::Axis;
15pub use error::Error;
16pub use limit::Limit;
17pub use syntax::Syntax;
18
19#[derive(Clone, Copy, PartialEq, Eq)]
20#[repr(u8)]
21pub enum Boundary {
22 More,
23 End,
24}
25
26#[derive(Clone, Copy, PartialEq, Eq)]
27pub enum Fragment<'input> {
28 More(usize),
29 Data {
30 consumed: num::NonZero<usize>,
31 bytes: &'input [u8],
32 boundary: Boundary,
33 },
34 Trailer(num::NonZero<usize>),
35 Complete {
36 consumed: num::NonZero<usize>,
37 bytes: &'input [u8],
41 },
42}
43
44#[derive(Clone, Copy, PartialEq, Eq)]
45enum Active {
46 Size(size::Size),
47 SizeLf(size::Size),
48 Data(num::NonZero<usize>),
49 DataCr,
50 DataLf,
51 Trailer(state::State),
52}
53
54#[derive(Clone, Copy, PartialEq, Eq)]
55pub struct Framer {
56 phase: ControlFlow<num::NonZero<u32>, Active>,
57 wire_bytes: usize,
58 body_bytes: usize,
59}
60
61impl Default for Framer {
62 fn default() -> Self {
63 Self::new()
64 }
65}
66
67impl Framer {
68 pub const fn new() -> Self {
69 Self {
70 phase: ControlFlow::Continue(Active::Size(size::Size::new())),
71 wire_bytes: 0,
72 body_bytes: 0,
73 }
74 }
75
76 pub const fn wire_bytes(&self) -> usize {
77 self.wire_bytes
78 }
79
80 pub const fn body_bytes(&self) -> usize {
81 self.body_bytes
82 }
83
84 pub fn trailer_bytes(&self) -> Option<num::NonZero<u32>> {
86 self.phase.break_value()
87 }
88
89 pub fn reset(&mut self) {
90 *self = Self::new();
91 }
92
93 pub fn scan<'input>(
94 &mut self,
95 input: &'input [u8],
96 limits: &Limit,
97 ) -> Result<Run<'input>, Error> {
98 let (next, run) = (*self).prepare::<scan::Whole>(input, limits, usize::MAX)?;
99 *self = next;
100 Ok(run)
101 }
102
103 pub fn decode<'input>(
104 self,
105 input: &'input [u8],
106 limits: &Limit,
107 data: usize,
108 ) -> Result<(Self, Fragment<'input>), Error> {
109 let (next, output) = self.prepare::<scan::Fragments>(input, limits, data)?;
110 Ok((next, output.fragment()))
111 }
112
113 pub(in crate::h1) fn prepare<'input, M: scan::Mode>(
114 self,
115 input: &'input [u8],
116 limits: &Limit,
117 data: usize,
118 ) -> Result<(Self, M::Output<'input>), Error> {
119 let ControlFlow::Continue(active) = self.phase else {
120 return Ok((self, M::finished(input)));
121 };
122 self.drive::<M>(active, input, limits, data)
123 }
124
125 fn drive<'input, M: scan::Mode>(
126 mut self,
127 mut active: Active,
128 input: &'input [u8],
129 limits: &Limit,
130 data: usize,
131 ) -> Result<(Self, M::Output<'input>), Error> {
132 let mut pos = 0usize;
133 while let Some(&byte) = input.get(pos) {
134 match active {
135 Active::Size(size) => {
136 let offset = self.wire_bytes;
137 let wire = Self::wire(self.wire_bytes, 1, limits)?;
138 let (size, progress) = size.scan(byte, offset, limits.line_bytes)?;
139 self.wire_bytes = wire;
140 pos += 1;
141 active = if progress == size::Progress::Complete {
142 Active::SizeLf(size)
143 } else {
144 Active::Size(size)
145 };
146 }
147 Active::SizeLf(size) => {
148 let offset = self.wire_bytes;
149 let wire = Self::wire(self.wire_bytes, 1, limits)?;
150 let size = size.finish(byte, offset, limits.line_bytes)?;
151 let (body, next) = Self::check_size(self.body_bytes, size.value(), limits)?;
152 self.wire_bytes = wire;
153 self.body_bytes = body;
154 pos += 1;
155 active = next;
156 }
157 Active::Data(left) => {
158 let tail = &input[pos..];
159 let Some(amount) = num::NonZero::new(left.get().min(tail.len()).min(data))
160 else {
161 break;
162 };
163 self.wire_bytes = Self::wire(self.wire_bytes, amount.get(), limits)?;
164 let bytes = &tail[..amount.get()];
165 let consumed = amount.saturating_add(pos);
166 pos = consumed.get();
167 let boundary = match num::NonZero::new(left.get() - amount.get()) {
168 Some(left) => {
169 active = Active::Data(left);
170 Boundary::More
171 }
172 None => {
173 active = Active::DataCr;
174 Boundary::End
175 }
176 };
177 if let Some(output) = M::data(consumed, bytes, boundary) {
178 self.phase = ControlFlow::Continue(active);
179 return Ok((self, output));
180 }
181 }
182 Active::DataCr => {
183 self.wire_bytes =
184 Self::exact(self.wire_bytes, byte, b'\r', Syntax::DataCr, limits)?;
185 pos += 1;
186 active = Active::DataLf;
187 }
188 Active::DataLf => {
189 self.wire_bytes =
190 Self::exact(self.wire_bytes, byte, b'\n', Syntax::DataLf, limits)?;
191 pos += 1;
192 active = Active::Size(size::Size::default());
193 }
194 Active::Trailer(state) => {
195 let mut trailer = trailer::Trailer::new(state, self.wire_bytes, *limits);
196 let (progress, bytes) = trailer.scan(&input[pos..])?;
197 match progress {
198 trailer::Progress::More { next, consumed } => {
199 self.wire_bytes = next.wire;
200 self.phase = ControlFlow::Continue(Active::Trailer(next.state));
201 trailer.cursor = next;
202 let output = match consumed {
203 Some(consumed) => {
204 M::trailer(input, consumed.saturating_add(pos), bytes, trailer)
205 }
206 None => M::pending(input, pos),
207 };
208 return Ok((self, output));
209 }
210 trailer::Progress::Complete {
211 wire,
212 consumed,
213 trailers,
214 } => {
215 self.wire_bytes = wire;
216 self.phase = ControlFlow::Break(trailers);
217 return Ok((
218 self,
219 M::complete(input, consumed.saturating_add(pos), bytes),
220 ));
221 }
222 }
223 }
224 }
225 }
226
227 self.phase = ControlFlow::Continue(active);
228 Ok((self, M::pending(input, pos)))
229 }
230
231 fn wire(current: usize, amount: usize, limits: &Limit) -> Result<usize, Error> {
232 let actual = current.checked_add(amount).ok_or(Error::Overflow {
233 axis: Axis::Wire,
234 value: current,
235 added: amount,
236 })?;
237 if actual > limits.wire_bytes {
238 return Err(Error::Limit {
239 axis: Axis::Wire,
240 actual,
241 maximum: limits.wire_bytes,
242 });
243 }
244 Ok(actual)
245 }
246
247 fn exact(
248 wire: usize,
249 byte: u8,
250 expected: u8,
251 syntax: Syntax,
252 limits: &Limit,
253 ) -> Result<usize, Error> {
254 let offset = wire;
255 let actual = Self::wire(wire, 1, limits)?;
256 if byte == expected {
257 Ok(actual)
258 } else {
259 Err(Error::Syntax {
260 offset,
261 syntax,
262 actual: byte,
263 })
264 }
265 }
266
267 fn check_size(current: usize, size: usize, limits: &Limit) -> Result<(usize, Active), Error> {
268 let total = current.checked_add(size).ok_or(Error::Overflow {
269 axis: Axis::Body,
270 value: current,
271 added: size,
272 })?;
273 if total > limits.body_bytes {
274 return Err(Error::Limit {
275 axis: Axis::Body,
276 actual: total,
277 maximum: limits.body_bytes,
278 });
279 }
280 let active = match num::NonZero::new(size) {
281 Some(size) => Active::Data(size),
282 None => Active::Trailer(state::State::new()),
283 };
284 Ok((total, active))
285 }
286}
287
288const _: () = {
289 assert!(mem::size_of::<Boundary>() == mem::size_of::<bool>());
290 assert!(mem::align_of::<Boundary>() == mem::align_of::<bool>());
291 assert!(mem::size_of::<Framer>() <= 6 * mem::size_of::<usize>());
292 assert!(!mem::needs_drop::<Framer>());
293};
294
295#[must_use]
296pub struct Run<'input> {
297 source: ptr::NonNull<u8>,
298 state: usize,
299 borrow: marker::PhantomData<&'input [u8]>,
300}
301
302impl<'input> Run<'input> {
303 const COMPLETE: usize = 1 << (usize::BITS - 1);
304
305 pub(in crate::h1::chunk) fn pending(input: &'input [u8], scanned: usize) -> Self {
308 Self {
309 source: ptr::NonNull::from(input).cast(),
310 state: scanned,
311 borrow: marker::PhantomData,
312 }
313 }
314
315 pub(in crate::h1::chunk) fn complete(input: &'input [u8], scanned: usize) -> Self {
318 Self {
319 source: ptr::NonNull::from(input).cast(),
320 state: scanned | Self::COMPLETE,
321 borrow: marker::PhantomData,
322 }
323 }
324
325 pub const fn is_complete(self) -> bool {
326 self.state & Self::COMPLETE != 0
327 }
328
329 pub const fn into_slice(self) -> &'input [u8] {
330 let len = self.state & !Self::COMPLETE;
331 unsafe { slice::from_raw_parts(self.source.as_ptr(), len) }
335 }
336}
337
338const _: () = {
339 assert!(mem::size_of::<Run<'static>>() == 2 * mem::size_of::<usize>());
340 assert!(mem::align_of::<Run<'static>>() == mem::align_of::<usize>());
341 assert!(!mem::needs_drop::<Run<'static>>());
342};