sark_http/h1/field/
scan.rs1use core::num::NonZero;
2
3use o3::buffer::{self, write};
4use write::CopyError;
5
6use crate::h1::field::{self, Cursor, Entry, Limit, syntax};
7
8pub struct State<S> {
11 source: S,
12 cursor: Cursor,
13}
14
15pub enum Progress<S> {
16 More(State<S>),
17 Complete(Complete<S>),
18}
19
20pub struct Complete<S> {
23 source: S,
24 end: field::End,
25}
26
27#[derive(Debug)]
28pub enum Error<E> {
29 Syntax(syntax::Error),
30 Sink(E),
31}
32
33impl<S: buffer::raw::Source> State<S> {
34 pub const fn source(&self) -> &S {
35 &self.source
36 }
37
38 pub fn try_new(
41 source: S,
42 start: usize,
43 seen: usize,
44 fields: usize,
45 line: usize,
46 ) -> Result<Self, (S, syntax::Error)> {
47 if start > source.as_ref().len() {
48 return Err((source, syntax::Error::Invalid));
49 }
50 match Cursor::seed(start, seen, Limit::new(fields, line)) {
51 Ok(cursor) => Ok(Self { source, cursor }),
52 Err(error) => Err((source, error)),
53 }
54 }
55
56 pub fn advance<E>(
57 mut self,
58 mut sink: impl FnMut(Entry<'_>) -> Result<(), E>,
59 ) -> Result<Progress<S>, (S, Error<E>)> {
60 loop {
61 match self.cursor.advance(self.source.as_ref()) {
62 Ok(field::Progress::Field(field)) => {
63 if let Err(error) = sink(field) {
64 return Err((self.source, Error::Sink(error)));
65 }
66 }
67 Ok(field::Progress::More) => return Ok(Progress::More(self)),
68 Ok(field::Progress::End(end)) => {
69 return Ok(Progress::Complete(Complete {
70 source: self.source,
71 end,
72 }));
73 }
74 Err(error) => return Err((self.source, Error::Syntax(error))),
75 }
76 }
77 }
78
79 pub fn try_copy<D>(&self, target: D) -> Result<State<D>, (D, CopyError<D::Error>)>
81 where
82 D: buffer::raw::Source + write::Sink,
83 {
84 let target = write::try_copy(target, self.source.as_ref())?;
85 Ok(State {
86 source: target,
87 cursor: self.cursor,
88 })
89 }
90}
91
92impl<S: write::Sink> State<S> {
93 pub fn try_extend(&mut self, bytes: &[u8]) -> Result<(), S::Error> {
94 self.source.write_slice(bytes)
95 }
96}
97
98impl<S: buffer::raw::Source> AsRef<[u8]> for State<S> {
99 fn as_ref(&self) -> &[u8] {
100 self.source.as_ref()
101 }
102}
103
104impl<S> Complete<S> {
105 pub fn into_parts(self) -> (S, usize, NonZero<u32>) {
108 (self.source, self.end.fields() as usize, self.end.wire_len())
109 }
110}