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 range_of(&self, bytes: &[u8]) -> Option<ProvidedSpan> {
42        let base = self.region.ptr.as_ptr().addr();
43        let start = bytes.as_ptr().addr();
44        let offset = start.checked_sub(base)?;
45        if offset > self.region.len || bytes.len() > self.region.len - offset {
46            return None;
47        }
48        Some(ProvidedSpan {
49            offset,
50            len: bytes.len(),
51        })
52    }
53
54    pub fn into_view(self, span: ProvidedSpan) -> Result<ProvidedView<'d>, Self> {
55        let Some(region) = self.region.subregion(span.offset, span.len) else {
56            return Err(self);
57        };
58        Ok(ProvidedView {
59            _lease: self,
60            region,
61        })
62    }
63
64    pub fn release(&self, driver: &mut DriverContext<'_, 'd>) {
65        let _ = self.driver;
66        if let Some(id) = self.id.take() {
67            driver.release_buffer(id);
68        }
69    }
70}
71
72impl AsRef<[u8]> for ProvidedLease<'_> {
73    fn as_ref(&self) -> &[u8] {
74        self.as_slice()
75    }
76}
77
78impl Drop for ProvidedLease<'_> {
79    fn drop(&mut self) {
80        if let Some(id) = self.id.take() {
81            self.driver.return_buffer(id);
82        }
83    }
84}
85
86impl ProvidedView<'_> {
87    pub fn as_slice(&self) -> &[u8] {
88        self.region.as_slice()
89    }
90
91    pub fn len(&self) -> usize {
92        self.region.len()
93    }
94
95    pub fn is_empty(&self) -> bool {
96        self.region.len() == 0
97    }
98
99    pub fn advance(&mut self, count: usize) {
100        assert!(
101            self.region.advance(count),
102            "dope: provided view advance out of bounds"
103        );
104    }
105}
106
107impl AsRef<[u8]> for ProvidedView<'_> {
108    fn as_ref(&self) -> &[u8] {
109        self.as_slice()
110    }
111}