DiscImageDevice now walks the GDFX tree at open() and caches every
file/dir entry by full relative path; the previous root-only scan
returned ENOENT for any path under a subdirectory (dat/tables.pak,
media/x.wav). Lookups become O(n) over the cached vec.
xex::load_image gains a tracing span plus per-load metrics
(xex.load_image_ms histogram, xex.bytes_{in,out} counters) so the
observability subscriber the app installs can see decompression cost.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
34 lines
808 B
Rust
34 lines
808 B
Rust
pub mod device;
|
|
pub mod disc_image;
|
|
|
|
use thiserror::Error;
|
|
|
|
#[derive(Debug, Error)]
|
|
pub enum VfsError {
|
|
#[error("I/O error: {0}")]
|
|
Io(#[from] std::io::Error),
|
|
|
|
#[error("Invalid format: {0}")]
|
|
InvalidFormat(String),
|
|
|
|
#[error("File not found: {0}")]
|
|
NotFound(String),
|
|
}
|
|
|
|
/// A virtual filesystem entry (file or directory).
|
|
#[derive(Debug, Clone)]
|
|
pub struct VfsEntry {
|
|
pub name: String,
|
|
pub is_directory: bool,
|
|
pub size: u64,
|
|
pub offset: u64,
|
|
}
|
|
|
|
/// Trait for VFS device implementations (XISO, STFS, host path, etc.)
|
|
pub trait VfsDevice: Send + Sync {
|
|
fn name(&self) -> &str;
|
|
fn list_root(&self) -> Result<Vec<VfsEntry>, VfsError>;
|
|
fn read_file(&self, path: &str) -> Result<Vec<u8>, VfsError>;
|
|
fn stat(&self, path: &str) -> Result<VfsEntry, VfsError>;
|
|
}
|