1use crate::randfile::RandFile;
2use std::io::{Read, Result, Seek};
3
4#[cfg(all(feature = "mapped_io", not(target_arch = "wasm32")))]
5use std::fs::File;
6
7pub struct Blob<T> {
8 file: RandFile<T>,
9 size: usize,
10 offset: u64,
11}
12
13pub struct BlobReader<'a, T> {
14 cursor: u64,
15 blob: &'a mut Blob<T>,
16}
17
18impl<'a, T: Read + Seek> Read for BlobReader<'a, T> {
19 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
20 let bytes_read = self.blob.read_block(self.cursor, buf)?;
21 self.cursor += bytes_read as u64;
22 Ok(bytes_read)
23 }
24}
25
26impl<T: Read + Seek> Blob<T> {
27 pub fn get_reader(&mut self) -> BlobReader<'_, T> {
28 BlobReader {
29 cursor: 0,
30 blob: self,
31 }
32 }
33 pub fn size(&self) -> usize {
34 self.size
35 }
36 pub fn get_view(&self, offset: u64, size: usize) -> Self {
37 let rel_offset = offset.min(self.size as u64);
38 let abs_offset = self.offset + rel_offset;
39 let size = (self.size - rel_offset as usize).min(size);
40
41 Self {
42 file: self.file.clone(),
43 size,
44 offset: abs_offset,
45 }
46 }
47 pub fn read_block(&mut self, offset: u64, buf: &mut [u8]) -> Result<usize> {
48 if self.size < offset as usize {
49 return Ok(0);
50 }
51
52 let bytes_to_read = buf.len().min(self.size - offset as usize);
53
54 self.file.read_block(self.offset + offset, buf)?;
55
56 Ok(bytes_to_read)
57 }
58}
59
60impl<T> Blob<T> {
61 pub(crate) fn new(file: RandFile<T>, offset: u64, size: usize) -> Self {
62 Self { file, size, offset }
63 }
64}
65
66#[cfg(all(feature = "mapped_io", not(target_arch = "wasm32")))]
67impl Blob<File> {
68 pub fn mmap(&self) -> Result<impl AsRef<[u8]>> {
69 self.file.mmap(self.offset, self.size)
70 }
71 pub fn mmap_mut(&mut self) -> Result<impl AsMut<[u8]>> {
72 self.file.mmap_mut(self.offset, self.size)
73 }
74}