Skip to main content

sark_http/h1/field/
entry.rs

1use crate::{
2    field::{head, scan::Match},
3    request::span,
4};
5
6#[derive(Clone, Copy, PartialEq, Eq)]
7pub struct Entry<'owner> {
8    name: &'owner [u8],
9    value: &'owner [u8],
10    name_span: span::Span,
11    value_span: span::Span,
12    line_span: span::Span,
13}
14
15impl<'owner> Entry<'owner> {
16    /// Splits one CRLF-terminated field without validating its name or value.
17    /// Admitted sections retain their grammar proof; arbitrary input returns `None`
18    /// when a required delimiter is missing. The value retains its original OWS.
19    pub fn split(bytes: &[u8]) -> Option<(&[u8], &[u8], &[u8])> {
20        let end = Match::find(b'\r', bytes)?;
21        let rest = end.suffix().strip_prefix(b"\n")?;
22        let colon = Match::find(b':', end.prefix())?;
23        Some((colon.prefix(), colon.suffix(), rest))
24    }
25
26    pub(super) fn new(
27        name: span::Retained<'owner>,
28        value: span::Retained<'owner>,
29        line: span::Span,
30    ) -> Self {
31        Self {
32            name: name.bytes(),
33            value: value.bytes(),
34            name_span: name.span(),
35            value_span: value.span(),
36            line_span: line,
37        }
38    }
39
40    pub(crate) fn kind(&self) -> head::Name {
41        match head::Name::from_h1(self.name()) {
42            Some(name) => name,
43            None => head::Name::Regular,
44        }
45    }
46
47    pub fn name(&self) -> &'owner [u8] {
48        self.name
49    }
50
51    pub fn value(&self) -> &'owner [u8] {
52        self.value
53    }
54
55    pub const fn name_span(&self) -> span::Span {
56        self.name_span
57    }
58
59    pub const fn value_span(&self) -> span::Span {
60        self.value_span
61    }
62
63    pub const fn line_span(&self) -> span::Span {
64        self.line_span
65    }
66}
67
68const _: () = assert!(core::mem::size_of::<Entry<'_>>() == 56);