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 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}