Skip to main content

sark_http/h1/codec/decode/request/
head.rs

1use core::convert::Infallible;
2use std::num::NonZero;
3
4use crate::h1::{
5    codec::decode::fields,
6    field, framing,
7    head::{Limit, ParseError, line, request},
8};
9
10/// Complete request head borrowing the exact scanned wire owner.
11pub struct Head<'input, F> {
12    pub method: &'input [u8],
13    pub target: &'input [u8],
14    pub version: u8,
15    pub admission: framing::Admission,
16    pub connection: field::Connection,
17    pub fields: F,
18    pub header_len: NonZero<u32>,
19}
20
21impl<'input> Head<'input, ()> {
22    pub fn scan(input: &'input [u8], bound: usize) -> Result<Option<Self>, ParseError<Infallible>> {
23        let Some(plan) = request::Parts::scan(input, Limit::DEFAULT.with_bytes(bound))? else {
24            return Ok(None);
25        };
26        Ok(Some(Self::from(plan, ())))
27    }
28}
29
30impl<'input, F: fields::Sink<'input>> Head<'input, F> {
31    pub fn parse(
32        input: &'input [u8],
33        bound: usize,
34        mut fields: F,
35    ) -> Result<Option<Self>, ParseError<F::Error>> {
36        let Some(plan) = request::Parts::parse(input, Limit::DEFAULT.with_bytes(bound), |field| {
37            fields.entry(field)
38        })?
39        else {
40            return Ok(None);
41        };
42        Ok(Some(Self::from(plan, fields)))
43    }
44}
45
46impl<'input, F> Head<'input, F> {
47    fn from(plan: request::Parts<&'input [u8]>, fields: F) -> Self {
48        let (method, target) = plan.line();
49        let version = match plan.version() {
50            line::Version::Ten => 0,
51            line::Version::Eleven => 1,
52        };
53        Self {
54            method,
55            target,
56            version,
57            admission: plan.admission(),
58            connection: plan.connection(),
59            fields,
60            header_len: plan.wire_len(),
61        }
62    }
63}