wireshift_core/buffer/
mod.rs1use std::marker::PhantomData;
4
5use crate::error::{Error, Result};
6
7pub(crate) mod pool;
8pub use pool::BufferPool;
9
10pub(crate) const REGISTERED_BUFFER_CAPACITY: usize = 256 * 1024;
11pub(crate) const REGISTERED_BUFFER_COUNT: usize = 32;
12
13#[derive(Debug)]
15pub struct Owned;
16
17#[derive(Debug)]
19pub struct Submitted;
20
21#[derive(Debug)]
23pub struct Completed;
24
25#[derive(Debug)]
27pub struct Pool;
28
29#[derive(Debug)]
30pub(crate) struct PooledBuffer {
31 pub(crate) data: Vec<u8>,
32 pub(crate) reusable: bool,
33}
34
35impl PooledBuffer {
36 pub(crate) fn new(data: Vec<u8>, reusable: bool) -> Self {
37 Self { data, reusable }
38 }
39
40 pub(crate) fn capacity(&self) -> usize {
41 self.data.capacity()
42 }
43
44 pub(crate) fn zero_contents(&mut self) {
45 self.data.fill(0);
46 }
47
48 pub(crate) fn deallocate(self) {
49 drop(self.data);
50 }
51}
52
53#[cfg(test)]
54mod tests;
55
56pub(crate) fn allocate_reusable_buffer(capacity: usize) -> Result<PooledBuffer> {
57 if capacity > 1024 * 1024 * 1024 {
58 return Err(Error::validation(
59 "requested buffer capacity is too large",
60 "request a buffer size less than 1 GiB",
61 ));
62 }
63 let mut data = vec![0; capacity];
68 data.shrink_to_fit();
69 Ok(PooledBuffer::new(data, true))
70}
71
72pub(crate) fn allocate_overflow_buffer(capacity: usize) -> PooledBuffer {
73 let mut data = vec![0; capacity];
74 data.shrink_to_fit();
75 PooledBuffer::new(data, false)
76}
77
78#[derive(Debug)]
80pub struct Buffer<State> {
81 pool: std::sync::Arc<pool::BufferPoolInner>,
82 data: Option<PooledBuffer>,
83 filled: usize,
84 state: PhantomData<State>,
85}
86
87impl<State> Buffer<State> {
88 pub(crate) fn new(
89 pool: std::sync::Arc<pool::BufferPoolInner>,
90 data: PooledBuffer,
91 filled: usize,
92 ) -> Self {
93 Self {
94 pool,
95 data: Some(data),
96 filled,
97 state: PhantomData,
98 }
99 }
100
101 fn data_ref(&self) -> &[u8] {
102 self.data.as_ref().map_or(&[], |data| data.data.as_slice())
103 }
104
105 fn data_mut(&mut self) -> &mut [u8] {
106 self.data
107 .as_mut()
108 .map_or(&mut [], |data| data.data.as_mut_slice())
109 }
110
111 #[must_use]
113 pub fn capacity(&self) -> usize {
114 self.data.as_ref().map_or(0, PooledBuffer::capacity)
115 }
116
117 #[must_use]
119 pub fn filled_len(&self) -> usize {
120 self.filled
121 }
122}
123
124impl Buffer<Owned> {
125 #[must_use]
127 pub fn as_slice(&self) -> &[u8] {
128 self.data_ref()
129 }
130
131 pub fn as_mut_slice(&mut self) -> &mut [u8] {
133 self.data_mut()
134 }
135
136 pub fn set_filled_len(mut self, len: usize) -> Result<Self> {
138 if len > self.capacity() {
139 return Err(Error::validation(
140 "filled length exceeds buffer capacity",
141 "ensure data written does not exceed buffer size",
142 ));
143 }
144 self.filled = len;
145 Ok(self)
146 }
147
148 #[must_use]
150 pub fn into_submitted(mut self) -> Buffer<Submitted> {
151 Buffer {
152 pool: self.pool.clone(),
153 data: self.data.take(),
154 filled: self.filled,
155 state: PhantomData,
156 }
157 }
158}
159
160impl Buffer<Submitted> {
161 #[allow(clippy::needless_pass_by_value)]
166 pub fn from_vec(data: Vec<u8>) -> Result<Self> {
167 if data.is_empty() {
168 return Err(Error::validation(
169 "submitted buffer must be non-empty",
170 "allocate at least one byte before submitting a read buffer",
171 ));
172 }
173 let capacity = data.len();
174 let pool = std::sync::Arc::new(pool::BufferPoolInner {
175 capacity,
176 max_buffers: 1,
177 overflow_on_exhaustion: false,
178 free: crossbeam_queue::ArrayQueue::new(1),
179 });
180 Ok(Buffer::new(pool, PooledBuffer::new(data, false), 0))
181 }
182
183 #[doc(hidden)]
185 pub fn backend_mut(&mut self) -> &mut [u8] {
186 self.data_mut()
187 }
188
189 #[doc(hidden)]
191 #[must_use]
192 pub fn backend_ref(&self) -> &[u8] {
193 self.data_ref()
194 }
195
196 pub fn into_completed(mut self, filled: usize) -> Result<Buffer<Completed>> {
198 if filled > self.capacity() {
199 return Err(Error::validation(
200 "completed length exceeds buffer capacity",
201 "return at most the number of bytes the buffer can hold",
202 ));
203 }
204 Ok(Buffer {
205 pool: self.pool.clone(),
206 data: self.data.take(),
207 filled,
208 state: PhantomData,
209 })
210 }
211}
212
213impl Buffer<Pool> {
214 #[doc(hidden)]
216 pub fn as_mut_slice(&mut self) -> &mut [u8] {
217 self.data_mut()
218 }
219
220 pub fn into_completed(mut self, filled: usize) -> Result<Buffer<Completed>> {
222 if filled > self.capacity() {
223 return Err(Error::validation(
224 "completed length exceeds buffer capacity",
225 "return at most the number of bytes the buffer can hold",
226 ));
227 }
228 Ok(Buffer {
229 pool: self.pool.clone(),
230 data: self.data.take(),
231 filled,
232 state: PhantomData,
233 })
234 }
235}
236
237impl Buffer<Completed> {
238 #[must_use]
240 pub fn filled(&self) -> &[u8] {
241 &self.data_ref()[..self.filled]
242 }
243
244 pub fn truncate(mut self, len: usize) -> Result<Self> {
246 if len > self.filled {
247 return Err(Error::validation(
248 "truncate length exceeds currently filled bytes",
249 "truncate to a length less than or equal to filled_len()",
250 ));
251 }
252 self.filled = len;
253 Ok(self)
254 }
255
256 #[must_use]
258 pub fn release(mut self) -> Buffer<Owned> {
259 let data = self
260 .data
261 .take()
262 .unwrap_or_else(|| allocate_overflow_buffer(0));
263 Buffer::new(self.pool.clone(), data, 0)
264 }
265}
266
267impl<State> Drop for Buffer<State> {
268 fn drop(&mut self) {
269 if let Some(mut data) = self.data.take() {
270 data.zero_contents();
271 if data.reusable {
272 if let Err(data) = self.pool.free.push(data) {
273 data.deallocate();
274 }
275 } else {
276 data.deallocate();
277 }
278 }
279 }
280}