sark_http/h1/codec/decode/
trailer.rs1use core::{mem, num::NonZero};
2
3use chunk::trailer;
4use o3::{
5 buffer::{
6 resident,
7 storage::Owned,
8 write::{Sink as _, SpareExt as _, consume},
9 },
10 mem::Rejected,
11};
12
13use crate::{
14 field,
15 h1::{chunk, field::Entry},
16};
17
18pub struct Pending<'input> {
20 bytes: &'input [u8],
21 consumed: NonZero<usize>,
22 parser: trailer::Trailer,
23}
24
25pub struct State<'d> {
27 source: Owned<resident::Budget<'d>>,
28 parser: trailer::Trailer,
29}
30
31#[must_use = "append the admitted bytes to transfer their framing proof"]
33pub struct Plan<'input, 'd, P = Phase<NonZero<usize>>> {
34 state: State<'d>,
35 bytes: &'input [u8],
36 next: P,
37}
38
39pub struct Phase<T>(Next<T>);
40
41enum Next<T> {
42 More {
43 cursor: trailer::Cursor,
44 consumed: Option<T>,
45 },
46 Complete(T),
47}
48
49pub struct More<T> {
50 cursor: trailer::Cursor,
51 consumed: Option<T>,
52}
53
54pub struct Ready<T>(T);
55
56pub struct Complete<'d> {
58 source: Owned<resident::Budget<'d>>,
59}
60
61#[derive(Debug)]
62pub enum StoreError {
63 Prefix(NonZero<usize>),
64 Capacity(consume::Error),
65}
66
67#[derive(Debug)]
68pub enum AppendError<E> {
69 Capacity(consume::Error),
70 Ready(E),
71}
72
73impl<E> From<consume::Error> for AppendError<E> {
74 fn from(error: consume::Error) -> Self {
75 Self::Capacity(error)
76 }
77}
78
79impl<'input> Pending<'input> {
80 pub(in crate::h1::codec::decode) fn new(partial: trailer::Partial<'input>) -> Self {
81 let (bytes, consumed, parser) = partial.into_parts();
82 Self {
83 bytes,
84 consumed,
85 parser,
86 }
87 }
88
89 pub const fn consumed(&self) -> NonZero<usize> {
90 self.consumed
91 }
92
93 pub const fn len(&self) -> usize {
94 self.bytes.len()
95 }
96
97 pub const fn is_empty(&self) -> bool {
98 self.bytes.is_empty()
99 }
100
101 pub const fn capacity(&self) -> usize {
102 self.parser.capacity()
103 }
104
105 pub fn try_store<'d>(
107 self,
108 mut target: Owned<resident::Budget<'d>>,
109 ) -> Result<State<'d>, Rejected<(Self, Owned<resident::Budget<'d>>), StoreError>> {
110 if let Err(error) = StoreError::copy(&mut target, self.bytes) {
111 return Err(Rejected::new((self, target), error));
112 }
113 Ok(State {
114 source: target,
115 parser: self.parser,
116 })
117 }
118}
119
120impl<'d> State<'d> {
121 pub fn len(&self) -> usize {
122 self.source.len()
123 }
124
125 pub fn is_empty(&self) -> bool {
126 self.source.is_empty()
127 }
128
129 pub fn prepare<'input>(
130 self,
131 input: &'input [u8],
132 ) -> Result<Plan<'input, 'd>, Rejected<Self, chunk::Error>> {
133 let (next, bytes) = match self.parser.scan(input) {
134 Ok(next) => next,
135 Err(error) => return Err(Rejected::new(self, error)),
136 };
137 let next = match next {
138 trailer::Progress::More { next, consumed } => Next::More {
139 cursor: next,
140 consumed,
141 },
142 trailer::Progress::Complete { consumed, .. } => Next::Complete(consumed),
143 };
144 Ok(Plan {
145 state: self,
146 bytes,
147 next: Phase(next),
148 })
149 }
150}
151
152impl<'input, 'd> Plan<'input, 'd> {
153 pub fn try_map<T, E>(
155 self,
156 bind: impl FnOnce(NonZero<usize>) -> Result<T, E>,
157 ) -> Result<Plan<'input, 'd, Phase<T>>, Rejected<State<'d>, E>> {
158 let next = match self.next.0 {
159 Next::More { cursor, consumed } => {
160 let consumed = match consumed.map(bind).transpose() {
161 Ok(consumed) => consumed,
162 Err(error) => return Err(Rejected::new(self.state, error)),
163 };
164 Next::More { cursor, consumed }
165 }
166 Next::Complete(consumed) => match bind(consumed) {
167 Ok(consumed) => Next::Complete(consumed),
168 Err(error) => return Err(Rejected::new(self.state, error)),
169 },
170 };
171 Ok(Plan {
172 state: self.state,
173 bytes: self.bytes,
174 next: Phase(next),
175 })
176 }
177}
178
179impl<'input, 'd, T> Plan<'input, 'd, Phase<T>> {
180 pub fn split(self) -> Result<Plan<'input, 'd, Ready<T>>, Plan<'input, 'd, More<T>>> {
181 match self.next.0 {
182 Next::Complete(consumed) => Ok(Plan {
183 state: self.state,
184 bytes: self.bytes,
185 next: Ready(consumed),
186 }),
187 Next::More { cursor, consumed } => Err(Plan {
188 state: self.state,
189 bytes: self.bytes,
190 next: More { cursor, consumed },
191 }),
192 }
193 }
194}
195
196impl<'d, P> Plan<'_, 'd, P> {
197 pub fn len(&self) -> usize {
198 self.state.len()
199 }
200
201 pub fn is_empty(&self) -> bool {
202 self.state.is_empty()
203 }
204
205 pub fn cancel(self) -> State<'d> {
206 self.state
207 }
208
209 pub fn try_grow(
211 &mut self,
212 mut target: Owned<resident::Budget<'d>>,
213 ) -> Result<(), Rejected<Owned<resident::Budget<'d>>, StoreError>> {
214 if let Err(error) = StoreError::copy(&mut target, self.state.source.as_slice()) {
215 return Err(Rejected::new(target, error));
216 }
217 self.state.source = target;
218 Ok(())
219 }
220}
221
222impl<'d, T> Plan<'_, 'd, More<T>> {
223 pub fn try_append(&mut self) -> Result<Option<T>, consume::Error> {
224 let mut spare = self.state.source.spare();
225 spare.write_slice(self.bytes)?;
226 spare.commit();
227 self.state.parser.cursor = self.next.cursor;
228 self.bytes = &[];
229 Ok(self.next.consumed.take())
230 }
231}
232
233impl<'d, T> Plan<'_, 'd, Ready<T>> {
234 pub fn fields(&self) -> [&[u8]; 2] {
236 let prefix = self.state.source.as_slice();
237 let left = prefix.len() - 2usize.saturating_sub(self.bytes.len());
238 let right = self.bytes.len().saturating_sub(2);
239 unsafe {
244 [
245 prefix.get_unchecked(..left),
246 self.bytes.get_unchecked(..right),
247 ]
248 }
249 }
250
251 pub fn try_append<V, E>(
253 self,
254 ready: impl FnOnce() -> Result<V, E>,
255 ) -> Result<(Complete<'d>, T, V), Rejected<Self, AppendError<E>>> {
256 let mut this = self;
257 let mut spare = this.state.source.spare();
258 let value = match spare.try_append(this.bytes, || ready().map_err(AppendError::Ready)) {
259 Ok(value) => value,
260 Err(error) => {
261 return Err(Rejected::new(this, error));
262 }
263 };
264 spare.commit();
265 let mut source = this.state.source;
266 let len = source.len() - 2;
267 source.truncate(len);
268 Ok((Complete { source }, this.next.0, value))
269 }
270}
271
272impl<'d> Complete<'d> {
273 pub fn fields(&self) -> Fields<'_> {
274 Fields::new(self.source.as_slice())
275 }
276
277 pub fn into_owner(self) -> Owned<resident::Budget<'d>> {
278 self.source
279 }
280}
281
282impl StoreError {
283 fn copy(target: &mut Owned<resident::Budget<'_>>, bytes: &[u8]) -> Result<(), Self> {
284 if let Some(len) = NonZero::new(target.len()) {
285 return Err(Self::Prefix(len));
286 }
287 target.try_extend(bytes).map_err(Self::Capacity)
288 }
289}
290
291pub struct Fields<'a> {
294 lines: &'a [u8],
295}
296
297impl<'a> Fields<'a> {
298 pub(super) fn new(lines: &'a [u8]) -> Self {
299 Self { lines }
300 }
301
302 pub const fn section(&self) -> &'a [u8] {
304 self.lines
305 }
306}
307
308impl<'a> Iterator for Fields<'a> {
309 type Item = (&'a [u8], &'a [u8]);
310
311 fn next(&mut self) -> Option<Self::Item> {
312 let (name, value, rest) = Entry::split(self.lines)?;
313 self.lines = rest;
314 Some((name, field::Error::trim_ows(value)))
315 }
316}
317
318const _: () = assert!(mem::size_of::<Fields<'_>>() == 2 * mem::size_of::<usize>());