Skip to main content

stuffr_core/source/
file.rs

1use std::fs::File;
2use std::io::Read;
3use std::path::Path;
4
5use super::{GuardedSeek, SeekRead, Source, SourceCaps};
6use crate::error::Result;
7
8/// A seekable source backed by a real file. The Exact rung.
9pub struct FileSource {
10    /// Wrapped, never bare: a container seeks to positions the ARCHIVE
11    /// declares, and a `u64` above `i64::MAX` reaches `lseek(2)` as a
12    /// negative offset and comes back as an unclassified `EINVAL`. See
13    /// [`GuardedSeek`]'s module doc.
14    file: GuardedSeek<File>,
15    len: u64,
16}
17
18impl FileSource {
19    pub fn open(path: &Path) -> Result<Self> {
20        Self::from_file(File::open(path)?)
21    }
22
23    pub fn from_file(file: File) -> Result<Self> {
24        let len = file.metadata()?.len();
25        Ok(Self {
26            file: GuardedSeek::new(file),
27            len,
28        })
29    }
30}
31
32impl Read for FileSource {
33    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
34        self.file.read(buf)
35    }
36}
37
38impl Source for FileSource {
39    fn caps(&self) -> SourceCaps {
40        SourceCaps {
41            seekable: true,
42            len: Some(self.len),
43        }
44    }
45
46    fn as_seek(&mut self) -> Option<&mut dyn SeekRead> {
47        Some(&mut self.file)
48    }
49}