1use std::io::{Read, Seek, SeekFrom, Write};
2
3use wedeo_core::error::{Error, Result};
4
5pub trait IoContext: Send + Sync {
8 fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
9 fn write(&mut self, buf: &[u8]) -> Result<usize>;
10 fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
11 fn tell(&mut self) -> Result<u64>;
12 fn size(&mut self) -> Result<u64>;
13 fn is_seekable(&self) -> bool;
14}
15
16pub struct FileIo {
18 file: std::fs::File,
19}
20
21impl FileIo {
22 pub fn open(path: &str) -> Result<Self> {
23 let file = std::fs::File::open(path)?;
24 Ok(Self { file })
25 }
26
27 pub fn create(path: &str) -> Result<Self> {
28 let file = std::fs::OpenOptions::new()
29 .read(true)
30 .write(true)
31 .create(true)
32 .truncate(true)
33 .open(path)?;
34 Ok(Self { file })
35 }
36}
37
38impl IoContext for FileIo {
39 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
40 Ok(self.file.read(buf)?)
41 }
42
43 fn write(&mut self, buf: &[u8]) -> Result<usize> {
44 Ok(self.file.write(buf)?)
45 }
46
47 fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
48 Ok(self.file.seek(pos)?)
49 }
50
51 fn tell(&mut self) -> Result<u64> {
52 Ok(self.file.stream_position()?)
53 }
54
55 fn size(&mut self) -> Result<u64> {
56 let metadata = self.file.metadata()?;
57 Ok(metadata.len())
58 }
59
60 fn is_seekable(&self) -> bool {
61 true
62 }
63}
64
65struct DeadIo;
68
69impl IoContext for DeadIo {
70 fn read(&mut self, _buf: &mut [u8]) -> Result<usize> {
71 Err(Error::Other("I/O context has been taken".into()))
72 }
73 fn write(&mut self, _buf: &[u8]) -> Result<usize> {
74 Err(Error::Other("I/O context has been taken".into()))
75 }
76 fn seek(&mut self, _pos: SeekFrom) -> Result<u64> {
77 Err(Error::Other("I/O context has been taken".into()))
78 }
79 fn tell(&mut self) -> Result<u64> {
80 Err(Error::Other("I/O context has been taken".into()))
81 }
82 fn size(&mut self) -> Result<u64> {
83 Err(Error::Other("I/O context has been taken".into()))
84 }
85 fn is_seekable(&self) -> bool {
86 false
87 }
88}
89
90pub struct BufferedIo {
94 inner: Box<dyn IoContext>,
95 read_buf: Vec<u8>,
96 read_pos: usize,
97 read_len: usize,
98 write_buf: Vec<u8>,
99 write_pos: usize,
100}
101
102impl BufferedIo {
103 const DEFAULT_BUF_SIZE: usize = 32768;
104
105 pub fn new(inner: Box<dyn IoContext>) -> Self {
106 Self {
107 inner,
108 read_buf: vec![0u8; Self::DEFAULT_BUF_SIZE],
109 read_pos: 0,
110 read_len: 0,
111 write_buf: vec![0u8; Self::DEFAULT_BUF_SIZE],
112 write_pos: 0,
113 }
114 }
115
116 pub fn take_inner(&mut self) -> Box<dyn IoContext> {
120 self.read_pos = 0;
121 self.read_len = 0;
122 self.write_pos = 0;
123 std::mem::replace(&mut self.inner, Box::new(DeadIo))
124 }
125
126 pub fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
128 let mut filled = 0;
129 while filled < buf.len() {
130 if self.read_pos >= self.read_len {
131 self.fill_buffer()?;
132 if self.read_len == 0 {
133 return Err(Error::Eof);
134 }
135 }
136 let available = self.read_len - self.read_pos;
137 let to_copy = available.min(buf.len() - filled);
138 buf[filled..filled + to_copy]
139 .copy_from_slice(&self.read_buf[self.read_pos..self.read_pos + to_copy]);
140 self.read_pos += to_copy;
141 filled += to_copy;
142 }
143 Ok(())
144 }
145
146 pub fn read_u8(&mut self) -> Result<u8> {
148 let mut buf = [0u8; 1];
149 self.read_exact(&mut buf)?;
150 Ok(buf[0])
151 }
152
153 pub fn read_u16le(&mut self) -> Result<u16> {
155 let mut buf = [0u8; 2];
156 self.read_exact(&mut buf)?;
157 Ok(u16::from_le_bytes(buf))
158 }
159
160 pub fn read_u16be(&mut self) -> Result<u16> {
162 let mut buf = [0u8; 2];
163 self.read_exact(&mut buf)?;
164 Ok(u16::from_be_bytes(buf))
165 }
166
167 pub fn read_u32le(&mut self) -> Result<u32> {
169 let mut buf = [0u8; 4];
170 self.read_exact(&mut buf)?;
171 Ok(u32::from_le_bytes(buf))
172 }
173
174 pub fn read_u32be(&mut self) -> Result<u32> {
176 let mut buf = [0u8; 4];
177 self.read_exact(&mut buf)?;
178 Ok(u32::from_be_bytes(buf))
179 }
180
181 pub fn read_i32le(&mut self) -> Result<i32> {
183 let mut buf = [0u8; 4];
184 self.read_exact(&mut buf)?;
185 Ok(i32::from_le_bytes(buf))
186 }
187
188 pub fn read_u64le(&mut self) -> Result<u64> {
190 let mut buf = [0u8; 8];
191 self.read_exact(&mut buf)?;
192 Ok(u64::from_le_bytes(buf))
193 }
194
195 pub fn read_u64be(&mut self) -> Result<u64> {
197 let mut buf = [0u8; 8];
198 self.read_exact(&mut buf)?;
199 Ok(u64::from_be_bytes(buf))
200 }
201
202 pub fn read_bytes(&mut self, len: usize) -> Result<Vec<u8>> {
204 let mut buf = vec![0u8; len];
205 self.read_exact(&mut buf)?;
206 Ok(buf)
207 }
208
209 pub fn read_up_to(&mut self, len: usize) -> Result<Vec<u8>> {
213 let mut buf = Vec::with_capacity(len);
214 while buf.len() < len {
215 if self.read_pos >= self.read_len {
216 self.fill_buffer()?;
217 if self.read_len == 0 {
218 break; }
220 }
221 let available = self.read_len - self.read_pos;
222 let to_copy = available.min(len - buf.len());
223 buf.extend_from_slice(&self.read_buf[self.read_pos..self.read_pos + to_copy]);
224 self.read_pos += to_copy;
225 }
226 Ok(buf)
227 }
228
229 pub fn skip(&mut self, n: u64) -> Result<()> {
231 if self.inner.is_seekable() {
232 let buffered_remaining = (self.read_len - self.read_pos) as u64;
234 if n <= buffered_remaining {
235 self.read_pos += n as usize;
236 return Ok(());
237 }
238 let skip_from_io = n - buffered_remaining;
239 self.read_pos = 0;
240 self.read_len = 0;
241 self.inner.seek(SeekFrom::Current(skip_from_io as i64))?;
242 } else {
243 let mut remaining = n;
245 let buf_len = self.read_buf.len();
246 let mut discard = vec![0u8; buf_len];
247 while remaining > 0 {
248 let to_skip = remaining.min(buf_len as u64) as usize;
249 self.read_exact(&mut discard[..to_skip])?;
250 remaining -= to_skip as u64;
251 }
252 }
253 Ok(())
254 }
255
256 pub fn seek(&mut self, pos: u64) -> Result<u64> {
258 self.flush_write()?;
259 self.read_pos = 0;
260 self.read_len = 0;
261 self.inner.seek(SeekFrom::Start(pos))
262 }
263
264 pub fn tell(&mut self) -> Result<u64> {
266 let io_pos = self.inner.tell()?;
267 let read_offset = (self.read_len - self.read_pos) as u64;
268 let write_offset = self.write_pos as u64;
269 Ok(io_pos.saturating_sub(read_offset) + write_offset)
270 }
271
272 pub fn size(&mut self) -> Result<u64> {
274 self.inner.size()
275 }
276
277 pub fn is_seekable(&self) -> bool {
279 self.inner.is_seekable()
280 }
281
282 pub fn write_u8(&mut self, v: u8) -> Result<()> {
286 self.write_all(&[v])
287 }
288
289 pub fn write_u16le(&mut self, v: u16) -> Result<()> {
291 self.write_all(&v.to_le_bytes())
292 }
293
294 pub fn write_u16be(&mut self, v: u16) -> Result<()> {
296 self.write_all(&v.to_be_bytes())
297 }
298
299 pub fn write_u32le(&mut self, v: u32) -> Result<()> {
301 self.write_all(&v.to_le_bytes())
302 }
303
304 pub fn write_u32be(&mut self, v: u32) -> Result<()> {
306 self.write_all(&v.to_be_bytes())
307 }
308
309 pub fn write_u64le(&mut self, v: u64) -> Result<()> {
311 self.write_all(&v.to_le_bytes())
312 }
313
314 pub fn write_bytes(&mut self, data: &[u8]) -> Result<()> {
316 self.write_all(data)
317 }
318
319 pub fn write_all(&mut self, data: &[u8]) -> Result<()> {
321 let mut offset = 0;
322 while offset < data.len() {
323 let space = self.write_buf.len() - self.write_pos;
324 let to_copy = space.min(data.len() - offset);
325 self.write_buf[self.write_pos..self.write_pos + to_copy]
326 .copy_from_slice(&data[offset..offset + to_copy]);
327 self.write_pos += to_copy;
328 offset += to_copy;
329 if self.write_pos >= self.write_buf.len() {
330 self.flush_write()?;
331 }
332 }
333 Ok(())
334 }
335
336 pub fn flush(&mut self) -> Result<()> {
338 self.flush_write()
339 }
340
341 fn flush_write(&mut self) -> Result<()> {
342 if self.write_pos > 0 {
343 let mut written = 0;
344 while written < self.write_pos {
345 let n = self.inner.write(&self.write_buf[written..self.write_pos])?;
346 if n == 0 {
347 return Err(Error::Io(std::io::ErrorKind::WriteZero));
348 }
349 written += n;
350 }
351 self.write_pos = 0;
352 }
353 Ok(())
354 }
355
356 fn fill_buffer(&mut self) -> Result<()> {
357 let n = self.inner.read(&mut self.read_buf)?;
358 self.read_pos = 0;
359 self.read_len = n;
360 Ok(())
361 }
362}
363
364pub fn read_tag(io: &mut BufferedIo) -> Result<[u8; 4]> {
366 let mut tag = [0u8; 4];
367 io.read_exact(&mut tag)?;
368 Ok(tag)
369}