summaryrefslogtreecommitdiff
path: root/src/util/mod.rs
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-06-26 13:57:21 +0200
committerLaurenz <laurmaedje@gmail.com>2023-06-27 18:40:17 +0200
commit7b92bd7c340d9f9c094ed2fa57912049317d9b20 (patch)
treeb91399526ba94d87309d09d864df2935dd7a4d0a /src/util/mod.rs
parent9c7f31870b4e1bf37df79ebbe1df9a56df83d878 (diff)
Basic package management
Diffstat (limited to 'src/util/mod.rs')
-rw-r--r--src/util/mod.rs42
1 files changed, 38 insertions, 4 deletions
diff --git a/src/util/mod.rs b/src/util/mod.rs
index 71c5aefc..78c7bedf 100644
--- a/src/util/mod.rs
+++ b/src/util/mod.rs
@@ -2,9 +2,9 @@
pub mod fat;
-mod buffer;
+mod bytes;
-pub use buffer::Buffer;
+pub use bytes::Bytes;
use std::fmt::{self, Debug, Formatter};
use std::hash::Hash;
@@ -125,26 +125,60 @@ where
pub trait PathExt {
/// Lexically normalize a path.
fn normalize(&self) -> PathBuf;
+
+ /// Treat `self` as a virtual root relative to which the `path` is resolved.
+ ///
+ /// Returns `None` if the path lexically escapes the root. The path
+ /// might still escape through symlinks.
+ fn join_rooted(&self, path: &Path) -> Option<PathBuf>;
}
impl PathExt for Path {
- #[tracing::instrument(skip_all)]
fn normalize(&self) -> PathBuf {
let mut out = PathBuf::new();
for component in self.components() {
match component {
Component::CurDir => {}
Component::ParentDir => match out.components().next_back() {
+ Some(Component::RootDir) => {}
Some(Component::Normal(_)) => {
out.pop();
}
_ => out.push(component),
},
- _ => out.push(component),
+ Component::Prefix(_) | Component::RootDir | Component::Normal(_) => {
+ out.push(component)
+ }
}
}
+ if out.as_os_str().is_empty() {
+ out.push(Component::CurDir);
+ }
out
}
+
+ fn join_rooted(&self, path: &Path) -> Option<PathBuf> {
+ let mut parts: Vec<_> = self.components().collect();
+ let root = parts.len();
+ for component in path.components() {
+ match component {
+ Component::Prefix(_) => return None,
+ Component::RootDir => parts.truncate(root),
+ Component::CurDir => {}
+ Component::ParentDir => {
+ if parts.len() <= root {
+ return None;
+ }
+ parts.pop();
+ }
+ Component::Normal(_) => parts.push(component),
+ }
+ }
+ if parts.len() < root {
+ return None;
+ }
+ Some(parts.into_iter().collect())
+ }
}
/// Format pieces separated with commas and a final "and" or "or".