Skip to content

Commit a132fcb

Browse files
committed
New impl of seek and add seek_relative
1 parent f4407fe commit a132fcb

File tree

3 files changed

+28
-41
lines changed

3 files changed

+28
-41
lines changed

library/std/src/io/mod.rs

+26-37
Original file line numberDiff line numberDiff line change
@@ -3075,47 +3075,27 @@ impl<T> SizeHint for Take<T> {
30753075
#[stable(feature = "seek_io_take", since = "CURRENT_RUSTC_VERSION")]
30763076
impl<T: Seek> Seek for Take<T> {
30773077
fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
3078-
let offset_from_start = match pos {
3079-
SeekFrom::Start(offset) => offset,
3080-
SeekFrom::End(offset) => {
3081-
if offset > 0 {
3082-
return Ok(self.position());
3083-
}
3084-
if offset.unsigned_abs() > self.len {
3085-
return Err(Error::from(ErrorKind::InvalidInput));
3086-
}
3087-
self.len - offset.unsigned_abs()
3088-
}
3089-
SeekFrom::Current(offset) => {
3090-
if offset >= 0 {
3091-
self.position() + offset.unsigned_abs()
3092-
} else {
3093-
self.position() - offset.unsigned_abs()
3094-
}
3095-
}
3078+
let new_position = match pos {
3079+
SeekFrom::Start(v) => Some(v),
3080+
SeekFrom::Current(v) => self.position().checked_add_signed(v),
3081+
SeekFrom::End(v) => self.len.checked_add_signed(v),
30963082
};
3097-
let offset_from_start = offset_from_start.min(self.len);
3098-
if offset_from_start > self.position() {
3099-
let mut offset_from_current = offset_from_start - self.position();
3100-
while offset_from_current > i64::MAX as u64 {
3101-
self.inner.seek(SeekFrom::Current(i64::MAX))?;
3102-
self.limit -= i64::MAX as u64;
3103-
offset_from_current -= i64::MAX as u64;
3083+
let new_position = match new_position {
3084+
Some(v) if v <= self.len => v,
3085+
_ => return Err(ErrorKind::InvalidInput.into()),
3086+
};
3087+
while new_position != self.position() {
3088+
if let Some(offset) = new_position.checked_signed_diff(self.position()) {
3089+
self.seek_relative(offset)?;
3090+
break;
31043091
}
3105-
self.inner.seek(SeekFrom::Current(offset_from_current as i64))?;
3106-
self.limit -= offset_from_current;
3107-
Ok(self.position())
3108-
} else {
3109-
let mut offset_from_current = self.position() - offset_from_start;
3110-
while offset_from_current > i64::MIN.unsigned_abs() {
3111-
self.inner.seek(SeekFrom::Current(i64::MIN))?;
3112-
self.limit += i64::MIN.unsigned_abs();
3113-
offset_from_current -= i64::MIN.unsigned_abs();
3092+
if new_position > self.position() {
3093+
self.seek_relative(i64::MAX)?;
3094+
} else {
3095+
self.seek_relative(i64::MIN)?;
31143096
}
3115-
self.inner.seek(SeekFrom::Current(-(offset_from_current as i64)))?;
3116-
self.limit += offset_from_current;
3117-
Ok(self.position())
31183097
}
3098+
Ok(new_position)
31193099
}
31203100

31213101
fn stream_len(&mut self) -> Result<u64> {
@@ -3125,6 +3105,15 @@ impl<T: Seek> Seek for Take<T> {
31253105
fn stream_position(&mut self) -> Result<u64> {
31263106
Ok(self.position())
31273107
}
3108+
3109+
fn seek_relative(&mut self, offset: i64) -> Result<()> {
3110+
if !self.position().checked_add_signed(offset).is_some_and(|p| p <= self.len) {
3111+
return Err(ErrorKind::InvalidInput.into());
3112+
}
3113+
self.inner.seek_relative(offset)?;
3114+
self.limit = self.limit.wrapping_sub(offset as u64);
3115+
Ok(())
3116+
}
31283117
}
31293118

31303119
/// An iterator over `u8` values of a reader.

library/std/src/io/tests.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -438,9 +438,7 @@ fn take_seek() -> io::Result<()> {
438438
take.read_exact(&mut buf1)?;
439439
assert_eq!(buf1, [b'5']);
440440
assert_eq!(take.seek(SeekFrom::Start(4))?, 4);
441-
assert_eq!(take.seek(SeekFrom::Start(5))?, 4);
442441

443-
assert_eq!(take.seek(SeekFrom::End(1))?, 4);
444442
assert_eq!(take.seek(SeekFrom::End(0))?, 4);
445443
assert_eq!(take.seek(SeekFrom::End(-1))?, 3);
446444
take.read_exact(&mut buf1)?;
@@ -472,7 +470,6 @@ fn take_seek() -> io::Result<()> {
472470
assert_eq!(buf2, [b'2', b'3']);
473471

474472
assert_eq!(take.seek(SeekFrom::Current(2))?, 4);
475-
assert_eq!(take.seek(SeekFrom::Current(10))?, 4);
476473

477474
Ok(())
478475
}
@@ -517,7 +514,7 @@ impl Seek for ExampleHugeRangeOfZeroes {
517514
fn take_seek_big_offsets() -> io::Result<()> {
518515
let inner = ExampleHugeRangeOfZeroes { position: 1 };
519516
let mut take = inner.take(u64::MAX - 2);
520-
assert_eq!(take.seek(io::SeekFrom::Start(u64::MAX))?, u64::MAX - 2);
517+
assert_eq!(take.seek(io::SeekFrom::Start(u64::MAX - 2))?, u64::MAX - 2);
521518
assert_eq!(take.inner.position, u64::MAX - 1);
522519
assert_eq!(take.seek(io::SeekFrom::Start(0))?, 0);
523520
assert_eq!(take.inner.position, 1);

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@
320320
#![feature(thread_local)]
321321
#![feature(try_blocks)]
322322
#![feature(type_alias_impl_trait)]
323+
#![feature(unsigned_signed_diff)]
323324
// tidy-alphabetical-end
324325
//
325326
// Library features (core):

0 commit comments

Comments
 (0)