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 unsafe fn from_completion(driver: &mut DriverContext<'_, 'd>, len: u32, bid: u16) -> Self {
26 let reference = driver.driver_ref();
27 let (ptr, len) = unsafe { driver.buffer_ptr_len(len, bid) };
28 Self {
29 driver: reference,
30 bid: Cell::new(Some(bid)),
31 ptr,
32 len,
33 }
34 }
35
36 pub fn as_slice(&self) -> &[u8] {
37 unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
38 }
39
40 pub fn range_of(&self, bytes: &[u8]) -> Option<(usize, usize)> {
41 let base = self.ptr.as_ptr().addr();
42 let start = bytes.as_ptr().addr();
43 let offset = start.checked_sub(base)?;
44 (offset <= self.len && bytes.len() <= self.len - offset).then_some((offset, bytes.len()))
45 }
46
47 pub fn into_view(self, offset: usize, len: usize) -> ProvidedView<'d> {
48 assert!(offset <= self.len && len <= self.len - offset);
49 let ptr = unsafe { NonNull::new_unchecked(self.ptr.as_ptr().add(offset)) };
50 ProvidedView {
51 _lease: self,
52 ptr,
53 len,
54 }
55 }
56
57 pub fn retained_view(&self, offset: usize, len: usize) -> ProvidedView<'d> {
63 assert!(offset <= self.len && len <= self.len - offset);
64 let bid = self
65 .bid
66 .take()
67 .expect("provided buffer ownership was already transferred");
68 let ptr = unsafe { NonNull::new_unchecked(self.ptr.as_ptr().add(offset)) };
69 ProvidedView {
70 _lease: Self {
71 driver: self.driver,
72 bid: Cell::new(Some(bid)),
73 ptr: self.ptr,
74 len: self.len,
75 },
76 ptr,
77 len,
78 }
79 }
80
81 pub fn release(&self, driver: &mut DriverContext<'_, 'd>) {
82 let _ = self.driver;
83 if let Some(bid) = self.bid.take() {
84 unsafe { driver.release(bid) };
85 }
86 }
87}
88
89impl AsRef<[u8]> for ProvidedLease<'_> {
90 fn as_ref(&self) -> &[u8] {
91 self.as_slice()
92 }
93}
94
95impl Drop for ProvidedLease<'_> {
96 fn drop(&mut self) {
97 if let Some(bid) = self.bid.take() {
98 self.driver.return_buffer(bid);
99 }
100 }
101}
102
103impl ProvidedView<'_> {
104 pub fn as_slice(&self) -> &[u8] {
105 unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) }
106 }
107
108 pub fn len(&self) -> usize {
109 self.len
110 }
111
112 pub fn is_empty(&self) -> bool {
113 self.len == 0
114 }
115
116 pub fn advance(&mut self, count: usize) {
117 assert!(
118 count <= self.len,
119 "dope: provided view advance out of bounds"
120 );
121 self.ptr = unsafe { NonNull::new_unchecked(self.ptr.as_ptr().add(count)) };
122 self.len -= count;
123 }
124}
125
126impl AsRef<[u8]> for ProvidedView<'_> {
127 fn as_ref(&self) -> &[u8] {
128 self.as_slice()
129 }
130}