dope-session 0.2.0

Thin io_uring adaptor with "Manifolds"
Documentation
use core::marker::PhantomData;

use dambi::{ByteBufferMut, Bytes};

use crate::protocol::client::ClientFramer;

#[repr(C)]
pub(crate) struct FrameRing<F: ClientFramer, const CAP: usize> {
    buf: ByteBufferMut,
    head: u16,
    tail: u16,
    _framer: PhantomData<fn() -> F>,
}

impl<F: ClientFramer, const CAP: usize> FrameRing<F, CAP> {
    #[inline(always)]
    pub(crate) fn new() -> Self {
        const {
            assert!(CAP <= u16::MAX as usize, "FrameRing CAP must fit u16");
        }
        Self {
            buf: ByteBufferMut::with_capacity(CAP),
            head: 0,
            tail: 0,
            _framer: PhantomData,
        }
    }

    #[must_use = "remainder dropped if ignored"]
    #[inline(always)]
    pub(crate) fn append(&mut self, src: &[u8]) -> usize {
        let head = self.head as usize;
        let n = src.len().min(CAP - head);
        if n > 0 {
            self.buf.ensure_unique_for_mutate(head);

            unsafe {
                std::ptr::copy_nonoverlapping(src.as_ptr(), self.buf.data_mut_ptr().add(head), n);
            }
            self.head = (head + n) as u16;
        }
        n
    }

    #[inline(always)]
    pub(crate) fn drain<H>(&mut self, framer: &mut F, mut handler: H)
    where
        H: FnMut(<F as ClientFramer>::Head),
    {
        loop {
            let t = self.tail as usize;
            let h = self.head as usize;
            if h <= t {
                break;
            }
            let pending = Bytes::from_byte_buffer_range(self.buf.share(), t as u32, (h - t) as u32);
            let Some((parsed, consumed)) = framer.parse(&pending) else {
                break;
            };
            if consumed > h - t {
                break;
            }
            self.tail = (t + consumed) as u16;
            handler(parsed);
        }
        self.compact();
    }

    fn compact(&mut self) {
        let t = self.tail as usize;
        let h = self.head as usize;
        if t == 0 {
            return;
        }
        if t >= h {
            self.head = 0;
            self.tail = 0;
            return;
        }
        let unparsed = h - t;
        self.buf.ensure_unique_for_mutate(h);

        unsafe {
            std::ptr::copy(
                self.buf.data_ptr().add(t),
                self.buf.data_mut_ptr(),
                unparsed,
            );
        }
        self.head = unparsed as u16;
        self.tail = 0;
    }
}

impl<F: ClientFramer, const CAP: usize> Default for FrameRing<F, CAP> {
    #[inline(always)]
    fn default() -> Self {
        Self::new()
    }
}