monoio/buf/
slice.rs

1use std::ops;
2
3use super::{IoVecBuf, IoVecBufMut};
4use crate::buf::{IoBuf, IoBufMut};
5
6/// An owned view into a contiguous sequence of bytes.
7/// SliceMut implements IoBuf and IoBufMut.
8///
9/// This is similar to Rust slices (`&buf[..]`) but owns the underlying buffer.
10/// This type is useful for performing io_uring read and write operations using
11/// a subset of a buffer.
12///
13/// Slices are created using [`IoBuf::slice`].
14///
15/// # Examples
16///
17/// Creating a slice
18///
19/// ```
20/// use monoio::buf::{IoBuf, IoBufMut};
21///
22/// let buf = b"hello world".to_vec();
23/// let slice = buf.slice_mut(..5);
24///
25/// assert_eq!(&slice[..], b"hello");
26/// ```
27pub struct SliceMut<T> {
28    buf: T,
29    begin: usize,
30    end: usize,
31}
32
33impl<T: IoBuf + IoBufMut> SliceMut<T> {
34    /// Create a SliceMut from a buffer and range.
35    #[inline]
36    pub fn new(mut buf: T, begin: usize, end: usize) -> Self {
37        assert!(end <= buf.bytes_total());
38        assert!(begin <= buf.bytes_init());
39        assert!(begin <= end);
40        Self { buf, begin, end }
41    }
42}
43
44impl<T> SliceMut<T> {
45    /// Create a SliceMut from a buffer and range without boundary checking.
46    ///
47    /// # Safety
48    /// begin must be initialized, and end must be within the buffer capacity.
49    #[inline]
50    pub const unsafe fn new_unchecked(buf: T, begin: usize, end: usize) -> Self {
51        Self { buf, begin, end }
52    }
53
54    /// Offset in the underlying buffer at which this slice starts.
55    ///
56    /// # Examples
57    ///
58    /// ```
59    /// use monoio::buf::IoBuf;
60    ///
61    /// let buf = b"hello world".to_vec();
62    /// let slice = buf.slice(1..5);
63    ///
64    /// assert_eq!(1, slice.begin());
65    /// ```
66    #[inline]
67    pub const fn begin(&self) -> usize {
68        self.begin
69    }
70
71    /// Offset in the underlying buffer at which this slice ends.
72    ///
73    /// # Examples
74    ///
75    /// ```
76    /// use monoio::buf::IoBuf;
77    ///
78    /// let buf = b"hello world".to_vec();
79    /// let slice = buf.slice(1..5);
80    ///
81    /// assert_eq!(5, slice.end());
82    /// ```
83    #[inline]
84    pub const fn end(&self) -> usize {
85        self.end
86    }
87
88    /// Gets a reference to the underlying buffer.
89    ///
90    /// This method escapes the slice's view.
91    ///
92    /// # Examples
93    ///
94    /// ```
95    /// use monoio::buf::{IoBuf, IoBufMut};
96    ///
97    /// let buf = b"hello world".to_vec();
98    /// let slice = buf.slice_mut(..5);
99    ///
100    /// assert_eq!(slice.get_ref(), b"hello world");
101    /// assert_eq!(&slice[..], b"hello");
102    /// ```
103    #[inline]
104    pub const fn get_ref(&self) -> &T {
105        &self.buf
106    }
107
108    /// Gets a mutable reference to the underlying buffer.
109    ///
110    /// This method escapes the slice's view.
111    ///
112    /// # Examples
113    ///
114    /// ```
115    /// use monoio::buf::{IoBuf, IoBufMut};
116    ///
117    /// let buf = b"hello world".to_vec();
118    /// let mut slice = buf.slice_mut(..5);
119    ///
120    /// slice.get_mut()[0] = b'b';
121    ///
122    /// assert_eq!(slice.get_mut(), b"bello world");
123    /// assert_eq!(&slice[..], b"bello");
124    /// ```
125    #[inline]
126    pub fn get_mut(&mut self) -> &mut T {
127        &mut self.buf
128    }
129
130    /// Unwraps this `Slice`, returning the underlying buffer.
131    ///
132    /// # Examples
133    ///
134    /// ```
135    /// use monoio::buf::IoBuf;
136    ///
137    /// let buf = b"hello world".to_vec();
138    /// let slice = buf.slice(..5);
139    ///
140    /// let buf = slice.into_inner();
141    /// assert_eq!(buf, b"hello world");
142    /// ```
143    #[inline]
144    pub fn into_inner(self) -> T {
145        self.buf
146    }
147}
148
149impl<T: IoBuf> ops::Deref for SliceMut<T> {
150    type Target = [u8];
151
152    #[inline]
153    fn deref(&self) -> &[u8] {
154        let buf_bytes = super::deref(&self.buf);
155        let end = std::cmp::min(self.end, buf_bytes.len());
156        &buf_bytes[self.begin..end]
157    }
158}
159
160unsafe impl<T: IoBuf> IoBuf for SliceMut<T> {
161    #[inline]
162    fn read_ptr(&self) -> *const u8 {
163        super::deref(&self.buf)[self.begin..].as_ptr()
164    }
165
166    #[inline]
167    fn bytes_init(&self) -> usize {
168        ops::Deref::deref(self).len()
169    }
170}
171
172unsafe impl<T: IoBufMut> IoBufMut for SliceMut<T> {
173    #[inline]
174    fn write_ptr(&mut self) -> *mut u8 {
175        unsafe { self.buf.write_ptr().add(self.begin) }
176    }
177
178    #[inline]
179    fn bytes_total(&mut self) -> usize {
180        self.end - self.begin
181    }
182
183    #[inline]
184    unsafe fn set_init(&mut self, n: usize) {
185        self.buf.set_init(self.begin + n);
186    }
187}
188
189/// An owned view into a contiguous sequence of bytes.
190/// Slice implements IoBuf.
191pub struct Slice<T> {
192    buf: T,
193    begin: usize,
194    end: usize,
195}
196
197impl<T: IoBuf> Slice<T> {
198    /// Create a Slice from a buffer and range.
199    #[inline]
200    pub fn new(buf: T, begin: usize, end: usize) -> Self {
201        assert!(end <= buf.bytes_init());
202        assert!(begin <= end);
203        Self { buf, begin, end }
204    }
205}
206
207impl<T> Slice<T> {
208    /// Create a Slice from a buffer and range without boundary checking.
209    ///
210    /// # Safety
211    /// begin and end must be within the buffer initialized range.
212    #[inline]
213    pub const unsafe fn new_unchecked(buf: T, begin: usize, end: usize) -> Self {
214        Self { buf, begin, end }
215    }
216
217    /// Offset in the underlying buffer at which this slice starts.
218    #[inline]
219    pub const fn begin(&self) -> usize {
220        self.begin
221    }
222
223    /// Ofset in the underlying buffer at which this slice ends.
224    #[inline]
225    pub const fn end(&self) -> usize {
226        self.end
227    }
228
229    /// Gets a reference to the underlying buffer.
230    #[inline]
231    pub const fn get_ref(&self) -> &T {
232        &self.buf
233    }
234
235    /// Gets a mutable reference to the underlying buffer.
236    #[inline]
237    pub fn get_mut(&mut self) -> &mut T {
238        &mut self.buf
239    }
240
241    /// Unwraps this `Slice`, returning the underlying buffer.
242    #[inline]
243    pub fn into_inner(self) -> T {
244        self.buf
245    }
246}
247
248unsafe impl<T: IoBuf> IoBuf for Slice<T> {
249    #[inline]
250    fn read_ptr(&self) -> *const u8 {
251        unsafe { self.buf.read_ptr().add(self.begin) }
252    }
253
254    #[inline]
255    fn bytes_init(&self) -> usize {
256        self.end - self.begin
257    }
258}
259
260/// A wrapper to make IoVecBuf impl IoBuf.
261pub struct IoVecWrapper<T> {
262    // we must make sure raw contains at least one iovec.
263    raw: T,
264}
265
266impl<T: IoVecBuf> IoVecWrapper<T> {
267    /// Create a new IoVecWrapper with something that impl IoVecBuf.
268    #[inline]
269    pub fn new(buf: T) -> Result<Self, T> {
270        #[cfg(unix)]
271        if buf.read_iovec_len() == 0 {
272            return Err(buf);
273        }
274        #[cfg(windows)]
275        if buf.read_wsabuf_len() == 0 {
276            return Err(buf);
277        }
278        Ok(Self { raw: buf })
279    }
280
281    /// Consume self and return raw iovec buf.
282    #[inline]
283    pub fn into_inner(self) -> T {
284        self.raw
285    }
286}
287
288unsafe impl<T: IoVecBuf> IoBuf for IoVecWrapper<T> {
289    #[inline]
290    fn read_ptr(&self) -> *const u8 {
291        #[cfg(unix)]
292        {
293            let iovec = unsafe { *self.raw.read_iovec_ptr() };
294            iovec.iov_base as *const u8
295        }
296        #[cfg(windows)]
297        {
298            let wsabuf = unsafe { *self.raw.read_wsabuf_ptr() };
299            wsabuf.buf as *const u8
300        }
301    }
302
303    #[inline]
304    fn bytes_init(&self) -> usize {
305        #[cfg(unix)]
306        {
307            let iovec = unsafe { *self.raw.read_iovec_ptr() };
308            iovec.iov_len
309        }
310        #[cfg(windows)]
311        {
312            let wsabuf = unsafe { *self.raw.read_wsabuf_ptr() };
313            wsabuf.len as _
314        }
315    }
316}
317
318/// A wrapper to make IoVecBufMut impl IoBufMut.
319pub struct IoVecWrapperMut<T> {
320    // we must make sure raw contains at least one iovec.
321    raw: T,
322}
323
324impl<T: IoVecBufMut> IoVecWrapperMut<T> {
325    /// Create a new IoVecWrapperMut with something that impl IoVecBufMut.
326    #[inline]
327    pub fn new(mut iovec_buf: T) -> Result<Self, T> {
328        #[cfg(unix)]
329        if iovec_buf.write_iovec_len() == 0 {
330            return Err(iovec_buf);
331        }
332        #[cfg(windows)]
333        if iovec_buf.write_wsabuf_len() == 0 {
334            return Err(iovec_buf);
335        }
336        Ok(Self { raw: iovec_buf })
337    }
338
339    /// Consume self and return raw iovec buf.
340    #[inline]
341    pub fn into_inner(self) -> T {
342        self.raw
343    }
344}
345
346unsafe impl<T: IoVecBufMut> IoBufMut for IoVecWrapperMut<T> {
347    fn write_ptr(&mut self) -> *mut u8 {
348        #[cfg(unix)]
349        {
350            let iovec = unsafe { *self.raw.write_iovec_ptr() };
351            iovec.iov_base as *mut u8
352        }
353        #[cfg(windows)]
354        {
355            let wsabuf = unsafe { *self.raw.write_wsabuf_ptr() };
356            wsabuf.buf
357        }
358    }
359
360    fn bytes_total(&mut self) -> usize {
361        #[cfg(unix)]
362        {
363            let iovec = unsafe { *self.raw.write_iovec_ptr() };
364            iovec.iov_len
365        }
366        #[cfg(windows)]
367        {
368            let wsabuf = unsafe { *self.raw.write_wsabuf_ptr() };
369            wsabuf.len as _
370        }
371    }
372
373    unsafe fn set_init(&mut self, _pos: usize) {}
374}