1use super::utils::{safe_copy, set_zero};
2use libc::{c_void, free, malloc, posix_memalign};
3use nix::errno::Errno;
4use std::slice;
5use std::{
6 fmt,
7 ops::{Deref, DerefMut},
8 ptr::{NonNull, null_mut},
9};
10
11#[repr(C)]
39pub struct Buffer {
40 buf_ptr: NonNull<c_void>,
41 pub(crate) size: u32,
43 pub(crate) cap: u32,
45}
46
47impl fmt::Debug for Buffer {
48 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
49 write!(f, "buffer {:p} size {}", self.get_raw(), self.len())
50 }
51}
52
53unsafe impl Send for Buffer {}
54
55unsafe impl Sync for Buffer {}
56
57pub const MIN_ALIGN: u32 = 512;
58pub const MAX_BUFFER_SIZE: u32 = 1 << 31;
59
60fn is_aligned(offset: usize, size: usize) -> bool {
61 (offset & (MIN_ALIGN as usize - 1) == 0) && (size & (MIN_ALIGN as usize - 1) == 0)
62}
63
64impl Buffer {
65 #[inline]
72 pub fn aligned(size: i32) -> Result<Buffer, Errno> {
73 let mut _buf = Self::_alloc(MIN_ALIGN, size)?;
74 #[cfg(all(feature = "fail", feature = "rand"))]
75 fail::fail_point!("alloc_buf", |_| {
76 rand_buffer(&mut _buf);
77 return Ok(_buf);
78 });
79 Ok(_buf)
80 }
81
82 #[inline]
91 pub fn aligned_by(size: i32, align: u32) -> Result<Buffer, Errno> {
92 let mut _buf = Self::_alloc(align, size)?;
93 #[cfg(all(feature = "fail", feature = "rand"))]
94 fail::fail_point!("alloc_buf", |_| {
95 rand_buffer(&mut _buf);
96 return Ok(_buf);
97 });
98 Ok(_buf)
99 }
100
101 #[inline]
108 pub fn alloc(size: i32) -> Result<Buffer, Errno> {
109 let mut _buf = Self::_alloc(0, size)?;
110 #[cfg(all(feature = "fail", feature = "rand"))]
111 fail::fail_point!("alloc_buf", |_| {
112 rand_buffer(&mut _buf);
113 return Ok(_buf);
114 });
115 Ok(_buf)
116 }
117
118 #[inline]
122 fn _alloc(align: u32, size: i32) -> Result<Self, Errno> {
123 assert!(size > 0);
124 let mut ptr: *mut c_void = null_mut();
125 if align > 0 {
126 debug_assert!((align & (MIN_ALIGN - 1)) == 0);
127 debug_assert!((size as u32 & (align - 1)) == 0);
128 unsafe {
129 let res = posix_memalign(&mut ptr, align as libc::size_t, size as libc::size_t);
130 if res != 0 {
131 return Err(Errno::ENOMEM);
132 }
133 }
134 } else {
135 ptr = unsafe { malloc(size as libc::size_t) };
136 if ptr.is_null() {
137 return Err(Errno::ENOMEM);
138 }
139 }
140 let _size = size as u32 | MAX_BUFFER_SIZE;
142 let _cap = _size;
144 Ok(Self { buf_ptr: unsafe { NonNull::new_unchecked(ptr) }, size: _size, cap: _cap })
145 }
146
147 pub unsafe fn make_ref_const(&self) -> Self {
155 Self {
158 buf_ptr: self.buf_ptr,
159 size: self.size ^ MAX_BUFFER_SIZE,
160 cap: self.cap ^ MAX_BUFFER_SIZE,
161 }
162 }
163
164 #[inline]
172 pub unsafe fn force_owned(&mut self) {
173 self.size |= MAX_BUFFER_SIZE;
175 self.cap |= MAX_BUFFER_SIZE;
176 }
177
178 #[inline]
186 pub unsafe fn from_c_ref_mut(ptr: *mut c_void, size: i32) -> Self {
187 assert!(size >= 0);
188 assert!(!ptr.is_null());
189 let _cap = size as u32 | MAX_BUFFER_SIZE;
192 Self { buf_ptr: unsafe { NonNull::new_unchecked(ptr) }, size: size as u32, cap: _cap }
193 }
194
195 #[inline]
203 pub unsafe fn from_c_ref_const(ptr: *const c_void, size: i32) -> Self {
204 assert!(size >= 0);
205 assert!(!ptr.is_null());
206 Self {
209 buf_ptr: unsafe { NonNull::new_unchecked(ptr as *mut c_void) },
210 size: size as u32,
211 cap: size as u32,
212 }
213 }
214
215 #[inline(always)]
217 pub fn is_owned(&self) -> bool {
218 self.size & (MAX_BUFFER_SIZE) != 0
219 }
220
221 #[inline(always)]
223 pub fn is_mutable(&self) -> bool {
224 self.cap & (MAX_BUFFER_SIZE) != 0
225 }
226
227 #[inline(always)]
229 pub fn len(&self) -> usize {
230 let size = self.size & (MAX_BUFFER_SIZE - 1);
231 size as usize
232 }
233
234 #[inline(always)]
236 pub fn capacity(&self) -> usize {
237 let cap = self.cap & (MAX_BUFFER_SIZE - 1);
238 cap as usize
239 }
240
241 #[inline(always)]
243 pub fn set_len(&mut self, len: usize) {
244 assert!(
245 len < MAX_BUFFER_SIZE as usize,
246 "size {} >= {} is not supported",
247 len,
248 MAX_BUFFER_SIZE
249 );
250 assert!(len <= self.cap as usize, "size {} must be <= {}", len, self.cap);
251 let owned: u32 = self.size & MAX_BUFFER_SIZE;
252 self.size = owned | len as u32;
253 }
254
255 #[inline(always)]
256 fn _as_ref(&self) -> &[u8] {
257 unsafe { slice::from_raw_parts(self.buf_ptr.as_ptr() as *const u8, self.len()) }
258 }
259
260 #[inline(always)]
264 fn _as_mut(&mut self) -> &mut [u8] {
265 #[cfg(debug_assertions)]
266 {
267 if !self.is_mutable() {
268 panic!("Cannot change a mutable buffer")
269 }
270 }
271 unsafe { slice::from_raw_parts_mut(self.buf_ptr.as_ptr() as *mut u8, self.len()) }
272 }
273
274 #[inline(always)]
276 pub fn is_aligned(&self) -> bool {
277 is_aligned(self.buf_ptr.as_ptr() as usize, self.capacity())
278 }
279
280 #[inline]
282 pub fn get_raw(&self) -> *const u8 {
283 self.buf_ptr.as_ptr() as *const u8
284 }
285
286 #[inline]
288 pub fn get_raw_mut(&mut self) -> *mut u8 {
289 self.buf_ptr.as_ptr() as *mut u8
290 }
291
292 #[inline]
304 pub fn copy_from(&mut self, offset: usize, src: &[u8]) {
305 let size = self.len();
306 let dst = self.as_mut();
307 if offset > 0 {
308 assert!(offset < size);
309 safe_copy(&mut dst[offset..], src);
310 } else {
311 safe_copy(dst, src);
312 }
313 }
314
315 #[inline]
321 pub fn copy_and_clean(&mut self, offset: usize, other: &[u8]) {
322 let size = self.len();
323 let dst = self.as_mut();
324 assert!(offset < size);
325 let end: usize = if offset > 0 {
326 set_zero(&mut dst[0..offset]);
327 offset + safe_copy(&mut dst[offset..], other)
328 } else {
329 safe_copy(dst, other)
330 };
331 if size > end {
332 set_zero(&mut dst[end..]);
333 }
334 }
335
336 #[inline]
338 pub fn zero(&mut self) {
339 set_zero(self);
340 }
341
342 #[inline]
344 pub fn set_zero(&mut self, offset: usize, len: usize) {
345 let _len = self.len();
346 let mut end = offset + len;
347 if end > _len {
348 end = _len;
349 }
350 let buf = self.as_mut();
351 if offset > 0 || end < _len {
352 set_zero(&mut buf[offset..end]);
353 } else {
354 set_zero(buf);
355 }
356 }
357}
358
359impl Clone for Buffer {
362 fn clone(&self) -> Self {
363 let mut new_buf = if self.is_aligned() {
364 Self::aligned(self.capacity() as i32).unwrap()
365 } else {
366 Self::alloc(self.capacity() as i32).unwrap()
367 };
368 if self.len() != self.capacity() {
369 new_buf.set_len(self.len());
370 }
371 safe_copy(new_buf.as_mut(), self.as_ref());
372 new_buf
373 }
374}
375
376impl Drop for Buffer {
378 fn drop(&mut self) {
379 if self.is_owned() {
380 unsafe {
381 free(self.buf_ptr.as_ptr());
382 }
383 }
384 }
385}
386
387impl From<Buffer> for Vec<u8> {
389 fn from(mut val: Buffer) -> Self {
390 if !val.is_owned() {
391 panic!("buffer is c ref, not owned");
392 }
393 val.size &= MAX_BUFFER_SIZE - 1;
395 unsafe {
396 Vec::<u8>::from_raw_parts(val.buf_ptr.as_ptr() as *mut u8, val.len(), val.capacity())
397 }
398 }
399}
400
401impl From<Vec<u8>> for Buffer {
403 fn from(buf: Vec<u8>) -> Self {
404 let size = buf.len();
405 let cap = buf.capacity();
406 assert!(
407 size < MAX_BUFFER_SIZE as usize,
408 "size {} >= {} is not supported",
409 size,
410 MAX_BUFFER_SIZE
411 );
412 assert!(
413 cap < MAX_BUFFER_SIZE as usize,
414 "cap {} >= {} is not supported",
415 cap,
416 MAX_BUFFER_SIZE
417 );
418 let _size = size as u32 | MAX_BUFFER_SIZE;
420 let _cap = cap as u32 | MAX_BUFFER_SIZE;
422 Buffer {
423 buf_ptr: unsafe { NonNull::new_unchecked(buf.leak().as_mut_ptr() as *mut c_void) },
424 size: _size,
425 cap: _cap,
426 }
427 }
428}
429
430impl Deref for Buffer {
431 type Target = [u8];
432
433 #[inline]
434 fn deref(&self) -> &[u8] {
435 self._as_ref()
436 }
437}
438
439impl AsRef<[u8]> for Buffer {
440 #[inline]
441 fn as_ref(&self) -> &[u8] {
442 self._as_ref()
443 }
444}
445
446impl AsMut<[u8]> for Buffer {
450 #[inline]
451 fn as_mut(&mut self) -> &mut [u8] {
452 self._as_mut()
453 }
454}
455
456impl DerefMut for Buffer {
457 #[inline]
458 fn deref_mut(&mut self) -> &mut [u8] {
459 self._as_mut()
460 }
461}