io_buffer/
buffer.rs

1use super::utils::{safe_copy, set_zero};
2use libc;
3use nix::errno::Errno;
4use std::slice;
5use std::{
6    fmt,
7    ops::{Deref, DerefMut},
8};
9
10use fail::fail_point;
11
12/// Buffer is a static type,  size and cap (max to i32). Memory footprint is only 16B.
13///
14/// Can obtain from alloc (uninitialized, mutable and owned),
15///
16/// or wrap a raw pointer from c code (not owned,  mutable or immutable),
17///
18/// or convert `From<Vec<u8>>` (mutable and owned), and `To<Vec<u8>>`
19///
20/// When Clone, will copy the contain into a new Buffer.
21#[repr(C, align(1))]
22pub struct Buffer {
23    buf_ptr: *mut libc::c_void,
24    /// the highest bit of `size` represents `owned`
25    pub(crate) size: u32,
26    /// the highest bit of `cap` represents `mutable`
27    pub(crate) cap: u32,
28}
29
30impl fmt::Debug for Buffer {
31    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32        write!(f, "buffer {:p} size {}", self.get_raw(), self.len())
33    }
34}
35
36unsafe impl Send for Buffer {}
37
38unsafe impl Sync for Buffer {}
39
40pub const MIN_ALIGN: u32 = 512;
41pub const MAX_BUFFER_SIZE: usize = 1 << 31;
42
43fn is_aligned(offset: usize, size: usize) -> bool {
44    return (offset & (MIN_ALIGN as usize - 1) == 0) && (size & (MIN_ALIGN as usize - 1) == 0);
45}
46
47impl Buffer {
48    /// Allocate mutable and owned aligned buffer for aio by posix_memalign(),
49    /// with size set to capacity.
50    ///
51    /// **NOTE**: Be aware that buffer allocated is not initialized.
52    ///
53    /// `size`: must be larger than zero
54    #[inline]
55    pub fn aligned(size: i32) -> Result<Buffer, Errno> {
56        let mut _buf = Self::_alloc(MIN_ALIGN, size)?;
57        fail_point!("alloc_buf", |_| {
58            rand_buffer(&mut _buf);
59            return Ok(_buf);
60        });
61        return Ok(_buf);
62    }
63
64    /// Allocate mutable and owned aligned buffer for aio by posix_memalign(),
65    /// with size set to capacity.
66    ///
67    /// **NOTE**: Be aware that buffer allocated is not initialized.
68    ///
69    /// `size`: must be larger than zero
70    ///
71    /// `align`: normally 512 or 4096
72    #[inline]
73    pub fn aligned_by(size: i32, align: u32) -> Result<Buffer, Errno> {
74        let mut _buf = Self::_alloc(align, size)?;
75        fail_point!("alloc_buf", |_| {
76            rand_buffer(&mut _buf);
77            return Ok(_buf);
78        });
79        return Ok(_buf);
80    }
81
82    /// Allocate mutable and owned non-aligned Buffer by malloc(),
83    /// with size set to capacity.
84    ///
85    /// **NOTE**: Be aware that buffer allocated is not initialized.
86    ///
87    /// `size`: must be larger than zero
88    #[inline]
89    pub fn alloc(size: i32) -> Result<Buffer, Errno> {
90        let mut _buf = Self::_alloc(0, size)?;
91        fail_point!("alloc_buf", |_| {
92            rand_buffer(&mut _buf);
93            return Ok(_buf);
94        });
95        return Ok(_buf);
96    }
97
98    /// Allocate a buffer.
99    ///
100    /// `size`: must be larger than zero
101    #[inline]
102    fn _alloc(align: u32, size: i32) -> Result<Self, Errno> {
103        assert!(size > 0);
104        let mut ptr: *mut libc::c_void = std::ptr::null_mut();
105        if align > 0 {
106            debug_assert!((align & (MIN_ALIGN - 1)) == 0);
107            debug_assert!((size as u32 & (align - 1)) == 0);
108            unsafe {
109                let res =
110                    libc::posix_memalign(&mut ptr, align as libc::size_t, size as libc::size_t);
111                if res != 0 {
112                    return Err(Errno::ENOMEM);
113                }
114            }
115        } else {
116            ptr = unsafe { libc::malloc(size as libc::size_t) };
117            if ptr == std::ptr::null_mut() {
118                return Err(Errno::ENOMEM);
119            }
120        }
121        // owned == true
122        let _size = size as u32 | MAX_BUFFER_SIZE as u32;
123        // mutable == true
124        let _cap = _size;
125        Ok(Self { buf_ptr: ptr, size: _size, cap: _cap })
126    }
127
128    /// Wrap a mutable buffer passed from c code, without owner ship.
129    ///
130    /// **NOTE**: will not free on drop. You have to ensure the buffer valid throughout the lifecycle.
131    ///
132    /// `size`: must be larger than or equal to zero.
133    #[inline]
134    pub fn from_c_ref_mut(ptr: *mut libc::c_void, size: i32) -> Self {
135        assert!(size >= 0);
136        assert!(ptr != std::ptr::null_mut());
137        // owned == false
138        // mutable == true
139        let _cap = size as u32 | MAX_BUFFER_SIZE as u32;
140        Self { buf_ptr: ptr, size: size as u32, cap: _cap }
141    }
142
143    /// Wrap a const buffer passed from c code, without owner ship.
144    ///
145    /// **NOTE**: will not free on drop. You have to ensure the buffer valid throughout the lifecycle
146    ///
147    /// `size`: must be larger than or equal to zero.
148    #[inline]
149    pub fn from_c_ref_const(ptr: *const libc::c_void, size: i32) -> Self {
150        assert!(size >= 0);
151        assert!(ptr != std::ptr::null());
152        // owned == false
153        // mutable == false
154        Self { buf_ptr: unsafe { std::mem::transmute(ptr) }, size: size as u32, cap: size as u32 }
155    }
156
157    /// Tell whether the Buffer has true 'static lifetime.
158    #[inline(always)]
159    pub fn is_owned(&self) -> bool {
160        self.size & (MAX_BUFFER_SIZE as u32) != 0
161    }
162
163    /// Tell whether the Buffer can as_mut().
164    #[inline(always)]
165    pub fn is_mutable(&self) -> bool {
166        self.cap & (MAX_BUFFER_SIZE as u32) != 0
167    }
168
169    /// Return the buffer's size.
170    #[inline(always)]
171    pub fn len(&self) -> usize {
172        let size = self.size & (MAX_BUFFER_SIZE as u32 - 1);
173        size as usize
174    }
175
176    /// Return the memory capacity managed by buffer's ptr
177    #[inline(always)]
178    pub fn capacity(&self) -> usize {
179        let cap = self.cap & (MAX_BUFFER_SIZE as u32 - 1);
180        cap as usize
181    }
182
183    /// Change the buffer's size, the same as `Vec::set_len()`. Panics when len > capacity
184    #[inline(always)]
185    pub fn set_len(&mut self, len: usize) {
186        assert!(len < MAX_BUFFER_SIZE, "size {} >= {} is not supported", len, MAX_BUFFER_SIZE);
187        assert!(len <= self.cap as usize, "size {} must be <= {}", len, self.cap);
188        let owned: u32 = self.size & MAX_BUFFER_SIZE as u32;
189        self.size = owned | len as u32;
190    }
191
192    #[inline(always)]
193    pub fn as_ref(&self) -> &[u8] {
194        unsafe { slice::from_raw_parts(self.buf_ptr as *const u8, self.len()) }
195    }
196
197    /// On debug mode, will panic if the Buffer is not owned [Buffer::from_c_ref_const()]
198    ///
199    /// On release will skip the check for speed.
200    #[inline(always)]
201    pub fn as_mut(&mut self) -> &mut [u8] {
202        #[cfg(debug_assertions)]
203        {
204            if !self.is_mutable() {
205                panic!("Cannot change a mutable buffer")
206            }
207        }
208        unsafe { slice::from_raw_parts_mut(self.buf_ptr as *mut u8, self.len()) }
209    }
210
211    /// Check this buffer usable by aio. True when get from `Buffer::aligned()`.
212    #[inline(always)]
213    pub fn is_aligned(&self) -> bool {
214        is_aligned(self.buf_ptr as usize, self.capacity())
215    }
216
217    /// Get buffer raw pointer
218    #[inline]
219    pub fn get_raw(&self) -> *const u8 {
220        self.buf_ptr as *const u8
221    }
222
223    /// Get buffer raw mut pointer
224    #[inline]
225    pub fn get_raw_mut(&mut self) -> *mut u8 {
226        self.buf_ptr as *mut u8
227    }
228
229    /// Copy from another u8 slice into self[offset..].
230    ///
231    /// **NOTE**: will not do memset.
232    ///
233    /// Argument:
234    ///
235    ///  * offset: Address of this buffer to start filling.
236    #[inline]
237    pub fn copy_from(&mut self, offset: usize, other: &[u8]) {
238        let size = self.len();
239        let dst = self.as_mut();
240        if offset > 0 {
241            assert!(offset < size);
242            safe_copy(&mut dst[offset..], other);
243        } else {
244            safe_copy(dst, other);
245        }
246    }
247
248    /// Copy from another u8 slice into self[offset..], and memset the rest part.
249    ///
250    /// Argument:
251    ///
252    ///  * offset: Address of this buffer to start filling.
253    #[inline]
254    pub fn copy_and_clean(&mut self, offset: usize, other: &[u8]) {
255        let end: usize;
256        let size = self.len();
257        let dst = self.as_mut();
258        assert!(offset < size);
259        if offset > 0 {
260            set_zero(&mut dst[0..offset]);
261            end = offset + safe_copy(&mut dst[offset..], other);
262        } else {
263            end = safe_copy(dst, other);
264        }
265        if size > end {
266            set_zero(&mut dst[end..]);
267        }
268    }
269
270    /// Fill this buffer with zero
271    #[inline]
272    pub fn zero(&mut self) {
273        set_zero(self);
274    }
275
276    /// Fill specified region of buffer[offset..(offset+len)] with zero
277    #[inline]
278    pub fn set_zero(&mut self, offset: usize, len: usize) {
279        let _len = self.len();
280        let mut end = offset + len;
281        if end > _len {
282            end = _len;
283        }
284        let buf = self.as_mut();
285        if offset > 0 || end < _len {
286            set_zero(&mut buf[offset..end]);
287        } else {
288            set_zero(buf);
289        }
290    }
291}
292
293/// Allocates a new memory with the same size and clone the content.
294/// If original buffer is a c reference, will get a owned buffer after clone().
295impl Clone for Buffer {
296    fn clone(&self) -> Self {
297        let mut new_buf = if self.is_aligned() {
298            Self::aligned(self.capacity() as i32).unwrap()
299        } else {
300            Self::alloc(self.capacity() as i32).unwrap()
301        };
302        if self.len() != self.capacity() {
303            new_buf.set_len(self.len());
304        }
305        safe_copy(new_buf.as_mut(), self.as_ref());
306        new_buf
307    }
308}
309
310/// Automatically free on drop when buffer is owned
311impl Drop for Buffer {
312    fn drop(&mut self) {
313        if self.is_owned() {
314            unsafe {
315                libc::free(self.buf_ptr);
316            }
317        }
318    }
319}
320
321/// Convert a owned Buffer to `Vec<u8>`. Panic when buffer is a ref.
322impl Into<Vec<u8>> for Buffer {
323    fn into(mut self) -> Vec<u8> {
324        if !self.is_owned() {
325            panic!("buffer is c ref, not owned");
326        }
327        // Change to not owned, to prevent drop()
328        self.size &= MAX_BUFFER_SIZE as u32 - 1;
329        return unsafe {
330            Vec::<u8>::from_raw_parts(self.buf_ptr as *mut u8, self.len(), self.capacity())
331        };
332    }
333}
334
335/// Convert `Vec<u8>` to Buffer, inherit the size and cap of Vec.
336impl From<Vec<u8>> for Buffer {
337    fn from(buf: Vec<u8>) -> Self {
338        let size = buf.len();
339        let cap = buf.capacity();
340        assert!(size < MAX_BUFFER_SIZE, "size {} >= {} is not supported", size, MAX_BUFFER_SIZE);
341        assert!(cap < MAX_BUFFER_SIZE, "cap {} >= {} is not supported", cap, MAX_BUFFER_SIZE);
342        // owned == true
343        let _size = size as u32 | MAX_BUFFER_SIZE as u32;
344        // mutable == true
345        let _cap = cap as u32 | MAX_BUFFER_SIZE as u32;
346        Buffer { buf_ptr: buf.leak().as_mut_ptr() as *mut libc::c_void, size: _size, cap: _cap }
347    }
348}
349
350impl Deref for Buffer {
351    type Target = [u8];
352
353    #[inline]
354    fn deref(&self) -> &[u8] {
355        self.as_ref()
356    }
357}
358
359impl AsRef<[u8]> for Buffer {
360    #[inline]
361    fn as_ref(&self) -> &[u8] {
362        self.as_ref()
363    }
364}
365
366/// On debug mode, will panic if the Buffer is not owned [Buffer::from_c_ref_const()]
367///
368/// On release will skip the check for speed.
369impl AsMut<[u8]> for Buffer {
370    #[inline]
371    fn as_mut(&mut self) -> &mut [u8] {
372        self.as_mut()
373    }
374}
375
376impl DerefMut for Buffer {
377    #[inline]
378    fn deref_mut(&mut self) -> &mut [u8] {
379        self.as_mut()
380    }
381}