Skip to main content

sark_http/field/metadata/map/
record.rs

1//! Borrowed metadata records and match results.
2
3use core::ops;
4
5/// Borrowed bytes held in one or two physical segments.
6#[derive(Clone, Copy)]
7pub struct Span<'a> {
8    first: &'a [u8],
9    second: &'a [u8],
10}
11
12impl<'a> Span<'a> {
13    pub const fn new(first: &'a [u8], second: &'a [u8]) -> Self {
14        Self { first, second }
15    }
16
17    pub const fn from_slice(bytes: &'a [u8]) -> Self {
18        Self::new(bytes, &[])
19    }
20
21    pub const fn len(self) -> usize {
22        self.first.len() + self.second.len()
23    }
24
25    pub const fn is_empty(self) -> bool {
26        self.first.is_empty() && self.second.is_empty()
27    }
28
29    pub const fn parts(self) -> (&'a [u8], &'a [u8]) {
30        (self.first, self.second)
31    }
32
33    pub const fn as_slice(&self) -> Option<&'a [u8]> {
34        if self.second.is_empty() {
35            Some(self.first)
36        } else {
37            None
38        }
39    }
40
41    pub fn get(self, index: usize) -> Option<u8> {
42        if index < self.first.len() {
43            self.first.get(index).copied()
44        } else {
45            self.second.get(index - self.first.len()).copied()
46        }
47    }
48
49    pub fn iter(&self) -> impl Iterator<Item = &'a u8> + Clone {
50        self.first.iter().chain(self.second)
51    }
52
53    pub fn slice(self, range: ops::Range<usize>) -> Option<Self> {
54        let split = self.first.len();
55        if range.end <= split {
56            return self.first.get(range).map(Self::from_slice);
57        }
58        if range.start >= split {
59            return self
60                .second
61                .get(range.start - split..range.end - split)
62                .map(Self::from_slice);
63        }
64        Some(Self::new(
65            self.first.get(range.start..)?,
66            self.second.get(..range.end - split)?,
67        ))
68    }
69
70    pub fn is_equal(self, bytes: &[u8]) -> bool {
71        let split = self.first.len();
72        bytes.len() == self.len()
73            && bytes.get(..split) == Some(self.first)
74            && bytes.get(split..) == Some(self.second)
75    }
76
77    pub fn starts_with(self, prefix: &[u8]) -> bool {
78        let (first, second) = prefix.split_at(prefix.len().min(self.first.len()));
79        self.first.starts_with(first) && self.second.starts_with(second)
80    }
81
82    pub fn ends_with(self, suffix: &[u8]) -> bool {
83        let (first, second) = suffix.split_at(suffix.len().saturating_sub(self.second.len()));
84        self.first.ends_with(first) && self.second.ends_with(second)
85    }
86
87    pub fn eq_ascii(self, bytes: &[u8]) -> bool {
88        bytes.len() == self.len()
89            && self
90                .iter()
91                .copied()
92                .zip(bytes.iter().copied())
93                .all(|(left, right)| left.eq_ignore_ascii_case(&right))
94    }
95
96    pub fn extend(self, out: &mut impl Extend<u8>) {
97        out.extend(self.first.iter().copied());
98        out.extend(self.second.iter().copied());
99    }
100}
101
102impl PartialEq for Span<'_> {
103    fn eq(&self, other: &Self) -> bool {
104        self.first
105            .iter()
106            .chain(self.second)
107            .eq(other.first.iter().chain(other.second))
108    }
109}
110
111impl Eq for Span<'_> {}
112
113#[derive(Copy, Clone, Debug, PartialEq, Eq)]
114pub struct Entry<'a> {
115    pub name: &'a [u8],
116    pub value: &'a [u8],
117    pub indexing: crate::field::Indexing,
118}
119
120impl<'a> Entry<'a> {
121    pub const fn new(name: &'a [u8], value: &'a [u8]) -> Self {
122        Self {
123            name,
124            value,
125            indexing: crate::field::Indexing::Allowed,
126        }
127    }
128
129    pub const fn with_index(mut self, indexing: crate::field::Indexing) -> Self {
130        self.indexing = indexing;
131        self
132    }
133}
134
135impl<'field> From<&Entry<'field>> for Entry<'field> {
136    fn from(field: &Entry<'field>) -> Self {
137        *field
138    }
139}
140
141#[derive(Copy, Clone, PartialEq, Eq)]
142pub struct View<'a> {
143    pub name: Span<'a>,
144    pub value: Span<'a>,
145    pub indexing: crate::field::Indexing,
146}
147
148impl<'a> View<'a> {
149    pub const fn new(name: Span<'a>, value: Span<'a>) -> Self {
150        Self {
151            name,
152            value,
153            indexing: crate::field::Indexing::Allowed,
154        }
155    }
156
157    pub const fn with_index(mut self, indexing: crate::field::Indexing) -> Self {
158        self.indexing = indexing;
159        self
160    }
161}
162
163impl<'a> From<Entry<'a>> for View<'a> {
164    fn from(field: Entry<'a>) -> Self {
165        Self::new(Span::from_slice(field.name), Span::from_slice(field.value))
166            .with_index(field.indexing)
167    }
168}
169
170#[doc(hidden)]
171#[derive(Copy, Clone, PartialEq, Eq)]
172pub struct Match<I, N = Option<I>> {
173    pub exact: Option<I>,
174    pub name: N,
175}
176
177impl<I> Match<I> {
178    #[doc(hidden)]
179    pub const fn none() -> Self {
180        Self {
181            exact: None,
182            name: None,
183        }
184    }
185}