1use std::{
2 io::{Read, Seek},
3 ops::RangeInclusive,
4};
5
6use crate::{
7 multifile::{File, MultiFile},
8 utils::calculate_seek,
9 vec_deq::VecDeque,
10};
11
12pub struct ExactReader<R> {
14 file: R,
16
17 file_offset_view: RangeInclusive<usize>,
19
20 size: usize,
22
23 buffer: VecDeque<u8>,
25 buffer_offset: usize,
27
28 seeked: Option<usize>,
30}
31
32impl<R: Read + Seek> ExactReader<MultiFile<R>> {
33 pub fn new_multi(file: MultiFile<R>) -> Self {
35 let size = file.size();
36
37 Self {
38 file,
39 size,
40 buffer: VecDeque::new(),
41 file_offset_view: 0..=0,
42 buffer_offset: 0,
43 seeked: None,
44 }
45 }
46}
47
48impl<R: Read + Seek> ExactReader<File<R>> {
49 pub fn new_single(file: File<R>) -> Self {
51 let size = file.size;
52
53 Self {
54 file,
55 size,
56 buffer: VecDeque::new(),
57 file_offset_view: 0..=0,
58 buffer_offset: 0,
59 seeked: None,
60 }
61 }
62}
63
64impl<R: Read + Seek> ExactReader<R> {
65 pub fn size(&self) -> usize {
67 self.size
68 }
69
70 #[inline]
72 fn physical_idx(&self) -> usize {
73 self.file_offset_view.start() + self.buffer_offset
74 }
75
76 fn _read(&mut self, buf: &mut Vec<u8>, read_size: usize, head: usize, tail: usize) {
78 let _ = self.file.by_ref().take(read_size as u64).read_to_end(buf);
79 self.file_offset_view = head..=tail;
80 }
81
82 pub fn reserve(&mut self, reserve_size: usize) {
84 let real_head = self.file_offset_view.start();
85
86 if let Some(seek_head) = self.seeked.take() {
87 let seek_tail = seek_head + reserve_size;
88
89 if self.file_offset_view.contains(&seek_head) {
90 self.buffer_offset = seek_head - real_head;
91 } else if self.file_offset_view.contains(&seek_tail) {
92 let read_size = self.file_offset_view.start() - seek_head;
93 let mut buf: Vec<u8> = Vec::with_capacity(read_size); self._read(&mut buf, read_size, seek_head, seek_tail);
96 self.buffer_offset = 0;
97
98 self.buffer.extend_front(buf.as_slice());
99 return;
100 }
101 let mut buf: Vec<u8> = Vec::with_capacity(reserve_size); self._read(&mut buf, reserve_size, seek_head, seek_tail);
103
104 self.buffer_offset = 0;
105
106 self.buffer.clear();
107 self.buffer.extend_back(buf.as_slice());
108
109 return;
110 }
111
112 if self.buffer.len() >= self.buffer_offset + reserve_size {
113 return;
114 }
115
116 let mut buf: Vec<u8> = Vec::with_capacity(reserve_size); let tail = self.file_offset_view.start() + self.buffer.len() + buf.len();
118 self._read(&mut buf, reserve_size, *self.file_offset_view.start(), tail);
119
120 self.buffer.extend_back(buf.as_mut_slice());
121 }
122}
123
124impl<R: Read + Seek> Read for ExactReader<R> {
125 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
126 let size = buf.len();
128 self.reserve(size);
129
130 let (head, tail) = self.buffer.as_slices();
131 let head_len = head.len();
132 let adjusted_head_len = head_len.saturating_sub(self.buffer_offset);
133 let tail_offset = self.buffer_offset.saturating_sub(head_len);
134
135 if adjusted_head_len == 0 {
136 buf.copy_from_slice(&tail[tail_offset..tail_offset + size]);
138 } else if adjusted_head_len >= size {
139 buf.copy_from_slice(&head[self.buffer_offset..self.buffer_offset + size]);
141 } else {
142 buf[..adjusted_head_len].copy_from_slice(&head[self.buffer_offset..]);
144 buf[adjusted_head_len..]
145 .copy_from_slice(&tail[tail_offset..tail_offset + size - adjusted_head_len]);
146 }
147 self.buffer_offset += size;
148
149 Ok(size)
150 }
151}
152
153impl<R: Read + Seek> Seek for ExactReader<R> {
154 fn seek(&mut self, pos: std::io::SeekFrom) -> std::io::Result<u64> {
155 let calculated_seek = calculate_seek(self.size, self.physical_idx(), pos)? as usize;
156 if self.file_offset_view.contains(&calculated_seek) {
157 self.buffer_offset = calculated_seek - self.file_offset_view.start();
158 return Ok(calculated_seek as u64);
159 }
160
161 let result = self.file.seek(pos)?;
162 self.seeked = Some(result as usize);
163
164 Ok(result)
165 }
166
167 fn stream_position(&mut self) -> std::io::Result<u64> {
168 Ok(self.physical_idx() as u64)
169 }
170}