dope_core/io/provided/
mod.rs1use 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}