Skip to main content

sark_http/field/
mod.rs

1#[doc(hidden)]
2pub mod base64;
3pub mod date;
4pub mod head;
5pub mod metadata;
6pub mod raw;
7pub mod scan;
8pub mod storage;
9pub mod text;
10
11use std::{convert::Infallible, iter::Copied, slice};
12
13pub use storage::{Lower, Name, Value};
14
15/// Requires successful field admission at compile time.
16/// Invalid input fails during constant evaluation.
17#[macro_export]
18macro_rules! field_literal {
19    ($value:expr $(,)?) => {
20        const {
21            match $value {
22                ::core::result::Result::Ok(value) => value,
23                ::core::result::Result::Err(_) => ::core::panic!("literal"),
24            }
25        }
26    };
27}
28
29use metadata::map::record;
30use storage::encoded;
31
32pub use crate::field_literal as literal;
33use crate::payload::response::status;
34
35#[derive(Clone, Copy, Debug, PartialEq, Eq)]
36pub enum Error {
37    Empty,
38    InvalidByte { index: usize, byte: u8 },
39}
40
41/// Compression permission retained with one HTTP field line.
42#[repr(u8)]
43#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
44pub enum Indexing {
45    #[default]
46    Allowed,
47    Never,
48}
49
50impl Indexing {
51    pub(in crate::field) const fn from_byte(value: u8) -> Option<Self> {
52        match value {
53            0 => Some(Self::Allowed),
54            1 => Some(Self::Never),
55            _ => None,
56        }
57    }
58
59    pub(in crate::field) const fn from_never(never: bool) -> Self {
60        if never { Self::Never } else { Self::Allowed }
61    }
62}
63
64/// Writes one generated field value into its protocol encoder.
65pub trait Writer {
66    fn write_byte(&mut self, byte: u8);
67
68    fn write_slice(&mut self, bytes: &[u8]);
69}
70
71/// A generated field value with an exact encoded length.
72pub trait Encode: encoded::Encoded {
73    fn encoded_len(&self) -> usize;
74
75    /// Stops at the first rejected fragment and preserves its exact error.
76    fn try_write<E>(self, emit: impl FnMut(&[u8]) -> Result<(), E>) -> Result<(), E>;
77
78    fn encode(self, out: &mut impl Writer)
79    where
80        Self: Sized,
81    {
82        match self.try_write(|bytes| {
83            out.write_slice(bytes);
84            Ok::<_, Infallible>(())
85        }) {
86            Ok(()) => {}
87            Err(never) => match never {},
88        }
89    }
90}
91
92/// Receives one synchronous semantic field plan without staging storage.
93pub trait Sink<'field> {
94    fn entry(&mut self, field: Entry<'field>);
95
96    /// Emits a preencoded group while retaining each field's indexing policy.
97    fn group(&mut self, group: &Group<'field>) {
98        for entry in group.entries() {
99            self.entry(*entry);
100        }
101    }
102
103    fn field(&mut self, name: Lower<&'field [u8]>, value: Value<&'field [u8]>) {
104        self.entry(Entry::new(name, value));
105    }
106
107    fn encoded_with<E: Encode>(&mut self, name: Lower<&'field [u8]>, value: E, indexing: Indexing);
108
109    /// Emits a newly generated value with indexing permitted.
110    fn generated<E: Encode>(&mut self, name: Lower<&'field [u8]>, value: E) {
111        self.encoded_with(name, value, Indexing::Allowed);
112    }
113}
114
115/// Borrows and synchronously emits one semantic field plan.
116pub trait Source {
117    fn emit<'field>(&'field self, sink: &mut impl Sink<'field>);
118}
119
120/// Borrows the exact bytes of a typed outgoing field value.
121pub trait AsValue {
122    fn as_value(&self) -> Value<&[u8]>;
123}
124
125impl<T: storage::Bytes> AsValue for Value<T> {
126    fn as_value(&self) -> Value<&[u8]> {
127        Value(self.0.as_bytes())
128    }
129}
130
131impl<T: storage::Bytes> Encode for Value<T> {
132    fn encoded_len(&self) -> usize {
133        self.as_bytes().len()
134    }
135
136    fn try_write<E>(self, mut emit: impl FnMut(&[u8]) -> Result<(), E>) -> Result<(), E> {
137        let Self(owner) = self;
138        emit(owner.as_bytes())
139    }
140}
141
142impl<W: Writer + ?Sized> Writer for &mut W {
143    fn write_byte(&mut self, byte: u8) {
144        (**self).write_byte(byte);
145    }
146
147    fn write_slice(&mut self, bytes: &[u8]) {
148        (**self).write_slice(bytes);
149    }
150}
151
152impl<S: Source + ?Sized> Source for &S {
153    fn emit<'field>(&'field self, sink: &mut impl Sink<'field>) {
154        (**self).emit(sink);
155    }
156}
157
158impl Source for [Entry<'_>] {
159    fn emit<'field>(&'field self, sink: &mut impl Sink<'field>) {
160        for field in self {
161            sink.entry(*field);
162        }
163    }
164}
165
166impl<const N: usize> Source for [Entry<'_>; N] {
167    fn emit<'field>(&'field self, sink: &mut impl Sink<'field>) {
168        self.as_slice().emit(sink);
169    }
170}
171
172impl Source for Vec<Entry<'_>> {
173    fn emit<'field>(&'field self, sink: &mut impl Sink<'field>) {
174        self.as_slice().emit(sink);
175    }
176}
177
178impl<'entry, 'value> Source for Copied<slice::Iter<'entry, Entry<'value>>>
179where
180    'value: 'entry,
181{
182    fn emit<'field>(&'field self, sink: &mut impl Sink<'field>) {
183        for field in self.clone() {
184            sink.entry(field);
185        }
186    }
187}
188
189impl<'entry, 'value> Source for slice::Iter<'entry, Entry<'value>>
190where
191    'value: 'entry,
192{
193    fn emit<'field>(&'field self, sink: &mut impl Sink<'field>) {
194        for field in self.clone() {
195            sink.entry(*field);
196        }
197    }
198}
199
200impl Error {
201    pub fn trim_ows(mut value: &[u8]) -> &[u8] {
202        while matches!(value.first(), Some(b' ' | b'\t')) {
203            value = &value[1..];
204        }
205        while matches!(value.last(), Some(b' ' | b'\t')) {
206            value = &value[..value.len() - 1];
207        }
208        value
209    }
210
211    pub const fn name(name: &[u8]) -> Result<(), Self> {
212        if name.is_empty() {
213            return Err(Self::Empty);
214        }
215        let mut index = 0;
216        while index < name.len() {
217            let byte = name[index];
218            if !Self::is_name_byte(byte) {
219                return Err(Self::InvalidByte { index, byte });
220            }
221            index += 1;
222        }
223        Ok(())
224    }
225
226    pub const fn is_name_byte(byte: u8) -> bool {
227        byte.is_ascii_alphanumeric()
228            | (byte == b'!')
229            | (byte.wrapping_sub(b'#') <= b'\'' - b'#')
230            | (byte.wrapping_sub(b'*') <= b'+' - b'*')
231            | (byte.wrapping_sub(b'-') <= b'.' - b'-')
232            | (byte.wrapping_sub(b'^') <= b'`' - b'^')
233            | (byte == b'|')
234            | (byte == b'~')
235    }
236
237    pub const fn value(value: &[u8]) -> Result<(), Self> {
238        let mut index = 0;
239        while index < value.len() {
240            let byte = value[index];
241            if !Self::is_text(byte) {
242                return Err(Self::InvalidByte { index, byte });
243            }
244            index += 1;
245        }
246        Ok(())
247    }
248
249    pub const fn is_text(byte: u8) -> bool {
250        ((byte >= 0x20) & (byte != 0x7f)) | (byte == b'\t')
251    }
252}
253
254/// HTTP/2 and HTTP/3 response fields prefixed by `:status`.
255pub struct Response<F> {
256    value: Value<[u8; 3]>,
257    fields: F,
258}
259
260impl<F> Response<F> {
261    pub const fn new(status: status::Code, fields: F) -> Self {
262        Self {
263            value: Value(status.as_bytes()),
264            fields,
265        }
266    }
267}
268
269impl<F: Source> Source for Response<F> {
270    fn emit<'field>(&'field self, sink: &mut impl Sink<'field>) {
271        sink.entry(Entry::pseudo(Pseudo::Status, self.value.borrow()));
272        self.fields.emit(sink);
273    }
274}
275
276/// One admitted HTTP field whose borrowed bytes cannot change during emission.
277#[derive(Clone, Copy, Debug, PartialEq, Eq)]
278#[repr(transparent)]
279pub struct Entry<'a>(pub(in crate::field) record::Entry<'a>);
280
281/// A pseudo-field supported by HTTP/2 and HTTP/3.
282#[derive(Clone, Copy, Debug, PartialEq, Eq)]
283pub enum Pseudo {
284    Method,
285    Scheme,
286    Authority,
287    Path,
288    Protocol,
289    Status,
290}
291
292impl<'a> Entry<'a> {
293    pub const fn new(name: Lower<&'a [u8]>, value: Value<&'a [u8]>) -> Self {
294        Self(record::Entry::new(name.0, value.0))
295    }
296
297    pub const fn pseudo(name: Pseudo, value: Value<&'a [u8]>) -> Self {
298        let name = match name {
299            Pseudo::Method => b":method".as_slice(),
300            Pseudo::Scheme => b":scheme".as_slice(),
301            Pseudo::Authority => b":authority".as_slice(),
302            Pseudo::Path => b":path".as_slice(),
303            Pseudo::Protocol => b":protocol".as_slice(),
304            Pseudo::Status => b":status".as_slice(),
305        };
306        Self(record::Entry::new(name, value.0))
307    }
308
309    pub const fn with_index(self, indexing: Indexing) -> Self {
310        Self(self.0.with_index(indexing))
311    }
312
313    pub const fn name(self) -> &'a [u8] {
314        self.0.name
315    }
316
317    pub const fn value(self) -> Value<&'a [u8]> {
318        Value(self.0.value)
319    }
320
321    pub const fn indexing(self) -> Indexing {
322        self.0.indexing
323    }
324
325    pub const fn as_record(&self) -> record::Entry<'a> {
326        self.0
327    }
328}
329
330/// Immutable fields paired with their exact name/value line encoding.
331#[derive(Clone, Copy, Debug, PartialEq, Eq)]
332pub struct Group<'a> {
333    entries: &'a [Entry<'a>],
334    wire: &'a [u8],
335}
336
337/// The first byte where a field sequence and its wire encoding differ.
338#[derive(Clone, Copy, Debug, PartialEq, Eq)]
339pub struct Mismatch {
340    pub offset: usize,
341    pub expected: Option<u8>,
342    pub actual: Option<u8>,
343}
344
345struct Cursor<'a> {
346    wire: &'a [u8],
347    offset: usize,
348}
349
350impl<'a> Group<'a> {
351    pub const fn try_new(entries: &'a [Entry<'a>], wire: &'a [u8]) -> Result<Self, Mismatch> {
352        let mut cursor = Cursor { wire, offset: 0 };
353        let mut index = 0;
354        while index < entries.len() {
355            let entry = entries[index];
356            let parts = [entry.name(), b": ", entry.value().get(), b"\r\n"];
357            let mut part = 0;
358            while part < parts.len() {
359                if let Err(error) = cursor.check(parts[part]) {
360                    return Err(error);
361                }
362                part += 1;
363            }
364            index += 1;
365        }
366        if let Some((&actual, _)) = cursor.wire.split_first() {
367            return Err(Mismatch {
368                offset: cursor.offset,
369                expected: None,
370                actual: Some(actual),
371            });
372        }
373        Ok(Self { entries, wire })
374    }
375
376    pub const fn entries(&self) -> &'a [Entry<'a>] {
377        self.entries
378    }
379
380    pub const fn wire(&self) -> &'a [u8] {
381        self.wire
382    }
383}
384
385impl Source for Group<'_> {
386    fn emit<'field>(&'field self, sink: &mut impl Sink<'field>) {
387        sink.group(self);
388    }
389}
390
391impl Cursor<'_> {
392    const fn check(&mut self, expected: &[u8]) -> Result<(), Mismatch> {
393        let mut index = 0;
394        while index < expected.len() {
395            let byte = expected[index];
396            let (actual, rest) = match self.wire.split_first() {
397                Some((&actual, rest)) => (Some(actual), rest),
398                None => (None, self.wire),
399            };
400            if !matches!(actual, Some(actual) if actual == byte) {
401                return Err(Mismatch {
402                    offset: self.offset,
403                    expected: Some(byte),
404                    actual,
405                });
406            }
407            self.wire = rest;
408            self.offset += 1;
409            index += 1;
410        }
411        Ok(())
412    }
413}