diff options
Diffstat (limited to 'src/version.rs')
| -rw-r--r-- | src/version.rs | 46 |
1 files changed, 38 insertions, 8 deletions
diff --git a/src/version.rs b/src/version.rs index ae91149..af61481 100644 --- a/src/version.rs +++ b/src/version.rs @@ -10,7 +10,7 @@ use sha1_smol::Digest; pub mod manifest; use manifest::*; -#[derive(Deserialize, Debug, Clone, Copy)] +#[derive(Deserialize, Debug, Clone, Copy, PartialEq, Eq)] #[serde(rename_all = "lowercase")] pub enum RuleAction { Allow, @@ -81,21 +81,51 @@ pub struct CompatibilityRule { pub os: Option<OSRestriction> } -pub trait FeatureMatcher { - fn matches(&self, feature: &str) -> bool; -} -impl<F> FeatureMatcher for F +/// ## Details +/// ### Why is the lifetime `'f` specified instead of elided? +/// This trait has a blanket implementation for all `Fn(&str) -> bool`, with the intent of allowing +/// one to specify trivial feature matcher implementations using closures (maybe `|_| false` or +/// `|f| f == "something"`). If the lifetime is left unbounded, the following error is produced by +/// the compiler: +/// +/// ```text +/// Implementation of `Fn` is not general enough +/// Note: closure with signature `fn(&'2 str) -> bool` must implement `Fn<(&'1 str,)>`, for any lifetime `'1`... +/// Note: ...but it actually implements `Fn<(&'2 str,)>`, for some specific lifetime `'2` +/// ``` +/// +/// ### How do I implement this type for non-`Copy` custom feature matchers? +/// The short answer is: implement the trait for the reference type. Here's an example. +/// ```rust +/// use o3launcher::version::FeatureMatcher; +/// +/// #[derive(Clone)] // can't derive Copy here +/// struct FM { +/// our_feature: String // heap-owned data! +/// } +/// +/// impl<'f> FeatureMatcher<'f> for &FM { +/// fn matches(self, feature: &'f str) -> bool { +/// self.our_feature == feature +/// } +/// } +/// ``` +pub trait FeatureMatcher<'f>: Copy { + fn matches(self, feature: &'f str) -> bool; +} + +impl<'f, F> FeatureMatcher<'f> for F where - F: Fn(&str) -> bool + F: Fn(&'f str) -> bool + Copy { - fn matches(&self, feature: &str) -> bool { + fn matches(self, feature: &'f str) -> bool { self(feature) } } impl CompatibilityRule { - pub fn features_match(&self, checker: impl FeatureMatcher) -> bool { + pub fn features_match<'a>(&'a self, checker: impl FeatureMatcher<'a>) -> bool { if let Some(m) = self.features.as_ref() { for (feat, expect) in m { if checker.matches(feat) != *expect { |
