Skip to main content

sark_http/field/text/percent/
raw.rs

1use crate::{
2    field,
3    field::{
4        storage::encoded,
5        text::percent::{Error, Length, octet, scan},
6    },
7};
8
9pub struct Encoder<'a> {
10    text: &'a str,
11    length: Length,
12}
13
14impl<'a> Encoder<'a> {
15    pub fn new(text: &'a str) -> Result<Self, Error> {
16        Ok(Self {
17            text,
18            length: Length::measure(text.as_bytes())?,
19        })
20    }
21
22    /// Reuses the encoded length admitted for this exact immutable text.
23    /// # Safety
24    /// `length` must describe these same text bytes, measured by this codec.
25    pub const unsafe fn from_length(text: &'a str, length: Length) -> Self {
26        Self { text, length }
27    }
28
29    pub const fn length(&self) -> Length {
30        self.length
31    }
32}
33
34impl encoded::Encoded for Encoder<'_> {}
35
36impl field::Encode for Encoder<'_> {
37    fn encoded_len(&self) -> usize {
38        self.length.get()
39    }
40
41    fn try_write<E>(self, mut emit: impl FnMut(&[u8]) -> Result<(), E>) -> Result<(), E> {
42        let mut bytes = self.text.as_bytes();
43        while !bytes.is_empty() {
44            let (literal, suffix) = scan::Scan::new(bytes).plain();
45            emit(literal)?;
46            let Some((&byte, tail)) = suffix.split_first() else {
47                return Ok(());
48            };
49            emit(&octet::encode(byte))?;
50            bytes = tail;
51        }
52        Ok(())
53    }
54}
55
56const _: () = assert!(core::mem::size_of::<Encoder<'_>>() == 3 * core::mem::size_of::<usize>());