Skip to content

Commit 4463b08

Browse files
authored
Rollup merge of #86037 - soerenmeier:cursor_remaining, r=yaahc
Add `io::Cursor::{remaining, remaining_slice, is_empty}` Tracking issue: #86369 I came across an inconvenience when answering the following [Stack Overflow](https://stackoverflow.com/questions/67831170) question. To get the remaining slice you have to call `buff.fill_buf().unwrap()`. Which in my opinion doesn't really tell you what is returned (in the context of Cursor). To improve readability and convenience when using Cursor i propose adding the method `remaining`. The next thing i found inconvenient (unnecessary long) was detecting if the cursor reached the end. There are a few ways this can be achieved right now: - `buff.fill_buf().unwrap().is_empty()` - `buff.position() >= buff.get_ref().len()` - `buff.bytes().next().is_none()` Which all seem a bit unintuitive, hidden in trait documentations or just a bit long for such a simple task. Therefor i propose another method called `is_empty`, maybe with another name, since this one may leave room for interpretation on what really is empty (the underlying slice, the remaining slice or maybe the position). Since it seemed easier to create this PR instead of an RFC i did that, if an RFC is wanted, i can close this PR and write an RFC first.
2 parents 7f1a4a2 + 664bde0 commit 4463b08

File tree

1 file changed

+85
-4
lines changed

1 file changed

+85
-4
lines changed

library/std/src/io/cursor.rs

+85-4
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,88 @@ impl<T> Cursor<T> {
205205
}
206206
}
207207

208+
impl<T> Cursor<T>
209+
where
210+
T: AsRef<[u8]>,
211+
{
212+
/// Returns the remaining length.
213+
///
214+
/// # Examples
215+
///
216+
/// ```
217+
/// #![feature(cursor_remaining)]
218+
/// use std::io::Cursor;
219+
///
220+
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
221+
///
222+
/// assert_eq!(buff.remaining(), 5);
223+
///
224+
/// buff.set_position(2);
225+
/// assert_eq!(buff.remaining(), 3);
226+
///
227+
/// buff.set_position(4);
228+
/// assert_eq!(buff.remaining(), 1);
229+
///
230+
/// buff.set_position(6);
231+
/// assert_eq!(buff.remaining(), 0);
232+
/// ```
233+
#[unstable(feature = "cursor_remaining", issue = "86369")]
234+
pub fn remaining(&self) -> u64 {
235+
(self.inner.as_ref().len() as u64).checked_sub(self.pos).unwrap_or(0)
236+
}
237+
238+
/// Returns the remaining slice.
239+
///
240+
/// # Examples
241+
///
242+
/// ```
243+
/// #![feature(cursor_remaining)]
244+
/// use std::io::Cursor;
245+
///
246+
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
247+
///
248+
/// assert_eq!(buff.remaining_slice(), &[1, 2, 3, 4, 5]);
249+
///
250+
/// buff.set_position(2);
251+
/// assert_eq!(buff.remaining_slice(), &[3, 4, 5]);
252+
///
253+
/// buff.set_position(4);
254+
/// assert_eq!(buff.remaining_slice(), &[5]);
255+
///
256+
/// buff.set_position(6);
257+
/// assert_eq!(buff.remaining_slice(), &[]);
258+
/// ```
259+
#[unstable(feature = "cursor_remaining", issue = "86369")]
260+
pub fn remaining_slice(&self) -> &[u8] {
261+
let len = self.pos.min(self.inner.as_ref().len() as u64);
262+
&self.inner.as_ref()[(len as usize)..]
263+
}
264+
265+
/// Returns `true` if the remaining slice is empty.
266+
///
267+
/// # Examples
268+
///
269+
/// ```
270+
/// #![feature(cursor_remaining)]
271+
/// use std::io::Cursor;
272+
///
273+
/// let mut buff = Cursor::new(vec![1, 2, 3, 4, 5]);
274+
///
275+
/// buff.set_position(2);
276+
/// assert!(!buff.is_empty());
277+
///
278+
/// buff.set_position(5);
279+
/// assert!(buff.is_empty());
280+
///
281+
/// buff.set_position(10);
282+
/// assert!(buff.is_empty());
283+
/// ```
284+
#[unstable(feature = "cursor_remaining", issue = "86369")]
285+
pub fn is_empty(&self) -> bool {
286+
self.pos >= self.inner.as_ref().len() as u64
287+
}
288+
}
289+
208290
#[stable(feature = "rust1", since = "1.0.0")]
209291
impl<T> Clone for Cursor<T>
210292
where
@@ -268,7 +350,7 @@ where
268350
T: AsRef<[u8]>,
269351
{
270352
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
271-
let n = Read::read(&mut self.fill_buf()?, buf)?;
353+
let n = Read::read(&mut self.remaining_slice(), buf)?;
272354
self.pos += n as u64;
273355
Ok(n)
274356
}
@@ -291,7 +373,7 @@ where
291373

292374
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
293375
let n = buf.len();
294-
Read::read_exact(&mut self.fill_buf()?, buf)?;
376+
Read::read_exact(&mut self.remaining_slice(), buf)?;
295377
self.pos += n as u64;
296378
Ok(())
297379
}
@@ -308,8 +390,7 @@ where
308390
T: AsRef<[u8]>,
309391
{
310392
fn fill_buf(&mut self) -> io::Result<&[u8]> {
311-
let amt = cmp::min(self.pos, self.inner.as_ref().len() as u64);
312-
Ok(&self.inner.as_ref()[(amt as usize)..])
393+
Ok(self.remaining_slice())
313394
}
314395
fn consume(&mut self, amt: usize) {
315396
self.pos += amt as u64;

0 commit comments

Comments
 (0)