1#![deny(warnings, clippy::all)]
2
3use std::{
4 io::ErrorKind,
5 path::{Path, PathBuf},
6};
7
8pub mod mem_fs;
9pub mod rel_fs;
10mod utils;
11
12pub use crate::{mem_fs::MemFs, rel_fs::RelFs};
13
14#[derive(thiserror::Error, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
15pub enum Error {
16 #[error("Failed to locate {path:?}")]
17 NotFound { path: PathBuf },
18
19 #[error("Failed to access {path:?}")]
20 AccessDenied { path: PathBuf },
21
22 #[error("The path {path:?} is outside acceptable bounds")]
23 PathOutsideBounds { path: PathBuf },
24
25 #[error("The path {path:?} is not a directory")]
26 NotADirectory { path: PathBuf },
27
28 #[error("{0}")]
32 Other(String),
33}
34
35impl Error {
36 pub fn to_io_error(&self) -> std::io::Error {
37 match self {
38 Self::NotFound { .. } => ErrorKind::NotFound.into(),
39 Self::AccessDenied { .. } => ErrorKind::PermissionDenied.into(),
40 Self::PathOutsideBounds { .. } => ErrorKind::InvalidInput.into(),
41 Self::NotADirectory { .. } => {
42 std::io::Error::new(ErrorKind::Other, "Not a directory")
44 }
45 Self::Other(message) => std::io::Error::new(ErrorKind::Other, message.as_str()),
46 }
47 }
48
49 pub fn from_io(path: PathBuf, e: std::io::Error) -> Self {
50 match e.kind() {
51 ErrorKind::NotFound => Self::NotFound { path },
52 ErrorKind::PermissionDenied => Self::AccessDenied { path },
53 _ => {
54 let msg = e.to_string();
55 match msg.as_str().split_once(" (os error") {
57 Some(("Not a directory", _)) => Self::NotADirectory { path },
58 _ => Self::Other(msg),
59 }
60 }
61 }
62 }
63}
64
65pub trait LogixVfsDirEntry {
66 fn path(&self) -> &Path;
67 fn is_dir(&self) -> bool;
68 fn is_file(&self) -> bool;
69 fn is_symlink(&self) -> bool;
70}
71
72pub trait LogixVfs: std::fmt::Debug + Send + Sync {
73 type RoFile: std::io::Read;
74 type DirEntry: LogixVfsDirEntry;
75 type ReadDir: Iterator<Item = Result<Self::DirEntry, Error>>;
76
77 fn canonicalize_path(&self, path: &Path) -> Result<PathBuf, Error>;
78 fn open_file(&self, path: &Path) -> Result<Self::RoFile, Error>;
79 fn read_dir(&self, path: &Path) -> Result<Self::ReadDir, Error>;
80}