mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-05 16:53:47 +00:00
Moved dcb_drv::find_entry to DirPtr::find.
This commit is contained in:
parent
3828aeec9b
commit
91ba3b9406
@ -1,79 +0,0 @@
|
||||
//! Entry finding
|
||||
|
||||
// Imports
|
||||
use crate::{path::Component, DirEntry, DirEntryKind, DirEntryPtr, DirPtr, Path, PathBuf};
|
||||
use std::io;
|
||||
|
||||
/// Finds an entry given it's path
|
||||
pub fn find_entry<R: io::Seek + io::Read>(
|
||||
reader: &mut R, path: &Path,
|
||||
) -> Result<(DirEntryPtr, DirEntry), FindEntryError> {
|
||||
// Current directory pointer
|
||||
let mut cur_dir_ptr = DirPtr::root();
|
||||
|
||||
// Current entry
|
||||
let mut cur_entry = None;
|
||||
|
||||
let mut components = path.components();
|
||||
while let Some(component) = components.next() {
|
||||
// Get the next entry's name
|
||||
let entry_name = match component {
|
||||
// Note: We start at the root, so `Root` doesn't do anything to us
|
||||
Component::Root | Component::CurDir => continue,
|
||||
Component::ParentDir => return Err(FindEntryError::ParentDir),
|
||||
Component::Normal(entry) => entry,
|
||||
};
|
||||
|
||||
// Find the entry
|
||||
let (entry_ptr, entry) = cur_dir_ptr
|
||||
.find_entry(reader, entry_name)
|
||||
.map_err(FindEntryError::FindEntry)?;
|
||||
|
||||
// If there's no component after this, break
|
||||
if components.clone().next().is_none() {
|
||||
return Ok((entry_ptr, entry));
|
||||
}
|
||||
|
||||
// Else check what entry we got
|
||||
match entry.kind {
|
||||
// If we got a file at this stage return error
|
||||
DirEntryKind::File { .. } => {
|
||||
return Err(FindEntryError::ExpectedDir {
|
||||
path: path[..(path.len() - components.remaining().len())].to_path_buf(),
|
||||
})
|
||||
},
|
||||
|
||||
// If we got a directory, continue
|
||||
DirEntryKind::Dir { ptr } => {
|
||||
cur_entry = Some((entry_ptr, entry));
|
||||
cur_dir_ptr = ptr;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// If we got here, try to return our current entry
|
||||
cur_entry.ok_or(FindEntryError::EmptyPath)
|
||||
}
|
||||
|
||||
/// Error type for [`find_entry`]
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum FindEntryError {
|
||||
/// Unable to find entry
|
||||
#[error("Unable to find entry")]
|
||||
FindEntry(#[source] crate::ptr::FindEntryError),
|
||||
|
||||
/// Cannot go back to parent directory
|
||||
#[error("Cannot go back to parent directory")]
|
||||
ParentDir,
|
||||
|
||||
/// Expected directory
|
||||
#[error("Expected directory at {path}")]
|
||||
ExpectedDir {
|
||||
/// The path that wasn't a directory
|
||||
path: PathBuf,
|
||||
},
|
||||
|
||||
/// Path was empty
|
||||
#[error("Path was empty")]
|
||||
EmptyPath,
|
||||
}
|
||||
@ -30,5 +30,4 @@ The [`DirPtr`] type can be used to access any directory, namely the root directo
|
||||
|
||||
The [`Path`] type is used to refer to any entry.
|
||||
|
||||
There also exist some utility functions at the root of the crate, such as [`find_entry`]
|
||||
and [`swap_files`].
|
||||
There also exist some utility functions at the root of the crate, such as [`swap_files`].
|
||||
@ -8,7 +8,8 @@
|
||||
never_type,
|
||||
unwrap_infallible,
|
||||
format_args_capture,
|
||||
str_internals
|
||||
str_internals,
|
||||
destructuring_assignment
|
||||
)]
|
||||
// Lints
|
||||
#![warn(clippy::restriction, clippy::pedantic, clippy::nursery)]
|
||||
@ -69,7 +70,6 @@
|
||||
// Modules
|
||||
pub mod dir;
|
||||
pub mod entry;
|
||||
pub mod find;
|
||||
pub mod path;
|
||||
pub mod ptr;
|
||||
pub mod swap;
|
||||
@ -77,7 +77,6 @@ pub mod writer;
|
||||
|
||||
// Exports
|
||||
pub use entry::{DirEntry, DirEntryKind};
|
||||
pub use find::find_entry;
|
||||
pub use path::{Path, PathBuf};
|
||||
pub use ptr::{DirEntryPtr, DirPtr, FilePtr};
|
||||
pub use swap::swap_files;
|
||||
|
||||
@ -5,12 +5,12 @@ pub mod error;
|
||||
|
||||
// Exports
|
||||
pub use error::{
|
||||
FileCursorError, FindEntryError, ReadEntriesError, ReadEntryError, WriteEntriesError, WriteEntryError,
|
||||
FileCursorError, FindEntryError, FindError, ReadEntriesError, ReadEntryError, WriteEntriesError, WriteEntryError,
|
||||
};
|
||||
|
||||
// Imports
|
||||
use super::DirEntry;
|
||||
use crate::DirEntryKind;
|
||||
use crate::{path, DirEntryKind, Path};
|
||||
use ascii::AsciiStr;
|
||||
use core::str::lossy::Utf8Lossy;
|
||||
use dcb_bytes::Bytes;
|
||||
@ -123,6 +123,63 @@ impl DirPtr {
|
||||
Ok(iter)
|
||||
}
|
||||
|
||||
/// Finds an entry from it's path
|
||||
pub fn find<R: io::Seek + io::Read>(
|
||||
self, reader: &mut R, path: &Path,
|
||||
) -> Result<(DirEntryPtr, DirEntry), FindError> {
|
||||
// Current directory pointer
|
||||
let mut cur_ptr = self;
|
||||
|
||||
// Current entry
|
||||
let mut cur_entry = None;
|
||||
|
||||
let mut components = path.components();
|
||||
loop {
|
||||
match components.next() {
|
||||
// If we get root, reset us to root and clear any entry we have
|
||||
Some(path::Component::Root) => (cur_ptr, cur_entry) = (DirPtr::root(), None),
|
||||
|
||||
// For current directory just get the next component
|
||||
Some(path::Component::CurDir) => continue,
|
||||
|
||||
// Return `Err` on parent directories
|
||||
// Note: We don't support parent directories as we'd have to store all
|
||||
// of the parent directories, because directories don't have
|
||||
// access to their parents
|
||||
Some(path::Component::ParentDir) => return Err(FindError::ParentDir),
|
||||
|
||||
// On a normal entry, find the entry in the current dir
|
||||
Some(path::Component::Normal(entry_name)) => {
|
||||
// Find the entry
|
||||
let (entry_ptr, entry) = cur_ptr.find_entry(reader, entry_name).map_err(FindError::FindEntry)?;
|
||||
|
||||
// If this is the final entry, return it
|
||||
if components.clone().next().is_none() {
|
||||
return Ok((entry_ptr, entry));
|
||||
}
|
||||
|
||||
// Else check what entry we got
|
||||
match entry.kind {
|
||||
DirEntryKind::File { .. } => {
|
||||
return Err(FindError::ExpectedDir {
|
||||
path: path[..(path.len() - components.remaining().len())].to_path_buf(),
|
||||
})
|
||||
},
|
||||
|
||||
// If we got a directory, continue
|
||||
DirEntryKind::Dir { ptr } => {
|
||||
cur_entry = Some((entry_ptr, entry));
|
||||
cur_ptr = ptr;
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
// If we're done, return whatever entry we had before running out
|
||||
None => return cur_entry.ok_or(FindError::EmptyPath),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds an entry
|
||||
pub fn find_entry<R: io::Read + io::Seek>(
|
||||
self, reader: &mut R, entry_name: &AsciiStr,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
//! Errors
|
||||
|
||||
// Imports
|
||||
use crate::PathBuf;
|
||||
use std::io;
|
||||
|
||||
/// Error for [`FilePtr::cursor`](super::FilePtr::cursor)
|
||||
@ -56,6 +57,29 @@ pub enum WriteEntryError {
|
||||
WriteEntry(#[source] io::Error),
|
||||
}
|
||||
|
||||
/// Error type for [`DirPtr::find`](super::DirPtr::find)
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum FindError {
|
||||
/// Unable to find entry
|
||||
#[error("Unable to find entry")]
|
||||
FindEntry(#[source] crate::ptr::FindEntryError),
|
||||
|
||||
/// Cannot go back to parent directory
|
||||
#[error("Cannot go back to parent directory")]
|
||||
ParentDir,
|
||||
|
||||
/// Expected directory
|
||||
#[error("Expected directory at {path}")]
|
||||
ExpectedDir {
|
||||
/// The path that wasn't a directory
|
||||
path: PathBuf,
|
||||
},
|
||||
|
||||
/// Path was empty
|
||||
#[error("Path was empty")]
|
||||
EmptyPath,
|
||||
}
|
||||
|
||||
/// Error for [`DirPtr::find_entry`](super::DirPtr::find_entry)
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum FindEntryError {
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
//! File swapping
|
||||
|
||||
// Imports
|
||||
use crate::{ptr::WriteEntryError, DirEntryKind, Path};
|
||||
use crate::{
|
||||
ptr,
|
||||
DirEntryKind, DirPtr, Path,
|
||||
};
|
||||
use std::{io, mem};
|
||||
|
||||
/// Swaps two files
|
||||
@ -9,8 +12,8 @@ pub fn swap_files<T: io::Seek + io::Read + io::Write>(
|
||||
cursor: &mut T, lhs_path: &Path, rhs_path: &Path,
|
||||
) -> Result<(), SwapFilesError> {
|
||||
// Find both files and their entry pointers
|
||||
let (lhs_entry_ptr, mut lhs_entry) = crate::find_entry(cursor, lhs_path).map_err(SwapFilesError::FindLhs)?;
|
||||
let (rhs_entry_ptr, mut rhs_entry) = crate::find_entry(cursor, rhs_path).map_err(SwapFilesError::FindLhs)?;
|
||||
let (lhs_entry_ptr, mut lhs_entry) = DirPtr::root().find(cursor, lhs_path).map_err(SwapFilesError::FindLhs)?;
|
||||
let (rhs_entry_ptr, mut rhs_entry) = DirPtr::root().find(cursor, rhs_path).map_err(SwapFilesError::FindLhs)?;
|
||||
|
||||
// Swap both entries' file pointers
|
||||
match (&mut lhs_entry.kind, &mut rhs_entry.kind) {
|
||||
@ -36,11 +39,11 @@ pub fn swap_files<T: io::Seek + io::Read + io::Write>(
|
||||
pub enum SwapFilesError {
|
||||
/// Unable to find lhs file
|
||||
#[error("Unable to find lhs file")]
|
||||
FindLhs(#[source] crate::find::FindEntryError),
|
||||
FindLhs(#[source] ptr::FindError),
|
||||
|
||||
/// Unable to find rhs file
|
||||
#[error("Unable to find rhs file")]
|
||||
FindRhs(#[source] crate::find::FindEntryError),
|
||||
FindRhs(#[source] ptr::FindError),
|
||||
|
||||
/// Both paths must be files
|
||||
#[error("Both paths must be files")]
|
||||
@ -48,9 +51,9 @@ pub enum SwapFilesError {
|
||||
|
||||
/// Unable to write lhs file entry
|
||||
#[error("Unable to write lhs file entry")]
|
||||
WriteLhs(#[source] WriteEntryError),
|
||||
WriteLhs(#[source] ptr::WriteEntryError),
|
||||
|
||||
/// Unable to write rhs file entry
|
||||
#[error("Unable to write rhs file entry")]
|
||||
WriteRhs(#[source] WriteEntryError),
|
||||
WriteRhs(#[source] ptr::WriteEntryError),
|
||||
}
|
||||
|
||||
@ -147,7 +147,9 @@ impl<T: io::Seek + io::Read> GameFile<T> {
|
||||
};
|
||||
|
||||
// Then get the entry
|
||||
let (_, entry) = dcb_drv::find_entry(&mut cursor, path).map_err(OpenFileError::FindFile)?;
|
||||
let (_, entry) = dcb_drv::DirPtr::root()
|
||||
.find(&mut cursor, path)
|
||||
.map_err(OpenFileError::FindFile)?;
|
||||
|
||||
match entry.kind {
|
||||
DirEntryKind::File { ptr, .. } => ptr.cursor(cursor).map_err(OpenFileError::OpenFile),
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//! Errors
|
||||
|
||||
// Imports
|
||||
use dcb_drv::{find::FindEntryError, ptr::FileCursorError};
|
||||
use dcb_drv::ptr;
|
||||
use std::io;
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@ pub enum OpenFileError {
|
||||
|
||||
/// Unable to find file
|
||||
#[error("Unable to find file")]
|
||||
FindFile(#[source] FindEntryError),
|
||||
FindFile(#[source] ptr::FindError),
|
||||
|
||||
/// Found directory
|
||||
#[error("Found directory")]
|
||||
@ -33,7 +33,7 @@ pub enum OpenFileError {
|
||||
|
||||
/// Unable to open file
|
||||
#[error("Unable to open file")]
|
||||
OpenFile(#[source] FileCursorError),
|
||||
OpenFile(#[source] ptr::FileCursorError),
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user