Skip to content

Commit 38b3598

Browse files
committedOct 13, 2024
Make SeekFrom::End relative to end of TakeSeek
Fixes jam1garner#291.
1 parent 73ca4c2 commit 38b3598

File tree

2 files changed

+121
-30
lines changed

2 files changed

+121
-30
lines changed
 

‎binrw/src/io/take_seek.rs

+12
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,18 @@ impl<T: Read> Read for TakeSeek<T> {
9090

9191
impl<T: Seek> Seek for TakeSeek<T> {
9292
fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
93+
let pos = match pos {
94+
SeekFrom::End(end) => match self.end.checked_add_signed(end) {
95+
Some(pos) => SeekFrom::Start(pos),
96+
None => {
97+
return Err(super::Error::new(
98+
super::ErrorKind::InvalidInput,
99+
"invalid seek to a negative or overflowing position",
100+
))
101+
}
102+
},
103+
pos => pos,
104+
};
93105
self.pos = self.inner.seek(pos)?;
94106
Ok(self.pos)
95107
}

‎binrw/tests/io/take_seek.rs

+109-30
Original file line numberDiff line numberDiff line change
@@ -6,39 +6,118 @@ fn take_seek() {
66
let data = &mut Cursor::new(b"hello world".to_vec());
77
let mut buf = [0; 5];
88
let mut take = data.take_seek(6);
9-
assert_eq!(take.get_ref().position(), 0);
9+
10+
assert_eq!(take.get_ref().position(), 0, "`get_ref` seems broken");
1011
take.get_mut().get_mut()[10] = b'b';
11-
assert_eq!(take.limit(), 6);
12-
assert_eq!(take.read(&mut buf).unwrap(), 5);
13-
assert_eq!(take.get_ref().position(), 5);
14-
assert_eq!(take.stream_position().unwrap(), 5);
15-
assert_eq!(take.limit(), 1);
16-
assert_eq!(&buf, b"hello");
17-
assert_eq!(take.seek(SeekFrom::Current(1)).unwrap(), 6);
18-
assert_eq!(take.stream_position().unwrap(), 6);
19-
assert_eq!(take.limit(), 0);
20-
assert_eq!(take.read(&mut buf).unwrap(), 0);
21-
assert_eq!(take.limit(), 0);
22-
assert_eq!(take.stream_position().unwrap(), 6);
12+
assert_eq!(take.get_ref().get_ref()[10], b'b', "`get_mut` seems broken");
13+
assert_eq!(take.limit(), 6, "wrong initial limit");
14+
assert_eq!(take.read(&mut buf).unwrap(), 5, "`read` seems broken");
15+
assert_eq!(take.get_ref().position(), 5, "`read` from a mystery source");
16+
assert_eq!(take.stream_position().unwrap(), 5, "bad stream position");
17+
assert_eq!(take.limit(), 1, "limit did not update after a read");
18+
assert_eq!(&buf, b"hello", "`read` read wrong data");
19+
20+
assert_eq!(
21+
take.seek(SeekFrom::Current(1)).unwrap(),
22+
6,
23+
"`SeekFrom::Current` returned wrong position"
24+
);
25+
assert_eq!(
26+
take.stream_position().unwrap(),
27+
6,
28+
"stream position did not update after `SeekFrom::Current`"
29+
);
30+
assert_eq!(take.limit(), 0, "limit did not update after `seek`");
31+
assert_eq!(
32+
take.read(&mut buf).unwrap(),
33+
0,
34+
"`read` did something even though limit was 0"
35+
);
36+
assert_eq!(
37+
take.limit(),
38+
0,
39+
"`read` changed the limit even though it should not have done anything"
40+
);
41+
assert_eq!(
42+
take.stream_position().unwrap(),
43+
6,
44+
"`read` updated the stream position even though it should not have done anything"
45+
);
46+
2347
take.set_limit(5);
24-
assert_eq!(take.read(&mut buf).unwrap(), 5);
25-
assert_eq!(take.read(&mut buf).unwrap(), 0);
26-
assert_eq!(&buf, b"worlb");
27-
assert_eq!(take.seek(SeekFrom::Start(0)).unwrap(), 0);
28-
assert_eq!(take.stream_position().unwrap(), 0);
29-
assert_eq!(take.read(&mut buf).unwrap(), 5);
30-
assert_eq!(take.read(&mut buf).unwrap(), 5);
31-
assert_eq!(take.read(&mut buf).unwrap(), 1);
32-
assert_eq!(take.seek(SeekFrom::Start(0)).unwrap(), 0);
48+
assert_eq!(
49+
take.read(&mut buf).unwrap(),
50+
5,
51+
"`set_limit` caused too-small read"
52+
);
53+
assert_eq!(
54+
take.read(&mut buf).unwrap(),
55+
0,
56+
"`set_limit` caused too-large zero-limit read"
57+
);
58+
assert_eq!(&buf, b"worlb", "`read` read wrong data");
59+
60+
assert_eq!(
61+
take.seek(SeekFrom::Start(0)).unwrap(),
62+
0,
63+
"`SeekFrom::Start` returned wrong position"
64+
);
65+
assert_eq!(
66+
take.stream_position().unwrap(),
67+
0,
68+
"stream position did not update after `SeekFrom::Start`"
69+
);
70+
assert_eq!(
71+
take.read(&mut buf).unwrap(),
72+
5,
73+
"`read` did not read enough after `SeemFrom::Start`"
74+
);
75+
assert_eq!(
76+
take.read(&mut buf).unwrap(),
77+
5,
78+
"`read` did not read enough after `SeemFrom::Start`"
79+
);
80+
assert_eq!(
81+
take.read(&mut buf).unwrap(),
82+
1,
83+
"`read` read incorrect amount at end of stream"
84+
);
85+
assert_eq!(
86+
take.seek(SeekFrom::Start(0)).unwrap(),
87+
0,
88+
"`SeekFrom::Start` returned wrong position at end of stream"
89+
);
90+
3391
take.set_limit(3);
34-
assert_eq!(take.read(&mut buf).unwrap(), 3);
35-
assert_eq!(&buf, b"helrl");
36-
assert_eq!(take.seek(SeekFrom::End(-5)).unwrap(), 6);
37-
assert_eq!(take.stream_position().unwrap(), 6);
38-
assert_eq!(take.read(&mut buf).unwrap(), 0);
39-
assert_eq!(take.seek(SeekFrom::End(-10)).unwrap(), 1);
40-
assert_eq!(take.read(&mut buf).unwrap(), 2);
41-
assert_eq!(take.into_inner().position(), 3);
92+
assert_eq!(
93+
take.read(&mut buf).unwrap(),
94+
3,
95+
"`set_limit` caused too-large partial-limit read"
96+
);
97+
assert_eq!(&buf, b"helrl", "`read` read wrong data");
98+
99+
take.seek(SeekFrom::End(-5))
100+
.expect_err("out-of-range `SeekFrom::End` backward seek should fail");
101+
102+
take.seek(SeekFrom::Start(0)).unwrap();
103+
take.set_limit(10);
104+
assert_eq!(
105+
take.seek(SeekFrom::End(-6)).unwrap(),
106+
4,
107+
"`SeekFrom::End` returned wrong position"
108+
);
109+
assert_eq!(
110+
take.stream_position().unwrap(),
111+
4,
112+
"stream position did not update after `SeekFrom::End`"
113+
);
114+
assert_eq!(
115+
take.read(&mut buf).unwrap(),
116+
5,
117+
"`read` after `SeekFrom::End` read wrong number of bytes"
118+
);
119+
assert_eq!(&buf, b"o wor", "`read` read wrong data");
120+
assert_eq!(take.into_inner().position(), 9, "`into_inner` seems broken");
42121
}
43122

44123
#[test]

0 commit comments

Comments
 (0)
Please sign in to comment.