Skip to content

Commit

Permalink
SingleComponentPath<'p> -> &SingleComponentPath
Browse files Browse the repository at this point in the history
  • Loading branch information
TheAlgorythm committed Dec 8, 2023
1 parent 5f9491e commit 5f272e1
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 30 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ documentation = "https://docs.rs/crate/path_ratchet"


[lints.rust]
unsafe_code = "forbid"
unsafe_code = "deny"
missing_abi = "warn"
missing_docs = "warn"
noop_method_call = "warn"
Expand Down
74 changes: 46 additions & 28 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@
#[cfg(test)]
mod tests;

use std::path::{Path, PathBuf};
use std::{
borrow::Borrow,
path::{Path, PathBuf},
};

/// A safe wrapper for a `PathBuf` with only a single component.
/// This prevents path traversal attacks.
Expand Down Expand Up @@ -67,17 +70,21 @@ impl SingleComponentPathBuf {
path: component.into(),
};

SingleComponentPath::from(&component)
.is_valid()
.then_some(component)
component.is_valid().then_some(component)
}
}

impl std::ops::Deref for SingleComponentPathBuf {
type Target = Path;
type Target = SingleComponentPath;

fn deref(&self) -> &Self::Target {
&self.path
self.borrow()
}
}

impl AsRef<SingleComponentPath> for SingleComponentPathBuf {
fn as_ref(&self) -> &SingleComponentPath {
self.borrow()
}
}

Expand All @@ -96,11 +103,12 @@ impl AsRef<Path> for SingleComponentPathBuf {
/// It allows just a single normal path element and no parent, root directory or prefix like `C:`.
/// Allows reference to the current directory of the path (`.`).
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct SingleComponentPath<'p> {
pub(crate) path: &'p Path,
#[repr(transparent)]
pub struct SingleComponentPath {
pub(crate) path: Path,
}

impl<'p> SingleComponentPath<'p> {
impl SingleComponentPath {
/// It creates the wrapped `SingleComponentPath` if it's valid.
/// Otherwise it will return `None`.
///
Expand All @@ -118,10 +126,10 @@ impl<'p> SingleComponentPath<'p> {
/// assert!(SingleComponentPath::new("/etc/shadow").is_none());
/// # }
/// ```
pub fn new<P: AsRef<Path> + ?Sized>(component: &'p P) -> Option<Self> {
let component = Self {
path: component.as_ref(),
};
#[allow(unsafe_code)]
pub fn new<P: AsRef<Path> + ?Sized>(component: &P) -> Option<&Self> {
// same reprensentation
let component: &Self = unsafe { std::mem::transmute(component.as_ref()) };

component.is_valid().then_some(component)
}
Expand All @@ -141,31 +149,41 @@ impl<'p> SingleComponentPath<'p> {
}
}

impl<'p> From<&'p SingleComponentPathBuf> for SingleComponentPath<'p> {
fn from(s: &'p SingleComponentPathBuf) -> Self {
Self { path: &s.path }
impl Borrow<SingleComponentPath> for SingleComponentPathBuf {
#[allow(unsafe_code)]
fn borrow(&self) -> &SingleComponentPath {
// same reprensentation
unsafe { std::mem::transmute(self.path.as_path()) }
}
}

impl<'p> From<SingleComponentPath<'p>> for SingleComponentPathBuf {
fn from(s: SingleComponentPath<'p>) -> Self {
Self {
path: s.path.to_path_buf(),
impl ToOwned for SingleComponentPath {
type Owned = SingleComponentPathBuf;

fn to_owned(&self) -> Self::Owned {
Self::Owned {
path: self.path.to_path_buf(),
}
}
}

impl std::ops::Deref for SingleComponentPath<'_> {
impl std::ops::Deref for SingleComponentPath {
type Target = Path;

fn deref(&self) -> &Self::Target {
self.path
&self.path
}
}

impl AsRef<Path> for SingleComponentPath<'_> {
impl AsRef<SingleComponentPath> for SingleComponentPath {
fn as_ref(&self) -> &SingleComponentPath {
self
}
}

impl AsRef<Path> for SingleComponentPath {
fn as_ref(&self) -> &Path {
self.path
&self.path
}
}

Expand Down Expand Up @@ -313,12 +331,12 @@ pub trait PushPathComponent {
/// # {
/// let mut path = PathBuf::new();
/// path.push_component(SingleComponentPath::new("foo").unwrap());
/// path.push_component(&SingleComponentPathBuf::new("bar.txt").unwrap());
/// path.push_component(SingleComponentPathBuf::new("bar.txt").unwrap());
///
/// assert_eq!(path, PathBuf::from("foo/bar.txt"));
/// # }
/// ```
fn push_component<'p>(&mut self, component: impl Into<SingleComponentPath<'p>>);
fn push_component(&mut self, component: impl AsRef<SingleComponentPath>);
/// ```
/// use std::path::PathBuf;
/// use path_ratchet::prelude::*;
Expand All @@ -335,8 +353,8 @@ pub trait PushPathComponent {
}

impl PushPathComponent for PathBuf {
fn push_component<'p>(&mut self, component: impl Into<SingleComponentPath<'p>>) {
self.push(component.into());
fn push_component(&mut self, component: impl AsRef<SingleComponentPath>) {
self.push(component.as_ref());
}

fn push_components<'p>(&mut self, component: impl Into<MultiComponentPath<'p>>) {
Expand Down

0 comments on commit 5f272e1

Please sign in to comment.