summaryrefslogtreecommitdiff
path: root/src/lib.rs
diff options
context:
space:
mode:
authorA Farzat <a@farzat.xyz>2026-06-03 20:44:45 +0300
committerA Farzat <a@farzat.xyz>2026-06-03 20:45:39 +0300
commit4895316ec584034ccfcca4103393422c2729415e (patch)
treeb23be5c7b0be8f1e7703d380c1128eab77d2e0c6 /src/lib.rs
parentb7f35189247c58b3926984f01544f11e25f9cc1b (diff)
downloadrepo2markdown-4895316ec584034ccfcca4103393422c2729415e.tar.gz
repo2markdown-4895316ec584034ccfcca4103393422c2729415e.zip
Rename to intuitive names
Diffstat (limited to 'src/lib.rs')
-rw-r--r--src/lib.rs115
1 files changed, 56 insertions, 59 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 5f29873..1415e83 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -6,56 +6,56 @@ use std::{
#[derive(Debug)]
pub enum NormalizeError {
EmptyInput,
- InputOutsideFileSystemRoot,
- PathHasMultipleInternalPrefix,
+ EscapesFilesystemRoot,
+ InvalidMultiplePrefix,
}
pub struct Normalizer {
root: PathBuf,
- origin: PathBuf,
+ origin_base: PathBuf,
}
impl Normalizer {
- pub fn new(root: &Path, origin: &Path) -> std::io::Result<Self> {
+ pub fn new(root: &Path, origin_base: &Path) -> std::io::Result<Self> {
let cwd = env::current_dir()?;
- Ok(Self::new_with_cwd(root, origin, &cwd))
+ Ok(Self::new_with_cwd(root, origin_base, &cwd))
}
- fn new_with_cwd(root: &Path, origin: &Path, cwd: &Path) -> Self {
+ fn new_with_cwd(root: &Path, origin_base: &Path, cwd: &Path) -> Self {
Self {
root: absolutize(root, cwd),
- origin: absolutize(origin, cwd),
+ origin_base: absolutize(origin_base, cwd),
}
}
- pub fn normalize_path(&self, input: &Path) -> Result<PathBuf, NormalizeError> {
+ pub fn normalize(&self, input: &Path) -> Result<PathBuf, NormalizeError> {
if input.as_os_str().is_empty() {
return Err(NormalizeError::EmptyInput);
}
- let input = absolutize(input, &self.origin);
- let normalized_input = normalize_lexically(&input)?;
- Ok(normalize_to_root(normalized_input, &self.root))
+ let input = absolutize(input, &self.origin_base);
+ let normalized_input = normalize_components(&input)?;
+ Ok(make_relative_to_root(normalized_input, &self.root))
}
}
-fn absolutize(path: &Path, absolute_prefix: &Path) -> PathBuf {
+fn absolutize(path: &Path, base: &Path) -> PathBuf {
if path.is_absolute() {
path.to_path_buf()
} else {
- absolute_prefix.join(path)
+ base.join(path)
}
}
/// # Invariant
/// `path` must be an absolute path.
/// Violations indicate a bug in the caller.
-fn normalize_lexically(path: &Path) -> Result<PathBuf, NormalizeError> {
+fn normalize_components(path: &Path) -> Result<PathBuf, NormalizeError> {
debug_assert!(
path.is_absolute(),
"Input must be an absolute path: {:?}",
path
);
- let mut lexical = PathBuf::new();
+ let mut normalized = PathBuf::new();
let mut iter = path.components().peekable();
// Find the root, if any, and add it to the lexical path.
@@ -63,21 +63,21 @@ fn normalize_lexically(path: &Path) -> Result<PathBuf, NormalizeError> {
// `components` splits it into two: (Prefix, RootDir).
let root = match iter.peek() {
Some(p @ Component::RootDir) => {
- lexical.push(p);
+ normalized.push(p);
iter.next();
- lexical.as_os_str().len()
+ normalized.as_os_str().len()
}
Some(Component::Prefix(prefix)) => {
- lexical.push(prefix.as_os_str());
+ normalized.push(prefix.as_os_str());
iter.next();
if let Some(p @ Component::RootDir) = iter.peek() {
- lexical.push(p);
+ normalized.push(p);
iter.next();
}
- lexical.as_os_str().len()
+ normalized.as_os_str().len()
}
_ => unreachable!(
- "normalize_lexically received a non-absolute path: {:?}",
+ "normalize_components received a non-absolute path: {:?}",
path
),
};
@@ -85,26 +85,26 @@ fn normalize_lexically(path: &Path) -> Result<PathBuf, NormalizeError> {
for component in iter {
match component {
Component::RootDir => unreachable!(),
- Component::Prefix(_) => return Err(NormalizeError::PathHasMultipleInternalPrefix),
+ Component::Prefix(_) => return Err(NormalizeError::InvalidMultiplePrefix),
Component::CurDir => continue,
Component::ParentDir => {
// It's an error if ParentDir causes us to go above the "root".
- if lexical.as_os_str().len() == root {
- return Err(NormalizeError::InputOutsideFileSystemRoot);
+ if normalized.as_os_str().len() == root {
+ return Err(NormalizeError::EscapesFilesystemRoot);
} else {
- lexical.pop();
+ normalized.pop();
}
}
- Component::Normal(path) => lexical.push(path),
+ Component::Normal(path) => normalized.push(path),
}
}
- Ok(lexical)
+ Ok(normalized)
}
/// # Invariant
/// `target` and `root` must be an absolute paths.
/// Violations indicate a bug in the caller.
-fn normalize_to_root(target: PathBuf, mut root: &Path) -> PathBuf {
+fn make_relative_to_root(target: PathBuf, mut root: &Path) -> PathBuf {
debug_assert!(
target.is_absolute(),
"Target must be an absolute path: {:?}",
@@ -115,13 +115,13 @@ fn normalize_to_root(target: PathBuf, mut root: &Path) -> PathBuf {
"Root must be an absolute path: {:?}",
root
);
- let mut prefix = PathBuf::new();
+ let mut upward = PathBuf::new();
loop {
if let Ok(suffix) = target.strip_prefix(root) {
- return prefix.join(suffix);
+ return upward.join(suffix);
}
if let Some(new_root) = root.parent() {
- prefix.push("..");
+ upward.push("..");
root = new_root;
} else {
return target;
@@ -139,7 +139,7 @@ mod tests {
fn empty_path_returns_error() {
let fake_cwd = Path::new("/sandbox");
let normalizer = Normalizer::new_with_cwd(Path::new(""), Path::new(""), fake_cwd);
- let result = normalizer.normalize_path(Path::new(""));
+ let result = normalizer.normalize(Path::new(""));
assert!(matches!(result, Err(NormalizeError::EmptyInput)));
}
@@ -147,7 +147,7 @@ mod tests {
fn plain_filename_with_root_at_cwd_returns_filename() {
let fake_cwd = Path::new("/sandbox");
let normalizer = Normalizer::new_with_cwd(Path::new(""), Path::new(""), fake_cwd);
- let result = normalizer.normalize_path(Path::new("main.rs"));
+ let result = normalizer.normalize(Path::new("main.rs"));
assert!(result.is_ok());
assert_eq!(result.unwrap(), Path::new("main.rs"));
}
@@ -156,9 +156,9 @@ mod tests {
fn relative_path_from_origin_is_resolved() {
let fake_cwd = Path::new("/sandbox");
let root = Path::new("");
- let origin_dir = Path::new("src");
- let normalizer = Normalizer::new_with_cwd(root, origin_dir, fake_cwd);
- let result = normalizer.normalize_path(Path::new("../main.rs"));
+ let origin_base = Path::new("src");
+ let normalizer = Normalizer::new_with_cwd(root, origin_base, fake_cwd);
+ let result = normalizer.normalize(Path::new("../main.rs"));
assert!(result.is_ok());
assert_eq!(result.unwrap(), Path::new("main.rs"));
}
@@ -167,9 +167,9 @@ mod tests {
fn path_is_made_relative_to_root() {
let fake_cwd = Path::new("/sandbox");
let root = Path::new("/project");
- let origin_dir = Path::new("/project/src");
- let normalizer = Normalizer::new_with_cwd(root, origin_dir, fake_cwd);
- let result = normalizer.normalize_path(Path::new("main.rs"));
+ let origin_base = Path::new("/project/src");
+ let normalizer = Normalizer::new_with_cwd(root, origin_base, fake_cwd);
+ let result = normalizer.normalize(Path::new("main.rs"));
assert!(result.is_ok());
assert_eq!(result.unwrap(), Path::new("src/main.rs"));
}
@@ -178,9 +178,9 @@ mod tests {
fn path_is_made_relative_to_root_from_outside() {
let fake_cwd = Path::new("/sandbox");
let root = Path::new("/project");
- let origin_dir = Path::new("/outside");
- let normalizer = Normalizer::new_with_cwd(root, origin_dir, fake_cwd);
- let result = normalizer.normalize_path(Path::new("main.rs"));
+ let origin_base = Path::new("/outside");
+ let normalizer = Normalizer::new_with_cwd(root, origin_base, fake_cwd);
+ let result = normalizer.normalize(Path::new("main.rs"));
assert!(result.is_ok());
assert_eq!(result.unwrap(), Path::new("../outside/main.rs"));
}
@@ -189,9 +189,9 @@ mod tests {
fn path_is_made_relative_to_root_even_if_root_dir_is_relative() {
let fake_cwd = Path::new("/sandbox");
let root = Path::new("project");
- let origin_dir = Path::new("/sandbox/outside");
- let normalizer = Normalizer::new_with_cwd(root, origin_dir, fake_cwd);
- let result = normalizer.normalize_path(Path::new("main.rs"));
+ let origin_base = Path::new("/sandbox/outside");
+ let normalizer = Normalizer::new_with_cwd(root, origin_base, fake_cwd);
+ let result = normalizer.normalize(Path::new("main.rs"));
assert!(result.is_ok());
assert_eq!(result.unwrap(), Path::new("../outside/main.rs"));
}
@@ -200,20 +200,20 @@ mod tests {
fn absolute_inputs_work() {
let fake_cwd = Path::new("/sandbox");
let root = Path::new("project");
- let origin_dir = Path::new("/sandbox/outside");
- let normalizer = Normalizer::new_with_cwd(root, origin_dir, fake_cwd);
- let result = normalizer.normalize_path(Path::new("/sandbox/main.rs"));
+ let origin_base = Path::new("/sandbox/outside");
+ let normalizer = Normalizer::new_with_cwd(root, origin_base, fake_cwd);
+ let result = normalizer.normalize(Path::new("/sandbox/main.rs"));
assert!(result.is_ok());
assert_eq!(result.unwrap(), Path::new("../main.rs"));
}
#[test]
- fn path_is_made_relative_to_root_even_if_origin_dir_is_relative() {
+ fn path_is_made_relative_to_root_even_if_origin_base_is_relative() {
let fake_cwd = Path::new("/sandbox");
let root = Path::new("/sandbox/project");
- let origin_dir = Path::new("outside");
- let normalizer = Normalizer::new_with_cwd(root, origin_dir, fake_cwd);
- let result = normalizer.normalize_path(Path::new("main.rs"));
+ let origin_base = Path::new("outside");
+ let normalizer = Normalizer::new_with_cwd(root, origin_base, fake_cwd);
+ let result = normalizer.normalize(Path::new("main.rs"));
assert!(result.is_ok());
assert_eq!(result.unwrap(), Path::new("../outside/main.rs"));
}
@@ -222,12 +222,9 @@ mod tests {
fn input_cannot_go_above_root() {
let fake_cwd = Path::new("/sandbox");
let root = Path::new("project");
- let origin_dir = Path::new("outside");
- let normalizer = Normalizer::new_with_cwd(root, origin_dir, fake_cwd);
- let result = normalizer.normalize_path(Path::new("../../../main.rs"));
- assert!(matches!(
- result,
- Err(NormalizeError::InputOutsideFileSystemRoot)
- ));
+ let origin_base = Path::new("outside");
+ let normalizer = Normalizer::new_with_cwd(root, origin_base, fake_cwd);
+ let result = normalizer.normalize(Path::new("../../../main.rs"));
+ assert!(matches!(result, Err(NormalizeError::EscapesFilesystemRoot)));
}
}