Most of the refactor. Need to switch machines.
This commit is contained in:
14
crates/path/Cargo.toml
Normal file
14
crates/path/Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
||||
[package]
|
||||
name = "path"
|
||||
version = "0.1.0"
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
description = "Raven's pathing tools"
|
||||
repository.workspace = true
|
||||
|
||||
publish.workspace = true
|
||||
test.workspace = true
|
||||
|
||||
[dependencies]
|
||||
const_format.workspace = true
|
||||
151
crates/path/src/lib.rs
Normal file
151
crates/path/src/lib.rs
Normal file
@@ -0,0 +1,151 @@
|
||||
use std::collections::HashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
//TODO: Clean this up. Shouldn't need duplicated DIR_SRC consts about the workspace.
|
||||
|
||||
const DIR_SRC: &str = "src/";
|
||||
const DIR_TARGET: &str = "target/";
|
||||
|
||||
const DIR_MAIN: &str = const_format::concatcp!(DIR_SRC, "main/");
|
||||
const DIR_TEST: &str = const_format::concatcp!(DIR_SRC, "test/");
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PathHandler {
|
||||
root_path: PathBuf,
|
||||
// This is a short-living binary. This doesn't need an LRU like Moka.
|
||||
derived_path_cache: HashMap<String, PathBuf>,
|
||||
}
|
||||
|
||||
impl PathHandler {
|
||||
pub fn new(root_path: PathBuf) -> Self {
|
||||
Self::from(root_path)
|
||||
}
|
||||
|
||||
pub fn root_path(&self) -> PathBuf {
|
||||
self.root_path.clone()
|
||||
}
|
||||
|
||||
/// This is a readability helper.
|
||||
/// Make sure to set the root of this `PathHandler` to the project root.
|
||||
/// This simply calls upon the root_path() of the `PathHandler`.
|
||||
pub fn project_root(&self) -> PathBuf {
|
||||
self.root_path()
|
||||
}
|
||||
|
||||
pub fn dir_src(&mut self) -> PathBuf {
|
||||
self.get_path(DIR_SRC)
|
||||
}
|
||||
|
||||
pub fn dir_target(&mut self) -> PathBuf {
|
||||
self.get_path(DIR_TARGET)
|
||||
}
|
||||
|
||||
pub fn dir_main(&mut self) -> PathBuf {
|
||||
self.get_path(DIR_MAIN)
|
||||
}
|
||||
|
||||
pub fn dir_test(&mut self) -> PathBuf {
|
||||
self.get_path(DIR_TEST)
|
||||
}
|
||||
|
||||
/// Attempts to load from cache, else generates the path and clones it to the cache.
|
||||
/// Returns the requested path.
|
||||
fn get_path<S>(&mut self, k: S) -> PathBuf
|
||||
where
|
||||
S: ToString + AsRef<str>,
|
||||
{
|
||||
self.from_cache(k.as_ref())
|
||||
.unwrap_or_else(|| {
|
||||
self.gen_key(k.to_string(), self.root_path().join(k.to_string()));
|
||||
self.get_path(k.as_ref())
|
||||
})
|
||||
.to_path_buf()
|
||||
}
|
||||
|
||||
/// Attempts to pull the value for the given key from the cache.
|
||||
fn from_cache<S: AsRef<str>>(&self, path_key: S) -> Option<PathBuf> {
|
||||
self.derived_path_cache
|
||||
.get(path_key.as_ref())
|
||||
.and_then(|v| Some(v.to_owned()))
|
||||
}
|
||||
|
||||
/// Tries to generate a new key-value pair in the cache
|
||||
fn gen_key<P, S>(&mut self, k: S, v: P) -> Option<PathBuf>
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
S: ToString,
|
||||
{
|
||||
self.derived_path_cache
|
||||
.insert(k.to_string(), v.as_ref().to_path_buf())
|
||||
}
|
||||
}
|
||||
|
||||
impl<P> From<P> for PathHandler
|
||||
where
|
||||
P: AsRef<Path>,
|
||||
{
|
||||
fn from(value: P) -> Self {
|
||||
Self {
|
||||
root_path: value.as_ref().to_path_buf(),
|
||||
derived_path_cache: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub trait PathHandled {
|
||||
fn set_path_handler(&mut self, ph: Arc<Mutex<PathHandler>>) {}
|
||||
|
||||
fn with_path_handler(&mut self, ph: Arc<Mutex<PathHandler>>) -> &mut Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
const ROOT: &str = "/root";
|
||||
|
||||
#[test]
|
||||
fn ph_get_path() {
|
||||
let root = PathBuf::from(ROOT);
|
||||
let expected = root.join(DIR_SRC);
|
||||
|
||||
let mut ph = PathHandler::from(root);
|
||||
|
||||
assert!(ph.dir_src() == expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ph_cache_gen() {
|
||||
let root = PathBuf::from(ROOT);
|
||||
let expected = root.join(DIR_SRC);
|
||||
|
||||
let ph = PathHandler::from(root);
|
||||
|
||||
assert!(
|
||||
ph.derived_path_cache
|
||||
.get(DIR_SRC)
|
||||
.is_some_and(|v| *v == expected)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ph_cache_pull() {
|
||||
let faux_path = "faux/path";
|
||||
|
||||
let mut ph = PathHandler::from("false/root");
|
||||
ph.derived_path_cache
|
||||
.insert(faux_path.to_string(), PathBuf::from(faux_path));
|
||||
|
||||
// Use the method that attempts a fallback.
|
||||
// By using a false root, this will create a different path to the injected one,
|
||||
// making it possible to determine if the cache load fails.
|
||||
//
|
||||
// I.e.
|
||||
// Expected: faux/path as PathBuf
|
||||
// Failed: false/root/faux/path as PathBuf
|
||||
assert!(ph.get_path(faux_path) == PathBuf::from(faux_path));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user