Skip to main content

sark_http/field/metadata/
strings.rs

1//! HPACK and QPACK string literal decoding.
2
3use o3::buffer::write;
4
5use crate::field::metadata::huffman::decoder;
6
7#[repr(u8)]
8#[derive(Clone, Copy, PartialEq, Eq)]
9pub enum Encoding {
10    Plain,
11    Huffman,
12}
13
14#[repr(u8)]
15#[derive(Clone, Copy, PartialEq, Eq)]
16pub enum Completion {
17    Pending,
18    Complete,
19}
20
21#[derive(Clone, Copy, PartialEq, Eq)]
22enum State {
23    Plain,
24    Huffman(decoder::Decoder),
25}
26
27#[derive(Clone, Copy, PartialEq, Eq)]
28pub struct Cursor {
29    remaining: usize,
30    decoded_len: u32,
31    state: State,
32}
33
34#[derive(Clone, Copy, PartialEq, Eq)]
35pub struct Progress {
36    consumed: usize,
37    decoded: usize,
38}
39
40impl Cursor {
41    pub const fn new(len: usize, encoding: Encoding) -> Self {
42        Self {
43            remaining: len,
44            decoded_len: 0,
45            state: match encoding {
46                Encoding::Plain => State::Plain,
47                Encoding::Huffman => State::Huffman(decoder::Decoder::new()),
48            },
49        }
50    }
51
52    pub const fn remaining(&self) -> usize {
53        self.remaining
54    }
55
56    pub const fn decoded_len(&self) -> usize {
57        self.decoded_len as usize
58    }
59
60    pub const fn completion(&self) -> Completion {
61        if self.remaining == 0 {
62            Completion::Complete
63        } else {
64            Completion::Pending
65        }
66    }
67
68    pub fn output_bound(&self, input: usize) -> Result<usize, decoder::Error> {
69        let consumed = input.min(self.remaining);
70        match self.state {
71            State::Huffman(_) => consumed.checked_mul(2).ok_or(decoder::Error),
72            State::Plain => Ok(consumed),
73        }
74    }
75
76    pub fn feed_count(&mut self, input: &[u8]) -> Result<Progress, decoder::Error> {
77        let consumed = input.len().min(self.remaining);
78        let payload = &input[..consumed];
79        let (state, decoded) = match self.state {
80            State::Huffman(decoder) => {
81                let (next, decoded) = decoder.feed_count(payload)?;
82                (State::Huffman(next), decoded)
83            }
84            State::Plain => (State::Plain, consumed),
85        };
86        self.advance(consumed, decoded, state)
87    }
88
89    pub fn feed_into<W: write::Sink>(
90        &mut self,
91        input: &[u8],
92        sink: W,
93    ) -> Result<(Progress, W), decoder::Failure<W, W::Error>> {
94        let consumed = input.len().min(self.remaining);
95        let payload = &input[..consumed];
96        let (state, sink, decoded) = match self.state {
97            State::Huffman(decoder) => {
98                let (next, sink, decoded) = decoder.feed_into(payload, sink)?.into_parts();
99                (State::Huffman(next), sink, decoded)
100            }
101            State::Plain => {
102                let mut sink = sink;
103                sink = match write::Sink::write_slice(&mut sink, payload) {
104                    Ok(()) => Ok(sink),
105                    Err(cause) => Err(decoder::Failure {
106                        sink,
107                        cause: decoder::DecodeError::Sink(cause),
108                        progress: decoder::Progress::new(0, 0),
109                    }),
110                }?;
111                (State::Plain, sink, consumed)
112            }
113        };
114        let progress = match self.advance(consumed, decoded, state) {
115            Ok(progress) => progress,
116            Err(cause) => {
117                return Err(decoder::Failure {
118                    sink,
119                    cause: decoder::DecodeError::InvalidEncoding(cause),
120                    progress: decoder::Progress::new(consumed, decoded),
121                });
122            }
123        };
124        Ok((progress, sink))
125    }
126
127    pub fn finish(self) -> Result<usize, decoder::Error> {
128        if self.remaining != 0 {
129            return Err(decoder::Error);
130        }
131        match self.state {
132            State::Huffman(decoder) => decoder.finish()?,
133            State::Plain => {}
134        }
135        Ok(self.decoded_len())
136    }
137    fn advance(
138        &mut self,
139        consumed: usize,
140        decoded: usize,
141        state: State,
142    ) -> Result<Progress, decoder::Error> {
143        if decoded > u32::MAX as usize {
144            return Err(decoder::Error);
145        }
146        let decoded = decoded as u32;
147        let total = self
148            .decoded_len
149            .checked_add(decoded)
150            .ok_or(decoder::Error)?;
151        self.remaining -= consumed;
152        self.decoded_len = total;
153        self.state = state;
154        Ok(Progress {
155            consumed,
156            decoded: decoded as usize,
157        })
158    }
159}
160
161impl Progress {
162    pub const fn consumed(self) -> usize {
163        self.consumed
164    }
165
166    pub const fn decoded(self) -> usize {
167        self.decoded
168    }
169}
170
171const _: () = {
172    assert!(core::mem::size_of::<Encoding>() == core::mem::size_of::<bool>());
173    assert!(core::mem::size_of::<Completion>() == core::mem::size_of::<bool>());
174    assert!(core::mem::size_of::<State>() == core::mem::size_of::<Option<decoder::Decoder>>());
175    assert!(core::mem::align_of::<State>() == core::mem::align_of::<Option<decoder::Decoder>>());
176};