1use crate::BlockHeader;
2use crate::blocks::{block_get_type, block_get_timestamp, block_get_size};
3
4#[derive(Debug,Copy,Clone)]
5pub enum ReadBlocksError<ReadErrorType> {
6 BlockCutoff,
7 TrailingBytes,
8 ImpossiblySmallBlockSize,
9 FileTooSmall,
10 ReadError(ReadErrorType),
11}
12
13#[cfg(feature = "std")]
14use std::io::{self, Read, Seek, SeekFrom};
15
16#[cfg(feature = "std")]
17pub fn read_wrapper<File>(mut file: File) -> impl FnMut(u64, &mut [u8]) -> io::Result<()>
18where
19 File: Read + Seek
20{
21 let mut pos = 0u64;
22 file.rewind();
23
24 return move |read_pos: u64, out: &mut [u8]| {
25 if read_pos != pos {
26 file.seek_relative(read_pos as i64 - pos as i64)?;
27 }
28 pos = read_pos + out.len() as u64;
29 file.read_exact(out).map(|_| ())
30 }
31}
32
33pub fn read_blocks<const MAX_BLOCK_BYTES: usize, ReadError>(
34 file_length: u64,
35 mut read_exact: impl FnMut(u64, &mut [u8]) -> Result<(), ReadError>,
37 mut block_data_callback: impl FnMut(&[u8], u64) -> bool,
39) -> Result<(), ReadBlocksError<ReadError>> {
40 let mut buf = [0u8; MAX_BLOCK_BYTES];
41 let mut pos = 0u64;
42
43 if file_length < 16 {
44 return Err(ReadBlocksError::FileTooSmall)
45 }
46
47 loop {
48 if let Err(e) = read_exact(pos, &mut buf[0..16]) {
50 return Err(ReadBlocksError::ReadError(e))
51 }
52 let block_size = u32::from_le_bytes([buf[4],buf[5],buf[6],buf[7]]);
53
54 if block_size < 16 {
55 return Err(ReadBlocksError::ImpossiblySmallBlockSize)
56 }
57
58 let next_block_pos = pos + block_size as u64;
59
60 if next_block_pos > file_length {
61 println!("File length = {file_length}, nextpos = {next_block_pos}");
62 return Err(ReadBlocksError::BlockCutoff)
64 } else {
65 let read_end = (block_size as usize).min(MAX_BLOCK_BYTES);
66 if let Err(e) = read_exact(pos+16, &mut buf[16..read_end]) {
67 return Err(ReadBlocksError::ReadError(e))
68 }
69 block_data_callback(&buf[0..read_end], pos);
70 if next_block_pos == file_length {
71 return Ok(())
73 } else if file_length - next_block_pos < 16 {
74 return Err(ReadBlocksError::TrailingBytes)
76 } else { }
77
78 pos = next_block_pos;
79 }
80 }
81}