summaryrefslogtreecommitdiff
path: root/src/util
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
parent9c7f31870b4e1bf37df79ebbe1df9a56df83d878 (diff)
Basic package management
Diffstat (limited to 'src/util')
-rw-r--r--src/util/bytes.rs (renamed from src/util/buffer.rs)18
-rw-r--r--src/util/mod.rs42
2 files changed, 47 insertions, 13 deletions
diff --git a/src/util/buffer.rs b/src/util/bytes.rs
index 23fb9802..9165467b 100644
--- a/src/util/buffer.rs
+++ b/src/util/bytes.rs
@@ -5,11 +5,11 @@ use std::sync::Arc;
use comemo::Prehashed;
-/// A shared buffer that is cheap to clone and hash.
+/// A shared byte buffer that is cheap to clone and hash.
#[derive(Clone, Hash, Eq, PartialEq)]
-pub struct Buffer(Arc<Prehashed<Cow<'static, [u8]>>>);
+pub struct Bytes(Arc<Prehashed<Cow<'static, [u8]>>>);
-impl Buffer {
+impl Bytes {
/// Create a buffer from a static byte slice.
pub fn from_static(slice: &'static [u8]) -> Self {
Self(Arc::new(Prehashed::new(Cow::Borrowed(slice))))
@@ -26,19 +26,19 @@ impl Buffer {
}
}
-impl From<&[u8]> for Buffer {
+impl From<&[u8]> for Bytes {
fn from(slice: &[u8]) -> Self {
Self(Arc::new(Prehashed::new(slice.to_vec().into())))
}
}
-impl From<Vec<u8>> for Buffer {
+impl From<Vec<u8>> for Bytes {
fn from(vec: Vec<u8>) -> Self {
Self(Arc::new(Prehashed::new(vec.into())))
}
}
-impl Deref for Buffer {
+impl Deref for Bytes {
type Target = [u8];
fn deref(&self) -> &Self::Target {
@@ -46,14 +46,14 @@ impl Deref for Buffer {
}
}
-impl AsRef<[u8]> for Buffer {
+impl AsRef<[u8]> for Bytes {
fn as_ref(&self) -> &[u8] {
self
}
}
-impl Debug for Buffer {
+impl Debug for Bytes {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
- f.pad("Buffer(..)")
+ write!(f, "bytes({})", self.len())
}
}
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".