summaryrefslogtreecommitdiffstats
path: root/src/version.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/version.rs')
-rw-r--r--src/version.rs46
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 {