dope-net 0.10.0

The manifold runtime
Documentation
use std::ptr;
use std::slice;

use dope_core::io::socket::msg::IoVec;

use super::super::EGRESS_QUANTUM;
use super::super::metadata::raw::pool::MetadataPool;

#[allow(clippy::large_enum_variant)]
pub(crate) enum Entry<B> {
    Retained {
        value: B,
        data: *const u8,
        len: usize,
    },
    Wire {
        data: *const u8,
        len: usize,
    },
    Inline {
        data: [u8; EGRESS_QUANTUM],
        len: u16,
    },
    Static {
        data: *const u8,
        len: usize,
    },
}

pub(crate) enum PreparedEntry {
    Empty,
    Node {
        index: u32,
        bytes: usize,
        resident: usize,
    },
}

impl<B> Entry<B> {
    pub(crate) fn retained(value: B) -> Self {
        Self::Retained {
            value,
            data: ptr::null(),
            len: 0,
        }
    }

    pub(crate) fn wire(data: *const u8, len: usize) -> Self {
        Self::Wire { data, len }
    }

    pub(crate) fn inline(src: &[u8]) -> Self {
        let mut data = [0; EGRESS_QUANTUM];
        data[..src.len()].copy_from_slice(src);
        Self::Inline {
            data,
            len: src.len() as u16,
        }
    }

    pub(crate) fn static_bytes(src: &'static [u8]) -> Self {
        Self::Static {
            data: src.as_ptr(),
            len: src.len(),
        }
    }

    pub(crate) fn retained_ref(&self) -> Option<&B> {
        match self {
            Self::Retained { value, .. } => Some(value),
            _ => None,
        }
    }

    pub(crate) fn len(&self) -> usize {
        match self {
            Self::Retained { len, .. } | Self::Wire { len, .. } | Self::Static { len, .. } => *len,
            Self::Inline { len, .. } => *len as usize,
        }
    }

    pub(crate) fn wire_len(&self) -> Option<usize> {
        match self {
            Self::Wire { len, .. } => Some(*len),
            _ => None,
        }
    }

    pub(crate) fn iov(&self, offset: usize, cap: usize) -> Option<(IoVec, usize)> {
        let (data, len) = match self {
            Self::Retained { data, len, .. }
            | Self::Wire { data, len }
            | Self::Static { data, len } => (*data, *len),
            Self::Inline { data, len } => (data.as_ptr(), *len as usize),
        };
        if offset >= len {
            return None;
        }
        let available = len - offset;
        let take = available.min(cap);
        let bytes = unsafe { slice::from_raw_parts(data.add(offset), take) };
        Some((IoVec::from_slice(bytes), available))
    }
}

impl<B: AsRef<[u8]>> Entry<B> {
    pub(crate) fn prepare_buffer(pool: &MetadataPool<Self>, value: B) -> Result<PreparedEntry, B> {
        let (index, bytes) = pool.reserve_from(value, Self::retained, Self::prepare_retained)?;
        pool.set_sizes(index, bytes, bytes);
        if bytes == 0 {
            drop(pool.take_node(index));
            return Ok(PreparedEntry::Empty);
        }
        Ok(PreparedEntry::Node {
            index,
            bytes,
            resident: bytes,
        })
    }

    pub(crate) fn prepare_wire(
        pool: &MetadataPool<Self>,
        data: *const u8,
        len: usize,
    ) -> Option<PreparedEntry> {
        if len == 0 {
            return Some(PreparedEntry::Empty);
        }
        let (index, bytes) = pool
            .reserve_from((data, len), |(data, len)| Self::wire(data, len), |_| len)
            .ok()?;
        pool.set_sizes(index, bytes, bytes);
        Some(PreparedEntry::Node {
            index,
            bytes,
            resident: bytes,
        })
    }

    pub(crate) fn prepare_copy(pool: &MetadataPool<Self>, src: &[u8]) -> Option<PreparedEntry> {
        debug_assert!(!src.is_empty() && src.len() <= EGRESS_QUANTUM);
        let (index, bytes) = pool
            .reserve_from(src, Self::inline, |entry| entry.len())
            .ok()?;
        pool.set_sizes(index, bytes, bytes);
        Some(PreparedEntry::Node {
            index,
            bytes,
            resident: bytes,
        })
    }

    pub(crate) fn prepare_static(
        pool: &MetadataPool<Self>,
        src: &'static [u8],
    ) -> Option<PreparedEntry> {
        if src.is_empty() {
            return Some(PreparedEntry::Empty);
        }
        let (index, bytes) = pool
            .reserve_from(src, Self::static_bytes, |entry| entry.len())
            .ok()?;
        pool.set_sizes(index, bytes, 0);
        Some(PreparedEntry::Node {
            index,
            bytes,
            resident: 0,
        })
    }

    pub(crate) fn prepare_retained(&mut self) -> usize {
        let Self::Retained { value, data, len } = self else {
            return 0;
        };
        let src = value.as_ref();
        *data = src.as_ptr();
        *len = src.len();
        *len
    }
}