From 1348b0b9dff8e9e395f6279f6316835ad85763f6 Mon Sep 17 00:00:00 2001 From: Avril Date: Fri, 22 Jul 2022 18:51:17 +0100 Subject: [PATCH] Added more convenience methods and trait impls to `PluginTrust<"a>`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fortune for rng's current commit: Small blessing − 小吉 --- src/plugin/searcher.rs | 95 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 88 insertions(+), 7 deletions(-) diff --git a/src/plugin/searcher.rs b/src/plugin/searcher.rs index f18bb93..5ab1507 100644 --- a/src/plugin/searcher.rs +++ b/src/plugin/searcher.rs @@ -5,7 +5,7 @@ use std::path::{ Path, }; use std::{ - fs, io, + fs, io, ops, borrow::{ Cow, Borrow, }, @@ -561,6 +561,32 @@ impl> LookupVisitor

} } +impl<'a, T: ToOwned + 'a> From<(T, bool)> for PluginTrust<'a> +{ + fn from((from, trust): (T, bool)) -> Self + { + (if trust { + Self::Trusted + } else { + Self::Untrusted + })(Cow::Owned(from.to_owned())) + .enforce_validity::() + } +} + + +impl<'a> From> for PluginTrust<'a> +{ + #[inline] + fn from(from: locations::PathTrust<'a>) -> Self + { + match from { + locations::PathTrust::Trusted(a) => PluginTrust::Trusted(Cow::from(Path::new(a))), + locations::PathTrust::Untrusted(a) => PluginTrust::Untrusted(Cow::from(Path::new(a))), + }.enforce_validity::() + } +} + /// Denoted a plugin and if it was loaded from a trusted path or not #[derive(Debug, Clone, Eq, Hash, PartialOrd, Ord)] pub enum PluginTrust<'a> @@ -569,6 +595,15 @@ pub enum PluginTrust<'a> Untrusted(Cow<'a, Path>) } +impl<'a> ops::Deref for PluginTrust<'a> +{ + type Target = Path; + #[inline] + fn deref(&self) -> &Self::Target { + self.as_path() + } +} + impl<'a> Borrow for PluginTrust<'a> { #[inline(always)] @@ -600,6 +635,15 @@ impl<'a> From> for Cow<'a, Path> } } +impl<'a> From> for PathBuf +{ + #[inline] + fn from(from: PluginTrust<'a>) -> Self { + let cow: Cow = from.into(); + cow.into_owned() + } +} + impl<'a, T: AsRef + ?Sized> PartialEq for PluginTrust<'a> { #[inline] @@ -628,15 +672,52 @@ impl<'a> PluginTrust<'a> { !self.is_trusted() } -} -impl From> for PathBuf -{ + /// Get the `Path`, trusted or otherwise. + #[inline(always)] + fn as_path(&self) -> &Path + { + self.borrow() + } + + /// Map this path to another. + /// + /// # Panics + /// If the output of `func` is not a file-like object or does not exist. #[inline] - fn from(from: PluginTrust<'static>) -> Self + pub fn map>>(self, func: F) -> Self + where F: FnOnce(Cow<'a, Path>) -> T { - match from { - PluginTrust::Trusted(a) | PluginTrust::Untrusted(a) => a.into_owned() + match self { + Self::Trusted(yes) => Self::Trusted(func(yes).into()), + Self::Untrusted(no) => Self::Untrusted(func(no).into()) + }.enforce_validity::() + } + + #[inline(always)] + pub(super) fn is_valid(&self) -> bool + { + let path = self.as_path(); + path.exists() && !path.is_dir() //XXX: Is this okay for validation for now? What about symlinked files? + } + + #[inline(always)] + fn enforce_validity(self) -> Self + { + if !DEBUG || cfg!(debug_assertions) { + #[inline(never)] + #[cold] + fn _panic_invalid(path: impl Into) -> ! + { + panic!("Illegal plugin path name: {:?}", path.into()) + } + if !self.is_valid() { + _panic_invalid(self) + } else { + self + } + } else { + self } } }