kvarn_tokio_uring/buf/
slice.rs

1use super::{BoundedBuf, BoundedBufMut, IoBuf, IoBufMut};
2
3use std::cmp;
4use std::ops;
5
6/// An owned view into a contiguous sequence of bytes.
7///
8/// This is similar to Rust slices (`&buf[..]`) but owns the underlying buffer.
9/// This type is useful for performing io-uring read and write operations using
10/// a subset of a buffer.
11///
12/// Slices are created using [`BoundedBuf::slice`].
13///
14/// # Examples
15///
16/// Creating a slice
17///
18/// ```
19/// use tokio_uring::buf::BoundedBuf;
20///
21/// let buf = b"hello world".to_vec();
22/// let slice = buf.slice(..5);
23///
24/// assert_eq!(&slice[..], b"hello");
25/// ```
26pub struct Slice<T> {
27    buf: T,
28    begin: usize,
29    end: usize,
30}
31
32impl<T> Slice<T> {
33    pub(crate) fn new(buf: T, begin: usize, end: usize) -> Slice<T> {
34        Slice { buf, begin, end }
35    }
36
37    /// Offset in the underlying buffer at which this slice starts.
38    ///
39    /// # Examples
40    ///
41    /// ```
42    /// use tokio_uring::buf::BoundedBuf;
43    ///
44    /// let buf = b"hello world".to_vec();
45    /// let slice = buf.slice(1..5);
46    ///
47    /// assert_eq!(1, slice.begin());
48    /// ```
49    pub fn begin(&self) -> usize {
50        self.begin
51    }
52
53    /// Ofset in the underlying buffer at which this slice ends.
54    ///
55    /// # Examples
56    ///
57    /// ```
58    /// use tokio_uring::buf::BoundedBuf;
59    ///
60    /// let buf = b"hello world".to_vec();
61    /// let slice = buf.slice(1..5);
62    ///
63    /// assert_eq!(5, slice.end());
64    /// ```
65    pub fn end(&self) -> usize {
66        self.end
67    }
68
69    /// Gets a reference to the underlying buffer.
70    ///
71    /// This method escapes the slice's view.
72    ///
73    /// # Examples
74    ///
75    /// ```
76    /// use tokio_uring::buf::BoundedBuf;
77    ///
78    /// let buf = b"hello world".to_vec();
79    /// let slice = buf.slice(..5);
80    ///
81    /// assert_eq!(slice.get_ref(), b"hello world");
82    /// assert_eq!(&slice[..], b"hello");
83    /// ```
84    pub fn get_ref(&self) -> &T {
85        &self.buf
86    }
87
88    /// Gets a mutable reference to the underlying buffer.
89    ///
90    /// This method escapes the slice's view.
91    ///
92    /// # Examples
93    ///
94    /// ```
95    /// use tokio_uring::buf::BoundedBuf;
96    ///
97    /// let buf = b"hello world".to_vec();
98    /// let mut slice = buf.slice(..5);
99    ///
100    /// slice.get_mut()[0] = b'b';
101    ///
102    /// assert_eq!(slice.get_mut(), b"bello world");
103    /// assert_eq!(&slice[..], b"bello");
104    /// ```
105    pub fn get_mut(&mut self) -> &mut T {
106        &mut self.buf
107    }
108
109    /// Unwraps this `Slice`, returning the underlying buffer.
110    ///
111    /// # Examples
112    ///
113    /// ```
114    /// use tokio_uring::buf::BoundedBuf;
115    ///
116    /// let buf = b"hello world".to_vec();
117    /// let slice = buf.slice(..5);
118    ///
119    /// let buf = slice.into_inner();
120    /// assert_eq!(buf, b"hello world");
121    /// ```
122    pub fn into_inner(self) -> T {
123        self.buf
124    }
125}
126
127impl<T: IoBuf> ops::Deref for Slice<T> {
128    type Target = [u8];
129
130    fn deref(&self) -> &[u8] {
131        let buf_bytes = super::deref(&self.buf);
132        let end = cmp::min(self.end, buf_bytes.len());
133        &buf_bytes[self.begin..end]
134    }
135}
136
137impl<T: IoBufMut> ops::DerefMut for Slice<T> {
138    fn deref_mut(&mut self) -> &mut [u8] {
139        let buf_bytes = super::deref_mut(&mut self.buf);
140        let end = cmp::min(self.end, buf_bytes.len());
141        &mut buf_bytes[self.begin..end]
142    }
143}
144
145impl<T: IoBuf> BoundedBuf for Slice<T> {
146    type Buf = T;
147    type Bounds = ops::Range<usize>;
148
149    fn slice(self, range: impl ops::RangeBounds<usize>) -> Slice<T> {
150        use ops::Bound;
151
152        let begin = match range.start_bound() {
153            Bound::Included(&n) => self.begin.checked_add(n).expect("out of range"),
154            Bound::Excluded(&n) => self
155                .begin
156                .checked_add(n)
157                .and_then(|x| x.checked_add(1))
158                .expect("out of range"),
159            Bound::Unbounded => self.begin,
160        };
161
162        assert!(begin <= self.end);
163
164        let end = match range.end_bound() {
165            Bound::Included(&n) => self
166                .begin
167                .checked_add(n)
168                .and_then(|x| x.checked_add(1))
169                .expect("out of range"),
170            Bound::Excluded(&n) => self.begin.checked_add(n).expect("out of range"),
171            Bound::Unbounded => self.end,
172        };
173
174        assert!(end <= self.end);
175        assert!(begin <= self.buf.bytes_init());
176
177        Slice::new(self.buf, begin, end)
178    }
179
180    fn slice_full(self) -> Slice<T> {
181        self
182    }
183
184    fn get_buf(&self) -> &T {
185        &self.buf
186    }
187
188    fn bounds(&self) -> Self::Bounds {
189        self.begin..self.end
190    }
191
192    fn from_buf_bounds(buf: T, bounds: Self::Bounds) -> Self {
193        assert!(bounds.start <= buf.bytes_init());
194        assert!(bounds.end <= buf.bytes_total());
195        Slice::new(buf, bounds.start, bounds.end)
196    }
197
198    fn stable_ptr(&self) -> *const u8 {
199        super::deref(&self.buf)[self.begin..].as_ptr()
200    }
201
202    fn bytes_init(&self) -> usize {
203        ops::Deref::deref(self).len()
204    }
205
206    fn bytes_total(&self) -> usize {
207        self.end - self.begin
208    }
209}
210
211impl<T: IoBufMut> BoundedBufMut for Slice<T> {
212    type BufMut = T;
213
214    fn stable_mut_ptr(&mut self) -> *mut u8 {
215        super::deref_mut(&mut self.buf)[self.begin..].as_mut_ptr()
216    }
217
218    unsafe fn set_init(&mut self, pos: usize) {
219        self.buf.set_init(self.begin + pos);
220    }
221}