mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-04 00:21:57 +00:00
Added minimal drv cursor implementation.
This commit is contained in:
parent
c0e9786666
commit
7bde99906a
@ -16,6 +16,7 @@ log = "0.4.13"
|
||||
# Util
|
||||
byteorder = "1.4.2"
|
||||
chrono = "0.4.19"
|
||||
bit-vec = "0.6.3"
|
||||
|
||||
# Derives
|
||||
thiserror = "1.0.23"
|
||||
|
||||
219
dcb-drv/src/cursor.rs
Normal file
219
dcb-drv/src/cursor.rs
Normal file
@ -0,0 +1,219 @@
|
||||
//! Filesystem cursor
|
||||
|
||||
// Modules
|
||||
pub mod error;
|
||||
|
||||
// Exports
|
||||
pub use error::NewError;
|
||||
|
||||
// Imports
|
||||
use crate::{dir::entry::DirEntryReaderKind, DirEntryReader, DirReader};
|
||||
use bit_vec::BitVec;
|
||||
use chrono::NaiveDateTime;
|
||||
use dcb_util::AsciiStrArr;
|
||||
use std::{
|
||||
convert::{TryFrom, TryInto},
|
||||
io,
|
||||
};
|
||||
|
||||
/// Filesystem cursor
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub struct DrvFsCursor {
|
||||
/// Root directory
|
||||
root_dir: DirCursor,
|
||||
|
||||
/// All sectors' status
|
||||
sector_status: BitVec,
|
||||
}
|
||||
|
||||
impl DrvFsCursor {
|
||||
/// Creates a new filesystem cursor
|
||||
pub fn new<R: io::Read + io::Seek>(reader: &mut R) -> Result<Self, NewError> {
|
||||
/// Helper function that sets sector status given a directory
|
||||
fn iter_file_tree<R: io::Read + io::Seek>(
|
||||
cursor: &mut R, dir: DirReader, sector_status: &mut BitVec,
|
||||
) -> Result<DirCursor, NewError> {
|
||||
// Read all entries
|
||||
// TODO: Avoid allocations by going through all entries twice.
|
||||
let entries_reader: Vec<DirEntryReader> = dir
|
||||
.read_entries(cursor)
|
||||
.map_err(|err| NewError::ReadDir {
|
||||
sector_pos: dir.sector_pos(),
|
||||
err,
|
||||
})?
|
||||
.collect::<Result<_, _>>()
|
||||
.map_err(|err| NewError::ReadDirEntry {
|
||||
sector_pos: dir.sector_pos(),
|
||||
err,
|
||||
})?;
|
||||
|
||||
// Set the entries of the directory as filled
|
||||
let dir_sector = usize::try_from(dir.sector_pos()).expect("Sector position didn't fit into `usize`");
|
||||
let dir_sectors_len = ((entries_reader.len() + 0x1) * 0x20 + 0x7ff) / 0x800;
|
||||
for n in 0..dir_sectors_len {
|
||||
sector_status.set(dir_sector + n, true);
|
||||
}
|
||||
|
||||
// Then add all entries
|
||||
let mut entries = vec![];
|
||||
for entry in entries_reader {
|
||||
let kind = match *entry.kind() {
|
||||
DirEntryReaderKind::Dir(dir) => {
|
||||
let dir = iter_file_tree(cursor, dir, sector_status)?;
|
||||
|
||||
DirEntryCursorKind::Dir(dir)
|
||||
},
|
||||
DirEntryReaderKind::File(file) => {
|
||||
// Set the file as filled
|
||||
let file_sector =
|
||||
usize::try_from(file.sector_pos()).expect("Sector position didn't fit into `usize`");
|
||||
let file_sectors_len =
|
||||
usize::try_from((file.size() + 0x7ff) / 0x800).expect("File size didn't fit into `usize`");
|
||||
for n in 0..file_sectors_len {
|
||||
sector_status.set(file_sector + n, true);
|
||||
}
|
||||
|
||||
DirEntryCursorKind::File(FileCursor {
|
||||
extension: *file.extension(),
|
||||
sector_pos: file.sector_pos(),
|
||||
size: file.size(),
|
||||
})
|
||||
},
|
||||
};
|
||||
|
||||
let entry = DirEntryCursor {
|
||||
name: *entry.name(),
|
||||
date: entry.date(),
|
||||
kind,
|
||||
};
|
||||
entries.push(entry);
|
||||
}
|
||||
|
||||
Ok(DirCursor {
|
||||
sector_pos: dir.sector_pos(),
|
||||
entries,
|
||||
})
|
||||
}
|
||||
|
||||
// Go through all directories and files and create a status
|
||||
let size: usize = reader
|
||||
.stream_len()
|
||||
.map_err(NewError::FileSize)?
|
||||
.try_into()
|
||||
.expect("File size didn't fit into `usize`");
|
||||
let mut sector_status = BitVec::from_elem((size + 0x7ff) / 0x800, false);
|
||||
|
||||
let root_dir = iter_file_tree(reader, DirReader::new(0), &mut sector_status)?;
|
||||
|
||||
Ok(Self {
|
||||
root_dir,
|
||||
sector_status,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the root directory
|
||||
#[must_use]
|
||||
pub const fn root_dir(&self) -> &DirCursor {
|
||||
&self.root_dir
|
||||
}
|
||||
|
||||
/// Returns the root directory mutably
|
||||
#[must_use]
|
||||
pub fn root_dir_mut(&mut self) -> &mut DirCursor {
|
||||
&mut self.root_dir
|
||||
}
|
||||
}
|
||||
|
||||
/// A directory
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub struct DirCursor {
|
||||
/// Sector position
|
||||
sector_pos: u32,
|
||||
|
||||
/// All entries
|
||||
entries: Vec<DirEntryCursor>,
|
||||
}
|
||||
|
||||
impl DirCursor {
|
||||
/// Returns all entries
|
||||
#[must_use]
|
||||
pub fn entries(&self) -> &[DirEntryCursor] {
|
||||
&self.entries
|
||||
}
|
||||
}
|
||||
|
||||
/// A directory entry cursor
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub struct DirEntryCursor {
|
||||
/// Entry name
|
||||
name: AsciiStrArr<0x10>,
|
||||
|
||||
/// Entry date
|
||||
date: NaiveDateTime,
|
||||
|
||||
/// Kind
|
||||
kind: DirEntryCursorKind,
|
||||
}
|
||||
|
||||
impl DirEntryCursor {
|
||||
/// Get a reference to the dir entry cursor's name.
|
||||
#[must_use]
|
||||
pub const fn name(&self) -> &AsciiStrArr<0x10> {
|
||||
&self.name
|
||||
}
|
||||
|
||||
/// Get a reference to the dir entry cursor's date.
|
||||
#[must_use]
|
||||
pub const fn date(&self) -> &NaiveDateTime {
|
||||
&self.date
|
||||
}
|
||||
|
||||
/// Get a reference to the dir entry cursor's kind.
|
||||
#[must_use]
|
||||
pub const fn kind(&self) -> &DirEntryCursorKind {
|
||||
&self.kind
|
||||
}
|
||||
}
|
||||
|
||||
/// A directory entry kind
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub enum DirEntryCursorKind {
|
||||
/// Directory
|
||||
Dir(DirCursor),
|
||||
|
||||
/// File
|
||||
File(FileCursor),
|
||||
}
|
||||
|
||||
/// A file cursor
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub struct FileCursor {
|
||||
/// Extension
|
||||
extension: AsciiStrArr<0x3>,
|
||||
|
||||
/// Sector position
|
||||
sector_pos: u32,
|
||||
|
||||
/// Size
|
||||
size: u32,
|
||||
}
|
||||
|
||||
impl FileCursor {
|
||||
/// Get a reference to the file cursor's extension.
|
||||
#[must_use]
|
||||
pub const fn extension(&self) -> &AsciiStrArr<0x3> {
|
||||
&self.extension
|
||||
}
|
||||
|
||||
/// Get a reference to the file cursor's sector pos.
|
||||
#[must_use]
|
||||
pub const fn sector_pos(&self) -> &u32 {
|
||||
&self.sector_pos
|
||||
}
|
||||
|
||||
/// Get a reference to the file cursor's size.
|
||||
#[must_use]
|
||||
pub const fn size(&self) -> &u32 {
|
||||
&self.size
|
||||
}
|
||||
}
|
||||
34
dcb-drv/src/cursor/error.rs
Normal file
34
dcb-drv/src/cursor/error.rs
Normal file
@ -0,0 +1,34 @@
|
||||
//! Errors
|
||||
|
||||
use crate::dir::reader::{ReadEntriesError, ReadEntryError};
|
||||
use std::io;
|
||||
|
||||
/// Error for [`Dir::read_entries`](super::Dir::read_entries)
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum NewError {
|
||||
/// Unable to get file size
|
||||
#[error("Unable to get file size")]
|
||||
FileSize(#[source] io::Error),
|
||||
|
||||
/// Unable to read directory
|
||||
#[error("Unable to read directory at {sector_pos:#x}")]
|
||||
ReadDir {
|
||||
/// Position of the sector
|
||||
sector_pos: u32,
|
||||
|
||||
/// Underlying error
|
||||
#[source]
|
||||
err: ReadEntriesError,
|
||||
},
|
||||
|
||||
/// Unable to read directory entry
|
||||
#[error("Unable to read directory entry at {sector_pos:#x}")]
|
||||
ReadDirEntry {
|
||||
/// Position of the sector
|
||||
sector_pos: u32,
|
||||
|
||||
/// Underlying error
|
||||
#[source]
|
||||
err: ReadEntryError,
|
||||
},
|
||||
}
|
||||
@ -19,6 +19,12 @@ pub struct DirReader {
|
||||
}
|
||||
|
||||
impl DirReader {
|
||||
/// Creates a directory reader for the root directory
|
||||
#[must_use]
|
||||
pub const fn root() -> Self {
|
||||
Self::new(0)
|
||||
}
|
||||
|
||||
/// Creates a directory reader from it's sector
|
||||
#[must_use]
|
||||
pub const fn new(sector_pos: u32) -> Self {
|
||||
|
||||
@ -6,7 +6,7 @@ use dcb_util::AsciiStrArr;
|
||||
use std::io::{self, SeekFrom};
|
||||
|
||||
/// A file reader
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub struct FileReader {
|
||||
/// File extension
|
||||
extension: AsciiStrArr<0x3>,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
#![doc(include = "lib.md")]
|
||||
// Features
|
||||
#![feature(external_doc)]
|
||||
#![feature(external_doc, seek_stream_len)]
|
||||
// Lints
|
||||
#![warn(clippy::restriction, clippy::pedantic, clippy::nursery)]
|
||||
// We'll disable the ones we don't need
|
||||
@ -58,6 +58,7 @@
|
||||
#![allow(clippy::map_err_ignore)]
|
||||
|
||||
// Modules
|
||||
pub mod cursor;
|
||||
pub mod dir;
|
||||
pub mod error;
|
||||
pub mod file;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user