dope 0.5.6

The manifold runtime
Documentation
use crate::transport::link::Core;
use crate::{Driver, backend};

pub struct Vectored<'a> {
    pub iovs: &'a [backend::socket::IoVec],
    pub iov_storage: &'a mut [backend::socket::IoVec],
    pub msghdr_storage: &'a mut backend::socket::MsgHdr,
}

impl<'a> Vectored<'a> {
    pub(super) fn install_into_msghdr(&mut self) {
        let n = self.iovs.len();
        self.iov_storage[..n].copy_from_slice(self.iovs);
        self.msghdr_storage.set_iov(&self.iov_storage[..n]);
    }

    pub(super) fn msghdr_storage(&self) -> &backend::socket::MsgHdr {
        self.msghdr_storage
    }
}

pub enum RecvChunk<'a> {
    Borrowed(&'a [u8]),
    Owned(Vec<u8>),
}

impl<'a> RecvChunk<'a> {
    pub fn as_slice(&self) -> &[u8] {
        match self {
            Self::Borrowed(b) => b,
            Self::Owned(v) => v.as_slice(),
        }
    }

    pub fn len(&self) -> usize {
        self.as_slice().len()
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
}

pub enum Reclaim {
    OnSubmit,
    OnComplete,
}

pub trait Wire: 'static + Sized {
    type InitConfig: 'static + Clone + Default;

    const RECLAIM: Reclaim;

    fn new(cfg: &Self::InitConfig) -> Self;

    fn process_recv<'a>(&mut self, bytes: &'a [u8]) -> Option<RecvChunk<'a>>;

    fn on_recv_eof(&mut self) {}

    fn submit_send(
        &mut self,
        core: &mut Core,
        plain: &[u8],
        ud: backend::token::Token,
        driver: &mut Driver,
    ) -> usize;

    fn submit_send_vectored(
        &mut self,
        core: &mut Core,
        vectored: Vectored<'_>,
        ud: backend::token::Token,
        driver: &mut Driver,
    ) -> usize;

    fn submit_send_tracked(
        &mut self,
        core: &mut Core,
        plain: &[u8],
        ud: backend::token::Token,
        driver: &mut Driver,
    ) -> Option<usize> {
        let was_inflight = core.is_send_inflight();
        let consumed = self.submit_send(core, plain, ud, driver);
        (core.is_send_inflight() && !was_inflight).then_some(consumed)
    }

    fn submit_send_vectored_tracked(
        &mut self,
        core: &mut Core,
        vectored: Vectored<'_>,
        ud: backend::token::Token,
        driver: &mut Driver,
    ) -> Option<usize> {
        let was_inflight = core.is_send_inflight();
        let consumed = self.submit_send_vectored(core, vectored, ud, driver);
        (core.is_send_inflight() && !was_inflight).then_some(consumed)
    }

    fn after_send_cqe(
        &mut self,
        core: &mut Core,
        n: usize,
        ud: backend::token::Token,
        driver: &mut Driver,
    ) -> bool;

    fn flush_pending(&mut self, core: &mut Core, ud: backend::token::Token, driver: &mut Driver);

    fn on_graceful_close(
        &mut self,
        _core: &mut Core,
        _ud: backend::token::Token,
        _driver: &mut Driver,
    ) {
    }
}

pub struct Identity;

impl Wire for Identity {
    type InitConfig = ();

    const RECLAIM: Reclaim = Reclaim::OnComplete;

    fn new(_: &()) -> Self {
        Identity
    }

    fn process_recv<'a>(&mut self, bytes: &'a [u8]) -> Option<RecvChunk<'a>> {
        Some(RecvChunk::Borrowed(bytes))
    }

    fn submit_send(
        &mut self,
        core: &mut Core,
        plain: &[u8],
        ud: backend::token::Token,
        driver: &mut Driver,
    ) -> usize {
        if plain.is_empty() {
            return 0;
        }
        core.submit_single(ud, plain, driver);
        plain.len()
    }

    fn submit_send_vectored(
        &mut self,
        core: &mut Core,
        vectored: Vectored<'_>,
        ud: backend::token::Token,
        driver: &mut Driver,
    ) -> usize {
        if vectored.iovs.is_empty() {
            return 0;
        }
        let consumed: usize = vectored.iovs.iter().map(|v| v.len()).sum();
        core.submit_vectored(ud, vectored, driver);
        consumed
    }

    fn after_send_cqe(
        &mut self,
        _core: &mut Core,
        _n: usize,
        _ud: backend::token::Token,
        _driver: &mut Driver,
    ) -> bool {
        false
    }

    fn flush_pending(
        &mut self,
        _core: &mut Core,
        _ud: backend::token::Token,
        _driver: &mut Driver,
    ) {
    }
}