sark-http 0.28.6

HTTP wire types, semantics, codecs, and ownership invariants for Sark
Documentation
use o3::buffer::write::{self, consume};

use crate::field::metadata::{block, huffman::decoder, lower, section::storage, strings};

pub(super) struct Scratch {
    bytes: Vec<u8>,
    scan: block::Value,
}

impl Scratch {
    pub(super) fn new(bytes: Vec<u8>) -> Self {
        Self {
            bytes,
            scan: block::Value::new(),
        }
    }

    pub(super) fn into_vec(self) -> Vec<u8> {
        self.bytes
    }

    pub(super) fn into_parts(self) -> (Vec<u8>, block::Validation) {
        (self.bytes, self.scan.finish())
    }

    pub(super) fn string(
        mut self,
        mut cursor: strings::Cursor,
        input: &[u8],
    ) -> (Self, lower::Step) {
        let bound = match cursor.output_bound(input.len()) {
            Ok(bound) => bound,
            Err(cause) => return (self, lower::Step::Bound { cause }),
        };
        if let Err(cause) = storage::try_reserve(&mut self.bytes, bound) {
            return (
                self,
                lower::Step::Store {
                    cause: lower::Error::Scratch(cause),
                },
            );
        }
        let current = self.bytes.len();
        let rest = cursor.remaining();
        let sink = Writer {
            bytes: write::Reserved::from(&mut self.bytes).into_staged(),
            scan: &mut self.scan,
        };
        let step = match cursor.feed_into(input, sink) {
            Ok((_, sink)) => {
                sink.bytes.commit();
                lower::Step::Ready { cursor }
            }
            Err(failure) => {
                let decoder::Failure {
                    sink,
                    cause,
                    progress,
                } = failure;
                let stored = [current, current + sink.bytes.len()];
                sink.bytes.commit();
                match cause {
                    decoder::DecodeError::InvalidEncoding(cause) => lower::Step::Decode {
                        cause: decoder::DecodeError::InvalidEncoding(cause),
                        progress,
                    },
                    decoder::DecodeError::Sink(cause) => lower::Step::Store {
                        cause: lower::Error::SinkProgress {
                            cause,
                            stored,
                            remaining: rest,
                            input: [input.len(), progress.consumed(), progress.decoded()],
                        },
                    },
                }
            }
        };
        (self, step)
    }
}

struct Writer<'a> {
    bytes: write::Staged<'a, usize>,
    scan: &'a mut block::Value,
}

impl write::Sink for Writer<'_> {
    type Error = consume::Error;

    fn write_slice(&mut self, bytes: &[u8]) -> Result<(), Self::Error> {
        self.bytes.write_slice(bytes)?;
        self.scan.extend(bytes);
        Ok(())
    }

    fn write_slices<const N: usize>(&mut self, slices: [&[u8]; N]) -> Result<(), Self::Error> {
        self.bytes.write_slices(slices)?;
        for bytes in slices {
            self.scan.extend(bytes);
        }
        Ok(())
    }
}