Skip to main content

dope_core/io/
provided.rs

1use std::cell::Cell;
2use std::ptr::NonNull;
3use std::slice;
4
5use crate::driver::buffers::ProvidedBuffers;
6use crate::driver::{DriverContext, DriverRef};
7
8pub struct ProvidedLease<'d> {
9    driver: DriverRef<'d>,
10    bid: Cell<Option<u16>>,
11    ptr: NonNull<u8>,
12    len: usize,
13}
14
15pub struct ProvidedView<'d> {
16    _lease: ProvidedLease<'d>,
17    ptr: NonNull<u8>,
18    len: usize,
19}
20
21impl<'d> ProvidedLease<'d> {
22    /// # Safety
23    /// `bid` and the region must name one live unique completion buffer.
24    pub(crate) unsafe fn from_raw_completion(
25        driver: DriverRef<'d>,
26        bid: u16,
27        ptr: NonNull<u8>,
28        len: usize,
29    ) -> Self {
30        Self {
31            driver,
32            bid: Cell::new(Some(bid)),
33            ptr,
34            len,
35        }
36    }
37
38    pub fn as_slice(&self) -> &[u8] {
39        unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
40    }
41
42    pub fn range_of(&self, bytes: &[u8]) -> Option<(usize, usize)> {
43        let base = self.ptr.as_ptr().addr();
44        let start = bytes.as_ptr().addr();
45        let offset = start.checked_sub(base)?;
46        (offset <= self.len && bytes.len() <= self.len - offset).then_some((offset, bytes.len()))
47    }
48
49    pub fn into_view(self, offset: usize, len: usize) -> Result<ProvidedView<'d>, Self> {
50        if offset > self.len || len > self.len - offset {
51            return Err(self);
52        }
53        let ptr = unsafe { NonNull::new_unchecked(self.ptr.as_ptr().add(offset)) };
54        Ok(ProvidedView {
55            _lease: self,
56            ptr,
57            len,
58        })
59    }
60
61    pub fn release(&self, driver: &mut DriverContext<'_, 'd>) {
62        let _ = self.driver;
63        if let Some(bid) = self.bid.take() {
64            unsafe { driver.release(bid) };
65        }
66    }
67}
68
69impl AsRef<[u8]> for ProvidedLease<'_> {
70    fn as_ref(&self) -> &[u8] {
71        self.as_slice()
72    }
73}
74
75impl Drop for ProvidedLease<'_> {
76    fn drop(&mut self) {
77        if let Some(bid) = self.bid.take() {
78            self.driver.return_buffer(bid);
79        }
80    }
81}
82
83impl ProvidedView<'_> {
84    pub fn as_slice(&self) -> &[u8] {
85        unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
86    }
87
88    pub fn len(&self) -> usize {
89        self.len
90    }
91
92    pub fn is_empty(&self) -> bool {
93        self.len == 0
94    }
95
96    pub fn advance(&mut self, count: usize) {
97        assert!(
98            count <= self.len,
99            "dope: provided view advance out of bounds"
100        );
101        self.ptr = unsafe { NonNull::new_unchecked(self.ptr.as_ptr().add(count)) };
102        self.len -= count;
103    }
104}
105
106impl AsRef<[u8]> for ProvidedView<'_> {
107    fn as_ref(&self) -> &[u8] {
108        self.as_slice()
109    }
110}