Skip to main content

sark_core/http/
field.rs

1use std::convert::Infallible;
2use std::fmt;
3use std::ops::Range;
4
5use o3::buffer::{ByteSink, PoolLayoutError, Pooled, SharedPool, SharedPoolLayout};
6
7#[derive(Copy, Clone, Debug, PartialEq, Eq)]
8pub struct Field<'a> {
9    pub name: &'a [u8],
10    pub value: &'a [u8],
11}
12
13impl<'a> Field<'a> {
14    pub const fn new(name: &'a [u8], value: &'a [u8]) -> Self {
15        Self { name, value }
16    }
17}
18
19#[doc(hidden)]
20#[derive(Copy, Clone, Debug, PartialEq, Eq)]
21pub struct FieldMatch<I> {
22    pub exact: Option<I>,
23    pub name: Option<I>,
24}
25
26#[doc(hidden)]
27pub fn match_field_candidates<'a, K, I>(
28    target: Field<'_>,
29    candidates: impl IntoIterator<Item = (K, Field<'a>)>,
30    mut classify: impl FnMut(K) -> Option<I>,
31) -> FieldMatch<I>
32where
33    I: Copy,
34{
35    let mut name = None;
36    for (key, candidate) in candidates {
37        if candidate.name != target.name {
38            continue;
39        }
40        let Some(index) = classify(key) else {
41            continue;
42        };
43        name.get_or_insert(index);
44        if candidate.value == target.value {
45            return FieldMatch {
46                exact: Some(index),
47                name,
48            };
49        }
50    }
51    FieldMatch { exact: None, name }
52}
53
54impl<'field> From<&Field<'field>> for Field<'field> {
55    fn from(field: &Field<'field>) -> Self {
56        *field
57    }
58}
59
60#[derive(Clone, Debug, PartialEq, Eq)]
61pub struct OwnedField {
62    pub name: Vec<u8>,
63    pub value: Vec<u8>,
64}
65
66impl OwnedField {
67    pub fn new(name: &[u8], value: &[u8]) -> Self {
68        Self {
69            name: name.to_vec(),
70            value: value.to_vec(),
71        }
72    }
73
74    pub fn as_ref(&self) -> Field<'_> {
75        Field::new(&self.name, &self.value)
76    }
77}
78
79impl From<Field<'_>> for OwnedField {
80    fn from(field: Field<'_>) -> Self {
81        Self::new(field.name, field.value)
82    }
83}
84
85impl<'a> From<&'a OwnedField> for Field<'a> {
86    fn from(field: &'a OwnedField) -> Self {
87        field.as_ref()
88    }
89}
90
91pub trait FieldStorage {
92    type Iter<'a>: Iterator<Item = Field<'a>>
93    where
94        Self: 'a;
95
96    fn fields(&self) -> Self::Iter<'_>;
97}
98
99#[derive(Clone)]
100pub struct FieldBlock<S> {
101    storage: S,
102}
103
104impl<S> FieldBlock<S> {
105    pub const fn from_storage(storage: S) -> Self {
106        Self { storage }
107    }
108
109    pub fn into_storage(self) -> S {
110        self.storage
111    }
112
113    pub fn storage(&self) -> &S {
114        &self.storage
115    }
116}
117
118impl<S: FieldStorage> FieldBlock<S> {
119    pub fn iter(&self) -> S::Iter<'_> {
120        self.storage.fields()
121    }
122
123    pub fn get(&self, name: &[u8]) -> Option<&[u8]> {
124        self.iter()
125            .find(|field| field.name == name)
126            .map(|field| field.value)
127    }
128}
129
130impl<S: FieldStorage> fmt::Debug for FieldBlock<S> {
131    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
132        formatter.debug_list().entries(self.iter()).finish()
133    }
134}
135
136impl<S, T> PartialEq<FieldBlock<T>> for FieldBlock<S>
137where
138    S: FieldStorage,
139    T: FieldStorage,
140{
141    fn eq(&self, other: &FieldBlock<T>) -> bool {
142        self.iter().eq(other.iter())
143    }
144}
145
146impl<S: FieldStorage> Eq for FieldBlock<S> {}
147
148impl<'a, S: FieldStorage> IntoIterator for &'a FieldBlock<S> {
149    type Item = Field<'a>;
150    type IntoIter = S::Iter<'a>;
151
152    fn into_iter(self) -> Self::IntoIter {
153        self.iter()
154    }
155}
156
157pub struct OwnedFieldIter<'a> {
158    fields: std::slice::Iter<'a, OwnedField>,
159}
160
161impl<'a> Iterator for OwnedFieldIter<'a> {
162    type Item = Field<'a>;
163
164    fn next(&mut self) -> Option<Self::Item> {
165        self.fields.next().map(OwnedField::as_ref)
166    }
167
168    fn size_hint(&self) -> (usize, Option<usize>) {
169        self.fields.size_hint()
170    }
171}
172
173impl ExactSizeIterator for OwnedFieldIter<'_> {}
174
175impl FieldStorage for Vec<OwnedField> {
176    type Iter<'a> = OwnedFieldIter<'a>;
177
178    fn fields(&self) -> Self::Iter<'_> {
179        OwnedFieldIter {
180            fields: self.iter(),
181        }
182    }
183}
184
185pub type OwnedFieldBlock = FieldBlock<Vec<OwnedField>>;
186
187impl FieldBlock<Vec<OwnedField>> {
188    pub const fn new() -> Self {
189        Self::from_storage(Vec::new())
190    }
191
192    pub fn push(&mut self, name: &[u8], value: &[u8]) {
193        self.storage.push(OwnedField::new(name, value));
194    }
195
196    pub fn as_slice(&self) -> &[OwnedField] {
197        &self.storage
198    }
199}
200
201impl Default for FieldBlock<Vec<OwnedField>> {
202    fn default() -> Self {
203        Self::new()
204    }
205}
206
207#[derive(Clone)]
208pub struct PackedFields<S> {
209    first: S,
210    second: Option<S>,
211}
212
213#[derive(Clone, Debug, PartialEq, Eq)]
214pub enum PackedFieldError<E> {
215    Write(E),
216    ComponentTooLarge { len: usize },
217    ValueLengthMismatch { expected: usize, actual: usize },
218}
219
220fn write_packed_prefix<W: ByteSink>(
221    writer: &mut W,
222    name: &[u8],
223    value_len: usize,
224) -> Result<(), PackedFieldError<W::Error>> {
225    let name_len = packed_len(name.len())?;
226    let value_len = packed_len(value_len)?;
227    writer
228        .write_slices([&name_len, &value_len, name])
229        .map_err(PackedFieldError::Write)
230}
231
232fn packed_len<E>(len: usize) -> Result<[u8; 4], PackedFieldError<E>> {
233    match u32::try_from(len) {
234        Ok(len) => Ok(len.to_ne_bytes()),
235        Err(_) => Err(PackedFieldError::ComponentTooLarge { len }),
236    }
237}
238
239fn write_packed_field<W: ByteSink>(
240    writer: &mut W,
241    field: Field<'_>,
242) -> Result<(), PackedFieldError<W::Error>> {
243    let name_len = packed_len(field.name.len())?;
244    let value_len = packed_len(field.value.len())?;
245    writer
246        .write_slices([&name_len, &value_len, field.name, field.value])
247        .map_err(PackedFieldError::Write)
248}
249
250fn packed_capacity(fields: &[Field<'_>]) -> Option<usize> {
251    fields.iter().try_fold(0usize, |size, field| {
252        u32::try_from(field.name.len()).ok()?;
253        u32::try_from(field.value.len()).ok()?;
254        field
255            .name
256            .len()
257            .checked_add(field.value.len())?
258            .checked_add(8)?
259            .checked_add(size)
260    })
261}
262
263impl<S> PackedFields<S> {
264    pub const fn new(first: S) -> Self {
265        Self {
266            first,
267            second: None,
268        }
269    }
270}
271
272impl<S: AsRef<[u8]>> FieldStorage for PackedFields<S> {
273    type Iter<'a>
274        = PackedFieldIter<'a>
275    where
276        S: 'a;
277
278    fn fields(&self) -> Self::Iter<'_> {
279        PackedFieldIter {
280            current: self.first.as_ref(),
281            second: self.second.as_ref().map(AsRef::as_ref),
282        }
283    }
284}
285
286pub type PooledFieldBlock = FieldBlock<PackedFields<Pooled>>;
287pub type VecFieldBlock = FieldBlock<PackedFields<Vec<u8>>>;
288pub type DecodedFieldBlock = PooledFieldBlock;
289
290impl FieldBlock<PackedFields<Pooled>> {
291    pub fn from_pooled(pooled: Pooled) -> Self {
292        Self::from_storage(PackedFields::new(pooled))
293    }
294
295    pub fn from_fields(fields: &[Field<'_>]) -> Result<Self, PoolLayoutError> {
296        let capacity = packed_capacity(fields).ok_or(PoolLayoutError::CapacityOverflow)?;
297        let layout = SharedPoolLayout::new(1, capacity.max(1))?;
298        let pool = SharedPool::from_layout(layout);
299        let mut lease = pool.try_acquire().ok_or(PoolLayoutError::SlotOverflow)?;
300        let mut writer = lease.spare_writer();
301        for field in fields {
302            write_packed_field(&mut writer, *field)
303                .map_err(|_| PoolLayoutError::CapacityOverflow)?;
304        }
305        drop(writer);
306        Ok(Self::from_pooled(lease.freeze()))
307    }
308
309    pub fn from_headers(fields: &[Field<'_>]) -> Result<Self, PoolLayoutError> {
310        Self::from_fields(fields)
311    }
312
313    pub fn append(&mut self, other: Self) -> Result<(), Self> {
314        if self.storage.second.is_some() || other.storage.second.is_some() {
315            return Err(other);
316        }
317        self.storage.second = Some(other.storage.first);
318        Ok(())
319    }
320
321    pub fn to_owned(&self) -> Vec<OwnedField> {
322        self.iter().map(OwnedField::from).collect()
323    }
324
325    pub(crate) fn into_primary(self) -> Pooled {
326        self.storage.first
327    }
328}
329
330impl FieldBlock<PackedFields<Vec<u8>>> {
331    pub const fn new() -> Self {
332        Self::from_storage(PackedFields::new(Vec::new()))
333    }
334
335    pub fn with_capacity(capacity: usize) -> Self {
336        Self::from_storage(PackedFields::new(Vec::with_capacity(capacity)))
337    }
338
339    pub fn push(&mut self, name: &[u8], value: &[u8]) -> Result<(), PackedFieldError<Infallible>> {
340        write_packed_field(&mut self.storage.first, Field::new(name, value))
341    }
342
343    pub fn push_encoded(
344        &mut self,
345        name: &[u8],
346        value_len: usize,
347        encode: impl FnOnce(&mut FieldValueWriter<'_>),
348    ) -> Result<(), PackedFieldError<Infallible>> {
349        let field_start = self.storage.first.len();
350        write_packed_prefix(&mut self.storage.first, name, value_len)?;
351        let start = self.storage.first.len();
352        encode(&mut FieldValueWriter {
353            bytes: &mut self.storage.first,
354        });
355        let actual = self.storage.first.len() - start;
356        if actual != value_len {
357            self.storage.first.truncate(field_start);
358            return Err(PackedFieldError::ValueLengthMismatch {
359                expected: value_len,
360                actual,
361            });
362        }
363        Ok(())
364    }
365
366    pub fn try_push_parts<E>(
367        &mut self,
368        encode_name: impl FnOnce(&mut FieldValueWriter<'_>) -> Result<(), E>,
369        encode_value: impl FnOnce(&mut FieldValueWriter<'_>, usize) -> Result<(), E>,
370    ) -> Result<(usize, usize), PackedFieldError<E>> {
371        let field_start = self.storage.first.len();
372        self.storage.first.extend_from_slice(&[0; 8]);
373        let name_start = self.storage.first.len();
374        if let Err(error) = encode_name(&mut FieldValueWriter {
375            bytes: &mut self.storage.first,
376        }) {
377            self.storage.first.truncate(field_start);
378            return Err(PackedFieldError::Write(error));
379        }
380        let value_start = self.storage.first.len();
381        let name_len = value_start - name_start;
382        if let Err(error) = encode_value(
383            &mut FieldValueWriter {
384                bytes: &mut self.storage.first,
385            },
386            name_len,
387        ) {
388            self.storage.first.truncate(field_start);
389            return Err(PackedFieldError::Write(error));
390        }
391        let end = self.storage.first.len();
392        let value_len = end - value_start;
393        let name_len_bytes = match packed_len(name_len) {
394            Ok(len) => len,
395            Err(error) => {
396                self.storage.first.truncate(field_start);
397                return Err(error);
398            }
399        };
400        let value_len_bytes = match packed_len(value_len) {
401            Ok(len) => len,
402            Err(error) => {
403                self.storage.first.truncate(field_start);
404                return Err(error);
405            }
406        };
407        self.storage.first[field_start..field_start + 4].copy_from_slice(&name_len_bytes);
408        self.storage.first[field_start + 4..name_start].copy_from_slice(&value_len_bytes);
409        Ok((name_len, value_len))
410    }
411}
412
413impl<S: AsRef<[u8]>> FieldBlock<PackedFields<S>> {
414    pub fn as_bytes(&self) -> &[u8] {
415        self.storage.first.as_ref()
416    }
417
418    pub fn iter_with_value_ranges(&self) -> PackedFieldRangeIter<'_> {
419        PackedFieldRangeIter {
420            current: self.storage.first.as_ref(),
421            offset: 0,
422        }
423    }
424
425    #[doc(hidden)]
426    pub fn iter_with_value_ranges_from(&self, offset: usize) -> PackedFieldRangeIter<'_> {
427        PackedFieldRangeIter {
428            current: self
429                .storage
430                .first
431                .as_ref()
432                .get(offset..)
433                .unwrap_or_default(),
434            offset,
435        }
436    }
437}
438
439impl Default for FieldBlock<PackedFields<Vec<u8>>> {
440    fn default() -> Self {
441        Self::new()
442    }
443}
444
445pub struct FieldValueWriter<'a> {
446    bytes: &'a mut Vec<u8>,
447}
448
449impl FieldValueWriter<'_> {
450    pub fn push(&mut self, byte: u8) {
451        self.bytes.push(byte);
452    }
453
454    pub fn extend_from_slice(&mut self, bytes: &[u8]) {
455        self.bytes.extend_from_slice(bytes);
456    }
457}
458
459pub struct PackedFieldIter<'a> {
460    current: &'a [u8],
461    second: Option<&'a [u8]>,
462}
463
464impl<'a> Iterator for PackedFieldIter<'a> {
465    type Item = Field<'a>;
466
467    fn next(&mut self) -> Option<Self::Item> {
468        if self.current.is_empty() {
469            self.current = self.second.take()?;
470        }
471        let Some((field, _, end)) = parse_packed_field(self.current) else {
472            self.current = &[];
473            self.second = None;
474            return None;
475        };
476        self.current = &self.current[end..];
477        Some(field)
478    }
479}
480
481pub struct PackedFieldRangeIter<'a> {
482    current: &'a [u8],
483    offset: usize,
484}
485
486impl<'a> Iterator for PackedFieldRangeIter<'a> {
487    type Item = (Field<'a>, Range<usize>);
488
489    fn next(&mut self) -> Option<Self::Item> {
490        let Some((field, value_start, end)) = parse_packed_field(self.current) else {
491            self.current = &[];
492            return None;
493        };
494        let value_range = self.offset + value_start..self.offset + end;
495        self.current = &self.current[end..];
496        self.offset += end;
497        Some((field, value_range))
498    }
499}
500
501fn parse_packed_field(bytes: &[u8]) -> Option<(Field<'_>, usize, usize)> {
502    if bytes.len() < 8 {
503        return None;
504    }
505    let name_len = u32::from_ne_bytes(bytes[..4].try_into().ok()?) as usize;
506    let value_len = u32::from_ne_bytes(bytes[4..8].try_into().ok()?) as usize;
507    let value_start = 8usize.checked_add(name_len)?;
508    let end = value_start.checked_add(value_len)?;
509    if end > bytes.len() {
510        return None;
511    }
512    Some((
513        Field::new(&bytes[8..value_start], &bytes[value_start..end]),
514        value_start,
515        end,
516    ))
517}
518
519#[cfg(test)]
520mod tests {
521    use super::{Field, match_field_candidates};
522
523    #[test]
524    fn field_matching_classifies_only_name_candidates_and_stops_at_exact() {
525        let candidates = [
526            (0, Field::new(b"other", b"target")),
527            (1, Field::new(b"name", b"older")),
528            (2, Field::new(b"name", b"target")),
529            (3, Field::new(b"name", b"newer")),
530        ];
531        let mut classified = Vec::new();
532        let found = match_field_candidates(Field::new(b"name", b"target"), candidates, |index| {
533            classified.push(index);
534            (index != 1).then_some(index)
535        });
536
537        assert_eq!(found.exact, Some(2));
538        assert_eq!(found.name, Some(2));
539        assert_eq!(classified, [1, 2]);
540    }
541}