Initial xenia-rs
This commit is contained in:
12
xenia-rs/crates/xenia-vfs/Cargo.toml
Normal file
12
xenia-rs/crates/xenia-vfs/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "xenia-vfs"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
xenia-types = { workspace = true }
|
||||
tracing = { workspace = true }
|
||||
byteorder = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
54
xenia-rs/crates/xenia-vfs/src/device.rs
Normal file
54
xenia-rs/crates/xenia-vfs/src/device.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
use crate::{VfsDevice, VfsEntry, VfsError};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
/// Host filesystem pass-through device.
|
||||
pub struct HostPathDevice {
|
||||
name: String,
|
||||
root: PathBuf,
|
||||
}
|
||||
|
||||
impl HostPathDevice {
|
||||
pub fn new(name: impl Into<String>, root: impl AsRef<Path>) -> Self {
|
||||
Self {
|
||||
name: name.into(),
|
||||
root: root.as_ref().to_path_buf(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl VfsDevice for HostPathDevice {
|
||||
fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
fn list_root(&self) -> Result<Vec<VfsEntry>, VfsError> {
|
||||
let mut entries = Vec::new();
|
||||
for entry in std::fs::read_dir(&self.root)? {
|
||||
let entry = entry?;
|
||||
let metadata = entry.metadata()?;
|
||||
entries.push(VfsEntry {
|
||||
name: entry.file_name().to_string_lossy().into_owned(),
|
||||
is_directory: metadata.is_dir(),
|
||||
size: metadata.len(),
|
||||
offset: 0,
|
||||
});
|
||||
}
|
||||
Ok(entries)
|
||||
}
|
||||
|
||||
fn read_file(&self, path: &str) -> Result<Vec<u8>, VfsError> {
|
||||
let full_path = self.root.join(path);
|
||||
std::fs::read(&full_path).map_err(VfsError::from)
|
||||
}
|
||||
|
||||
fn stat(&self, path: &str) -> Result<VfsEntry, VfsError> {
|
||||
let full_path = self.root.join(path);
|
||||
let metadata = std::fs::metadata(&full_path)?;
|
||||
Ok(VfsEntry {
|
||||
name: path.to_string(),
|
||||
is_directory: metadata.is_dir(),
|
||||
size: metadata.len(),
|
||||
offset: 0,
|
||||
})
|
||||
}
|
||||
}
|
||||
40
xenia-rs/crates/xenia-vfs/src/disc_image.rs
Normal file
40
xenia-rs/crates/xenia-vfs/src/disc_image.rs
Normal file
@@ -0,0 +1,40 @@
|
||||
use crate::{VfsDevice, VfsEntry, VfsError};
|
||||
|
||||
/// XISO disc image device. Parses Xbox 360 disc images.
|
||||
pub struct DiscImageDevice {
|
||||
name: String,
|
||||
_data: Vec<u8>,
|
||||
}
|
||||
|
||||
/// XISO sector size
|
||||
pub const SECTOR_SIZE: usize = 0x800;
|
||||
|
||||
impl DiscImageDevice {
|
||||
pub fn open(name: impl Into<String>, path: &std::path::Path) -> Result<Self, VfsError> {
|
||||
let data = std::fs::read(path)?;
|
||||
// TODO: validate XISO header
|
||||
Ok(Self {
|
||||
name: name.into(),
|
||||
_data: data,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl VfsDevice for DiscImageDevice {
|
||||
fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
fn list_root(&self) -> Result<Vec<VfsEntry>, VfsError> {
|
||||
// TODO: Parse XISO directory tree
|
||||
Ok(Vec::new())
|
||||
}
|
||||
|
||||
fn read_file(&self, _path: &str) -> Result<Vec<u8>, VfsError> {
|
||||
Err(VfsError::NotFound("Not yet implemented".into()))
|
||||
}
|
||||
|
||||
fn stat(&self, _path: &str) -> Result<VfsEntry, VfsError> {
|
||||
Err(VfsError::NotFound("Not yet implemented".into()))
|
||||
}
|
||||
}
|
||||
33
xenia-rs/crates/xenia-vfs/src/lib.rs
Normal file
33
xenia-rs/crates/xenia-vfs/src/lib.rs
Normal file
@@ -0,0 +1,33 @@
|
||||
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)]
|
||||
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>;
|
||||
}
|
||||
Reference in New Issue
Block a user