1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//! `Filesystem` trait — the common interface for all disc filesystem browsers.
use super::entry::FileEntry;
use thiserror::Error;
/// Errors returned by filesystem operations.
#[derive(Debug, Error)]
pub enum FilesystemError {
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Not a directory: {0}")]
NotADirectory(String),
#[error("Entry not found: {0}")]
NotFound(String),
#[error("Parse error: {0}")]
Parse(String),
#[error("Unsupported filesystem")]
Unsupported,
#[error("Invalid data: {0}")]
InvalidData(String),
}
/// Uniform interface for browsing files on a disc image, regardless of
/// container format (ISO, BIN/CUE, CHD) or on-disc filesystem (ISO9660, HFS, HFS+).
pub trait Filesystem: Send {
/// Return the root directory entry.
fn root(&mut self) -> Result<FileEntry, FilesystemError>;
/// List the direct children of a directory entry.
fn list_directory(&mut self, entry: &FileEntry) -> Result<Vec<FileEntry>, FilesystemError>;
/// Read the entire contents of a file entry into memory.
fn read_file(&mut self, entry: &FileEntry) -> Result<Vec<u8>, FilesystemError>;
/// Read a byte range from a file (for large files that should not be fully loaded).
fn read_file_range(
&mut self,
entry: &FileEntry,
offset: u64,
length: usize,
) -> Result<Vec<u8>, FilesystemError>;
/// Read the entire resource fork of a file.
///
/// Returns `Ok(None)` when the filesystem does not support resource forks
/// (ISO 9660) or when the file has no resource fork. HFS/HFS+ return
/// `Ok(Some(vec![]))` for files whose resource fork exists but has zero
/// length — callers can use `resource_fork_size` on [`FileEntry`] to
/// decide whether calling this is worthwhile.
fn read_resource_fork(&mut self, entry: &FileEntry)
-> Result<Option<Vec<u8>>, FilesystemError>;
/// Read a byte range from the resource fork. Returns `Ok(None)` under
/// the same conditions as [`Self::read_resource_fork`].
fn read_resource_fork_range(
&mut self,
entry: &FileEntry,
offset: u64,
length: usize,
) -> Result<Option<Vec<u8>>, FilesystemError>;
/// The volume label, if the filesystem provides one.
fn volume_name(&self) -> Option<&str>;
}