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}