Skip to main content

sark_http/h1/head/request/
mod.rs

1//! Request-head semantics bound to the scanned input.
2
3pub mod offers;
4mod parts;
5mod plan;
6pub mod pool;
7mod route;
8pub mod scan;
9pub mod trace;
10
11pub use parts::Parts;
12pub(in crate::h1::head::request) use plan::Kind;
13pub use plan::Plan;
14pub use route::Route;
15
16use crate::{
17    field::head::Name,
18    h1::{
19        field::{self, Connection, Transfer, expect},
20        framing,
21        head::{Semantic, line},
22        switch, target,
23    },
24    payload::response::Method,
25    request::{self, span},
26};
27
28#[derive(Clone, Copy, Default)]
29pub struct Fields {
30    pub message: Message,
31    pub routing: Routing,
32}
33
34impl Fields {
35    fn apply(mut self, field: &field::Entry<'_>, version: line::Version) -> Result<Self, Semantic> {
36        let value = field.value();
37        match field.kind() {
38            Name::ContentLength => {
39                self.message.framing = self
40                    .message
41                    .framing
42                    .try_length(value)
43                    .map_err(Semantic::Field)?;
44            }
45            Name::TransferEncoding => {
46                self.message = self.message.try_coding(value).map_err(Semantic::Field)?;
47            }
48            Name::Host => {
49                self.routing.authority = self
50                    .routing
51                    .authority
52                    .try_host(value)
53                    .map_err(Semantic::Host)?;
54                self.routing.host = Some(field.value_span());
55            }
56            Name::Expect => {
57                self.message = self.message.with_expect(value);
58            }
59            Name::Connection => {
60                self.routing.connection = self
61                    .routing
62                    .connection
63                    .try_push(value)
64                    .map_err(Semantic::Connection)?;
65            }
66            Name::Upgrade => {
67                self.routing = self
68                    .routing
69                    .try_upgrade(value, version)
70                    .map_err(Semantic::Upgrade)?;
71            }
72            Name::Invalid
73            | Name::Method
74            | Name::Scheme
75            | Name::Path
76            | Name::Status
77            | Name::Authority
78            | Name::Protocol
79            | Name::AcceptEncoding
80            | Name::Te
81            | Name::KeepAlive
82            | Name::ProxyConnection
83            | Name::Regular => {}
84        }
85        Ok(self)
86    }
87
88    pub fn admit_target(
89        self,
90        target: target::Target,
91        version: &[u8],
92        policy: target::Policy,
93    ) -> Result<framing::Admission, Semantic> {
94        framing::Admission::admit(
95            self.message.framing,
96            self.routing.authority,
97            self.message.expectation,
98            target,
99            version,
100            policy,
101        )
102        .map_err(Semantic::Admission)
103    }
104
105    pub fn transition(
106        self,
107        method: Method,
108        version: line::Version,
109    ) -> Result<switch::Intent, Semantic> {
110        switch::Intent::from_request(
111            method,
112            self.routing.connection,
113            self.routing.upgrades,
114            version,
115        )
116        .map_err(Semantic::Transition)
117    }
118
119    pub(super) fn admit_parts(
120        self,
121        target: target::Target,
122        range: span::Span,
123        version: line::Version,
124    ) -> Result<(framing::Admission, request::Layout, span::Span), Semantic> {
125        let admit = self.admit_target(target, version.as_bytes(), target::Policy::Require)?;
126        let auth = admit
127            .authority()
128            .span(target, self.routing.host)
129            .map_err(Semantic::Authority)?;
130        let request = target.layout(range, auth).map_err(Semantic::Authority)?;
131        Ok((admit, request, auth))
132    }
133
134    pub(super) const fn connection(self) -> Connection {
135        self.routing.connection
136    }
137
138    pub(super) const fn upgrades(self) -> switch::Offers {
139        self.routing.upgrades
140    }
141}
142
143const _: () = assert!(core::mem::size_of::<Fields>() <= 6 * core::mem::size_of::<usize>());
144
145#[derive(Clone, Copy, Default, PartialEq, Eq)]
146#[repr(u8)]
147pub enum Coding {
148    #[default]
149    Plain,
150    Gzip,
151}
152
153const _: () = assert!(core::mem::size_of::<Coding>() == core::mem::size_of::<bool>());
154
155#[derive(Clone, Copy, Default)]
156pub struct Message {
157    framing: framing::Fields,
158    expectation: expect::State,
159    coding: Coding,
160}
161
162impl Message {
163    pub fn try_length(mut self, length: usize) -> Result<Self, field::Error> {
164        self.framing = self.framing.try_set(length)?;
165        Ok(self)
166    }
167
168    pub fn try_coding(mut self, value: &[u8]) -> Result<Self, field::Error> {
169        self.framing = self.framing.try_coding(value)?;
170        Ok(self)
171    }
172
173    pub fn try_append(mut self, value: Transfer) -> Result<Self, field::Error> {
174        self.framing = self.framing.try_append(value)?;
175        Ok(self)
176    }
177
178    pub fn with_expect(mut self, value: &[u8]) -> Self {
179        self.expectation = self.expectation.push(value);
180        self
181    }
182
183    pub const fn length(self) -> Option<usize> {
184        self.framing.length()
185    }
186
187    pub const fn has_coding(self) -> bool {
188        self.framing.has_coding()
189    }
190
191    pub const fn is_chunked(self) -> bool {
192        self.framing.is_chunked()
193    }
194
195    /// Whether transfer codings remain after removing the final chunked framing.
196    pub const fn has_other_transfer_coding(self) -> bool {
197        self.framing.has_other()
198    }
199
200    pub(crate) fn set_coding(&mut self, coding: Coding) {
201        self.coding = coding;
202    }
203
204    pub const fn coding(self) -> Coding {
205        self.coding
206    }
207}
208
209#[derive(Clone, Copy, Default)]
210pub struct Routing {
211    pub(crate) authority: target::Request,
212    pub(crate) connection: Connection,
213    pub(in crate::h1::head::request) host: Option<span::Span>,
214    pub(in crate::h1::head::request) upgrades: switch::Offers,
215}
216
217impl Routing {
218    pub const fn connection(self) -> Connection {
219        self.connection
220    }
221
222    pub fn try_host(mut self, span: span::Span) -> Result<Self, target::Invalid> {
223        if !self.authority.has_host() || self.host.is_some() {
224            return Err(target::Invalid);
225        }
226        self.host = Some(span);
227        Ok(self)
228    }
229
230    pub const fn host_span(self) -> Option<span::Span> {
231        self.host
232    }
233
234    pub fn try_upgrade(
235        mut self,
236        value: &[u8],
237        version: line::Version,
238    ) -> Result<Self, switch::UpgradeError> {
239        if version == line::Version::Ten {
240            return Ok(self);
241        }
242        let next = self.upgrades.try_push(value)?;
243        self.upgrades = next;
244        Ok(self)
245    }
246}