Skip to main content

sark_http/field/metadata/packed/
mod.rs

1use std::{mem, ops};
2
3use crate::field::{Indexing, metadata::map::record};
4
5mod decoded;
6pub mod prefix;
7
8pub use decoded::Decoded;
9use prefix::Prefix;
10use record::Entry;
11
12#[derive(Clone, Copy)]
13pub struct Iter<'a> {
14    current: &'a [u8],
15}
16
17pub struct RangeIter<'a> {
18    current: Iter<'a>,
19    offset: usize,
20}
21
22impl<'a> Iter<'a> {
23    pub(in crate::field::metadata) const fn new(current: &'a [u8]) -> Self {
24        Self { current }
25    }
26}
27
28impl<'a> RangeIter<'a> {
29    pub(in crate::field::metadata) fn new(current: &'a [u8], prefix: usize) -> Self {
30        Self {
31            current: Iter::new(&current[prefix..]),
32            offset: prefix,
33        }
34    }
35}
36
37impl<'a> Iterator for Iter<'a> {
38    type Item = Entry<'a>;
39
40    fn next(&mut self) -> Option<Self::Item> {
41        if self.current.is_empty() {
42            return None;
43        }
44        // SAFETY: only finished packed owners and transactional map writers create
45        // this iterator. Every nonempty suffix retains a complete canonical prefix.
46        let prefix = unsafe { &*self.current.as_ptr().cast::<[u8; Prefix::LEN]>() };
47        let prefix = Prefix::decode(prefix, Indexing::from_never(prefix[8] != 0));
48        let name_end = Prefix::LEN + prefix.name_len() as usize;
49        let end = name_end + prefix.value_len() as usize;
50        // SAFETY: the same admission proves both payload lengths within this
51        // immutable suffix. Advancing by the whole record preserves that proof.
52        let field = unsafe {
53            let field = Entry::new(
54                self.current.get_unchecked(Prefix::LEN..name_end),
55                self.current.get_unchecked(name_end..end),
56            )
57            .with_index(prefix.indexing());
58            self.current = self.current.get_unchecked(end..);
59            field
60        };
61        Some(field)
62    }
63}
64
65impl<'a> Iterator for RangeIter<'a> {
66    type Item = (Entry<'a>, ops::Range<usize>);
67
68    fn next(&mut self) -> Option<Self::Item> {
69        let field = self.current.next()?;
70        let start = self.offset + Prefix::LEN + field.name.len();
71        self.offset = start + field.value.len();
72        Some((field, start..self.offset))
73    }
74}
75
76const _: () = assert!(mem::size_of::<Iter<'static>>() == mem::size_of::<&[u8]>());