sark-http 0.28.3

HTTP wire types, semantics, codecs, and ownership invariants for Sark
Documentation
use table::{
    ring::{Buf, Cursor},
    slot::Slot,
    state,
};

use crate::payload::compress::dynamic::{ENTRY_OVERHEAD, Field, mode, table};

pub(in crate::payload::compress::dynamic::table) struct Push<'a, M: mode::Kind> {
    parts: table::PartsMut<'a, M>,
    physical: u32,
    len: u32,
    tail: Cursor,
    size: u32,
}

pub(in crate::payload::compress::dynamic::table) struct Ready<'a, M: mode::Kind> {
    parts: table::PartsMut<'a, M>,
    physical: u32,
    len: u32,
    size: u32,
}

pub(in crate::payload::compress::dynamic::table) struct Pop<'a, M: mode::Kind> {
    parts: table::PartsMut<'a, M>,
    physical: u32,
    len: u32,
    size: u32,
}

impl<'a, M: mode::Kind> Push<'a, M> {
    pub(in crate::payload::compress::dynamic::table) const fn raw(&self) -> u32 {
        self.physical
    }

    pub(in crate::payload::compress::dynamic::table) fn parts(&self) -> &table::PartsMut<'a, M> {
        &self.parts
    }

    pub(in crate::payload::compress::dynamic::table) unsafe fn bytes_mut(&mut self) -> &mut [u8] {
        self.parts.index
    }

    pub(in crate::payload::compress::dynamic::table) fn commit(self) {
        let entries = &mut self.parts.state.entries;
        entries.front = self.physical;
        entries.len = self.len;
        entries.tail = self.tail;
        entries.size = self.size;
    }
}

impl<'a, M: mode::Kind> Ready<'a, M> {
    pub(in crate::payload::compress::dynamic::table) fn admit(
        parts: table::PartsMut<'a, M>,
        add: state::Size,
    ) -> state::Admission<'a, M> {
        let state = &parts.state;
        let entries = &state.entries;
        let count = state.layout.period.get();
        if entries.len != 0
            && (entries.size as u64 + add.get() as u64 > u64::from(entries.limit)
                || entries.len >= count)
        {
            return state::Admission::Evict(Pop::last(parts));
        }
        let physical = if entries.len == 0 {
            0
        } else if entries.front == 0 {
            count - 1
        } else {
            entries.front - 1
        };
        let len = entries.len + 1;
        let size = entries.size + ENTRY_OVERHEAD as u32 + add.0;
        state::Admission::Ready(Self {
            parts,
            physical,
            len,
            size,
        })
    }
    pub(in crate::payload::compress::dynamic::table) fn encode(
        &mut self,
        field: Field<'_>,
    ) -> (Slot, Cursor) {
        let start = self.parts.state.entries.tail();
        let slot = Slot::pack(start, field.name.len(), field.validation);
        let mut ring = Buf::new(self.parts.arena);
        let (first, second) = field.name.parts();
        let cursor = ring.write(start, first);
        let cursor = ring.write(cursor, second);
        let (first, second) = field.value.parts();
        let cursor = ring.write(cursor, first);
        let tail = ring.write(cursor, second);
        (slot, tail)
    }

    pub(in crate::payload::compress::dynamic::table) fn finish(
        self,
        record: M::Record,
        tail: Cursor,
    ) -> Push<'a, M> {
        let parts = self.parts;
        unsafe {
            parts
                .ledger
                .as_mut_ptr()
                .add(self.physical as usize)
                .write(record)
        };
        Push {
            parts,
            physical: self.physical,
            len: self.len,
            tail,
            size: self.size,
        }
    }
}

impl<'a, M: mode::Kind> Pop<'a, M> {
    pub(in crate::payload::compress::dynamic::table) fn oldest(
        parts: table::PartsMut<'a, M>,
    ) -> Option<Self> {
        let entries = &parts.state.entries;
        if entries.len == 0 || entries.size <= entries.limit {
            return None;
        }
        Some(Self::last(parts))
    }

    fn last(parts: table::PartsMut<'a, M>) -> Self {
        let entries = &parts.state.entries;
        let count = parts.state.layout.period;
        let len = entries.len - 1;
        let physical = state::position(count, entries.front, len);
        let start = M::slot(unsafe { parts.ledger.get_unchecked(physical as usize) }).start();
        let end = if len == 0 {
            entries.tail
        } else {
            let newer = state::position(count, entries.front, len - 1) as usize;
            M::slot(unsafe { parts.ledger.get_unchecked(newer) }).start()
        };
        let distance = start.distance(end, parts.state.layout.arena_len);
        let size = if distance == 0 && len == 0 {
            0
        } else {
            entries.size - ENTRY_OVERHEAD as u32 - distance
        };
        Self {
            parts,
            physical,
            len,
            size,
        }
    }

    pub(in crate::payload::compress::dynamic::table) const fn raw(&self) -> u32 {
        self.physical
    }

    pub(in crate::payload::compress::dynamic::table) fn parts(&self) -> &table::PartsMut<'a, M> {
        &self.parts
    }

    pub(in crate::payload::compress::dynamic::table) unsafe fn bytes_mut(&mut self) -> &mut [u8] {
        self.parts.index
    }
}

impl Pop<'_, mode::Direct> {
    pub(in crate::payload::compress::dynamic::table) fn commit(self) {
        let entries = &mut self.parts.state.entries;
        entries.size = self.size;
        entries.len = self.len;
        entries.reset();
    }
}

impl<'a> Pop<'a, mode::Staged> {
    pub(in crate::payload::compress::dynamic::table) fn commit(
        self,
    ) -> table::PartsMut<'a, mode::Staged> {
        let entries = &mut self.parts.state.entries;
        entries.size = self.size;
        entries.len = self.len;
        entries.reset();
        self.parts
    }
}

const _: () = {
    assert!(size_of::<Push<'_, mode::Direct>>() == 9 * size_of::<usize>());
    assert!(size_of::<Pop<'_, mode::Direct>>() == 9 * size_of::<usize>());
    assert!(size_of::<Ready<'_, mode::Direct>>() == 9 * size_of::<usize>());
};