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
64
65
66
67
68
69
70
71
72
73
74
75
76
use std::io::{Read, Result, Seek, SeekFrom};
type FnAPI = Box<dyn Fn(usize, &mut [u8]) -> Result<()>>;
pub struct RangedReader {
pos: u64,
length: u64,
buffer: Vec<u8>,
offset: usize,
range_fn: FnAPI,
}
impl RangedReader {
pub fn new(length: usize, range_fn: FnAPI, mut buffer: Vec<u8>) -> Self {
let length = length as u64;
buffer.clear();
Self {
pos: 0,
range_fn,
length,
buffer,
offset: 0,
}
}
fn read_more(&mut self, to_consume: usize) -> Result<()> {
let remaining = self.buffer.len() - self.offset;
if to_consume < remaining {
return Ok(());
}
let to_read = std::cmp::max(
std::cmp::max(self.offset, to_consume),
self.buffer.capacity(),
) - remaining;
self.buffer.rotate_left(self.offset);
self.buffer.resize(remaining + to_read, 0);
(self.range_fn)(self.pos as usize, &mut self.buffer[remaining..])?;
self.pos += to_read as u64;
self.offset = 0;
Ok(())
}
}
impl Read for RangedReader {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let to_consume = buf.len();
self.read_more(to_consume)?;
buf[..to_consume].copy_from_slice(&self.buffer[self.offset..self.offset + to_consume]);
self.offset += to_consume;
Ok(to_consume)
}
}
impl Seek for RangedReader {
fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
match pos {
SeekFrom::Start(pos) => self.pos = pos,
SeekFrom::End(pos) => self.pos = (self.length as i64 + pos) as u64,
SeekFrom::Current(pos) => self.pos = (self.pos as i64 + pos) as u64,
};
self.offset = 0;
self.buffer.clear();
Ok(self.pos)
}
}