Skip to main content

dope_core/io/provided/
mod.rs

1use std::cell::Cell;
2
3use crate::driver::{DriverContext, DriverRef};
4
5use self::raw::buffer::BufferId;
6use self::raw::completion::CompletedBuffer;
7use self::raw::region::InitializedRegion;
8
9pub(crate) mod raw;
10
11pub struct ProvidedSpan {
12    offset: usize,
13    len: usize,
14}
15
16pub struct ProvidedLease<'d> {
17    driver: DriverRef<'d>,
18    id: Cell<Option<BufferId>>,
19    region: InitializedRegion,
20}
21
22pub struct ProvidedView<'d> {
23    _lease: ProvidedLease<'d>,
24    region: InitializedRegion,
25}
26
27impl<'d> ProvidedLease<'d> {
28    pub(crate) fn from_completion(driver: DriverRef<'d>, completed: CompletedBuffer) -> Self {
29        let CompletedBuffer { id, region } = completed;
30        Self {
31            driver,
32            id: Cell::new(Some(id)),
33            region,
34        }
35    }
36
37    pub fn as_slice(&self) -> &[u8] {
38        self.region.as_slice()
39    }
40
41    pub fn as_mut_slice(&mut self) -> &mut [u8] {
42        self.region.as_mut_slice()
43    }
44
45    pub fn advance(&mut self, count: usize) {
46        assert!(
47            self.region.advance(count),
48            "dope: provided lease advance out of bounds"
49        );
50    }
51
52    pub fn range_of(&self, bytes: &[u8]) -> Option<ProvidedSpan> {
53        let base = self.region.ptr.as_ptr().addr();
54        let start = bytes.as_ptr().addr();
55        let offset = start.checked_sub(base)?;
56        self.span(offset, bytes.len())
57    }
58
59    pub fn span(&self, offset: usize, len: usize) -> Option<ProvidedSpan> {
60        if offset > self.region.len || len > self.region.len - offset {
61            return None;
62        }
63        Some(ProvidedSpan { offset, len })
64    }
65
66    pub fn into_view(self, span: ProvidedSpan) -> Result<ProvidedView<'d>, Self> {
67        let Some(region) = self.region.subregion(span.offset, span.len) else {
68            return Err(self);
69        };
70        Ok(ProvidedView {
71            _lease: self,
72            region,
73        })
74    }
75
76    pub fn release(&self, driver: &mut DriverContext<'_, 'd>) {
77        let _ = self.driver;
78        if let Some(id) = self.id.take() {
79            driver.release_buffer(id);
80        }
81    }
82}
83
84impl AsRef<[u8]> for ProvidedLease<'_> {
85    fn as_ref(&self) -> &[u8] {
86        self.as_slice()
87    }
88}
89
90impl Drop for ProvidedLease<'_> {
91    fn drop(&mut self) {
92        if let Some(id) = self.id.take() {
93            self.driver.return_buffer(id);
94        }
95    }
96}
97
98impl ProvidedView<'_> {
99    pub fn as_slice(&self) -> &[u8] {
100        self.region.as_slice()
101    }
102
103    pub fn len(&self) -> usize {
104        self.region.len()
105    }
106
107    pub fn is_empty(&self) -> bool {
108        self.region.len() == 0
109    }
110
111    pub fn advance(&mut self, count: usize) {
112        assert!(
113            self.region.advance(count),
114            "dope: provided view advance out of bounds"
115        );
116    }
117}
118
119impl AsRef<[u8]> for ProvidedView<'_> {
120    fn as_ref(&self) -> &[u8] {
121        self.as_slice()
122    }
123}