Skip to main content

dope_core/io/socket/msg/
raw.rs

1use core::slice;
2
3use crate::io::{socket::msg, transfer};
4
5pub trait Iovec {
6    /// Constructs a retained iovec.
7    /// # Safety
8    /// The bytes stay fixed through terminal completion or quiescence.
9    unsafe fn retain(self) -> msg::Iovec;
10}
11
12impl Iovec for &[u8] {
13    unsafe fn retain(self) -> msg::Iovec {
14        msg::Iovec::from_slice(self)
15    }
16}
17
18pub trait Vectored<'a> {
19    /// Constructs a retained descriptor graph.
20    /// # Safety
21    /// All inputs stay fixed through completion; length is their bounded sum.
22    unsafe fn retain(self) -> msg::Vectored<'a>;
23}
24
25impl<'a> Vectored<'a> for (&'a mut msg::Header, &'a [msg::Iovec], transfer::Len) {
26    unsafe fn retain(self) -> msg::Vectored<'a> {
27        let (header, iovecs, bytes) = self;
28        debug_assert!(iovecs.len() <= msg::MAX_IOVECS);
29        debug_assert_eq!(
30            Some(bytes.into_usize()),
31            iovecs
32                .iter()
33                .try_fold(0usize, |total, iovec| total.checked_add(iovec.len()))
34        );
35        *header = msg::Header::new();
36        header.bind_iovs(iovecs);
37        msg::Vectored::from_parts(header, iovecs, bytes)
38    }
39}
40
41pub(super) trait Project<'a> {
42    fn slice(self) -> &'a [u8];
43}
44
45impl<'a> Project<'a> for &'a msg::Iovec {
46    fn slice(self) -> &'a [u8] {
47        // SAFETY: construction proves the bytes live for the graph lifetime.
48        unsafe { slice::from_raw_parts(self.raw.iov_base.cast(), self.raw.iov_len) }
49    }
50}
51
52pub struct Part<'a> {
53    slice: &'a [u8],
54    bytes: transfer::Len,
55}
56
57impl<'a> Part<'a> {
58    /// # Safety
59    /// `slice.len()` must not exceed [`transfer::MAX_BYTES`].
60    #[must_use]
61    pub unsafe fn from_bounded(slice: &'a [u8]) -> Self {
62        debug_assert!(slice.len() <= transfer::MAX_BYTES);
63        Self {
64            slice,
65            bytes: transfer::Len::from_bounded(slice.len()),
66        }
67    }
68
69    pub(super) fn into_parts(self) -> (&'a [u8], transfer::Len) {
70        (self.slice, self.bytes)
71    }
72}