io_engine/buffer/
mod.rs

1mod large;
2pub mod utils;
3use large::{BufferLarge, MIN_ALIGN};
4use utils::*;
5
6#[cfg(test)]
7mod test;
8
9use nix::errno::Errno;
10use std::{
11    fmt,
12    ops::{Deref, DerefMut},
13};
14
15use fail::fail_point;
16
17/// The Buffer enum, can obtain from alloc, wrap a raw c buffer, or convert from Vec.
18///
19/// When Clone, will copy the contain into a new Buffer.
20#[derive(Clone)]
21pub enum Buffer {
22    Large(BufferLarge),
23    Vec(Vec<u8>),
24}
25
26impl fmt::Debug for Buffer {
27    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
28        write!(f, "buffer {:p} size {}", self.get_raw(), self.len())
29    }
30}
31
32impl Buffer {
33    /// Allocate aligned buffer for aio
34    /// NOTE: Be aware that buffer allocated will not necessarily be zeroed
35    #[inline]
36    pub fn aligned(size: usize) -> Result<Buffer, Errno> {
37        let mut _buf = BufferLarge::alloc(MIN_ALIGN, size)?;
38        fail_point!("alloc_buf", |_| {
39            rand_buffer(&mut _buf);
40            return Ok(Buffer::Large(_buf));
41        });
42        return Ok(Buffer::Large(_buf));
43    }
44
45    /// Allocate non-aligned Buffer
46    /// NOTE: Be aware that buffer allocated will not necessarily be zeroed
47    #[inline]
48    pub fn alloc(size: usize) -> Result<Buffer, Errno> {
49        let mut _buf = BufferLarge::alloc(0, size)?;
50        fail_point!("alloc_buf", |_| {
51            rand_buffer(&mut _buf);
52            return Ok(Buffer::Large(_buf));
53        });
54        return Ok(Buffer::Large(_buf));
55    }
56
57    /// Wrap a mutable buffer passed from c code without owner ship, as a fake 'static lifetime struct.
58    /// NOTE: will not free on drop. You have to ensure the buffer valid throughout the lifecycle
59    #[inline]
60    pub fn from_c_ref_mut(ptr: *mut libc::c_void, size: usize) -> Self {
61        Self::Large(BufferLarge::from_c_ref_mut(ptr, size))
62    }
63
64    /// Wrap a const buffer passed from c code, without owner ship, as a fake 'static lifetime struct.
65    /// NOTE: will not free on drop. You have to ensure the buffer valid throughout the lifecycle
66    #[inline]
67    pub fn from_c_ref_const(ptr: *const libc::c_void, size: usize) -> Self {
68        Self::Large(BufferLarge::from_c_ref_const(ptr, size))
69    }
70
71    #[inline(always)]
72    pub fn len(&self) -> usize {
73        match self {
74            Buffer::Large(buf) => buf.size as usize,
75            Buffer::Vec(buf) => buf.len(),
76        }
77    }
78
79    /// Get buffer raw pointer
80    #[inline]
81    pub fn get_raw(&self) -> *const u8 {
82        match self {
83            Buffer::Large(buf) => buf.buf_ptr as *const u8,
84            Buffer::Vec(buf) => buf.as_ptr(),
85        }
86    }
87
88    /// Get buffer raw mut pointer
89    #[inline]
90    pub fn get_raw_mut(&mut self) -> *mut u8 {
91        match self {
92            Buffer::Large(buf) => buf.buf_ptr as *mut u8,
93            Buffer::Vec(v) => v.as_mut_ptr(),
94        }
95    }
96
97    /// Copy from another u8 slice into self[offset..]. NOTE: will not do memset.
98    /// Argument:
99    ///   offset: Address of this buffer to start filling.
100    #[inline]
101    pub fn copy_from(&mut self, offset: usize, other: &[u8]) {
102        let size = self.len();
103        let dst = self.as_mut();
104        if offset > 0 {
105            assert!(offset < size);
106            safe_copy(&mut dst[offset..], other);
107        } else {
108            safe_copy(dst, other);
109        }
110    }
111
112    /// Copy from another u8 slice into self[offset..], and memset the rest part.
113    /// Argument:
114    ///   offset: Address of this buffer to start filling.
115    #[inline]
116    pub fn copy_and_clean(&mut self, offset: usize, other: &[u8]) {
117        let end: usize;
118        let size = self.len();
119        let dst = self.as_mut();
120        assert!(offset < size);
121        if offset > 0 {
122            set_zero(&mut dst[0..offset]);
123            end = offset + safe_copy(&mut dst[offset..], other);
124        } else {
125            end = safe_copy(dst, other);
126        }
127        if size > end {
128            set_zero(&mut dst[end..]);
129        }
130    }
131
132    /// Fill this buffer with zero
133    #[inline]
134    pub fn zero(&mut self) {
135        set_zero(self);
136    }
137
138    /// Fill this buffer[offset..(offset+len)] with zero
139    #[inline]
140    pub fn set_zero(&mut self, offset: usize, len: usize) {
141        let _len = self.len();
142        let mut end = offset + len;
143        if end > _len {
144            end = _len;
145        }
146        let buf = self.as_mut();
147        if offset > 0 || end < _len {
148            set_zero(&mut buf[offset..end]);
149        } else {
150            set_zero(buf);
151        }
152    }
153
154    #[inline]
155    pub fn is_aligned(&self) -> bool {
156        match self {
157            Buffer::Large(buf) => buf.is_aligned(),
158            Buffer::Vec(_) => false,
159        }
160    }
161}
162
163impl Into<Vec<u8>> for Buffer {
164    fn into(self) -> Vec<u8> {
165        if let Buffer::Vec(v) = self {
166            v
167        } else {
168            unimplemented!()
169        }
170    }
171}
172
173impl From<Vec<u8>> for Buffer {
174    fn from(buf: Vec<u8>) -> Self {
175        Buffer::Vec(buf)
176    }
177}
178
179impl Deref for Buffer {
180    type Target = [u8];
181
182    #[inline]
183    fn deref(&self) -> &[u8] {
184        match self {
185            Self::Large(buf) => buf.as_ref(),
186            Self::Vec(v) => &v,
187        }
188    }
189}
190
191impl AsMut<[u8]> for Buffer {
192    #[inline]
193    fn as_mut(&mut self) -> &mut [u8] {
194        match self {
195            Self::Large(buf) => buf.as_mut(),
196            Self::Vec(v) => v.as_mut(),
197        }
198    }
199}
200
201impl DerefMut for Buffer {
202    #[inline]
203    fn deref_mut(&mut self) -> &mut [u8] {
204        match self {
205            Self::Large(buf) => buf.as_mut(),
206            Self::Vec(v) => v.as_mut(),
207        }
208    }
209}