1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use std::io;
use std::io::Read;
pub struct Pos<R: Read> {
inner: R,
position: u64,
}
impl<R: Read> Pos<R> {
pub fn new(inner: R) -> Self {
Pos { inner, position: 0 }
}
pub fn position(&self) -> u64 {
self.position
}
pub fn into_inner(self) -> R {
self.inner
}
}
impl<R: Read> Read for Pos<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self.inner.read(buf) {
Ok(count) => {
self.position = self.position.saturating_add(count as u64);
Ok(count)
}
Err(e) => Err(e),
}
}
}
#[cfg(test)]
mod tests {
use super::Pos;
use std::io;
use std::io::Read;
#[test]
fn smoke_cursor() {
let mut pos = Pos::new(io::Cursor::new(vec![7, 8, 9, 10, 11, 12]));
assert_eq!(0, pos.position());
let mut buf = [0u8; 2];
pos.read_exact(&mut buf).unwrap();
assert_eq!(&[7, 8], &buf[..]);
assert_eq!(2, pos.position());
let mut buf = [0u8; 20];
assert_eq!(4, pos.read(&mut buf).unwrap());
assert_eq!(6, pos.position());
assert_eq!(0, pos.read(&mut buf).unwrap());
assert_eq!(6, pos.position());
}
}