Skip to main content

opys_mojang_rules/
rule.rs

1use serde::{Deserialize, Serialize};
2
3use crate::features::{satisfies_features, FeatureConstraint};
4use crate::os::{satisfies_os, OsConstraint, OsOptions, RuleError};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
7#[serde(rename_all = "lowercase")]
8pub enum RuleAction {
9    Allow,
10    Disallow,
11}
12
13/// A rule is `{ action }` plus an optional `os` or `features` constraint.
14///
15/// Order in `untagged` matters: the OS variant checks first, then features,
16/// then plain. JSON with extra keys is tolerated (matches the TS `z.object`
17/// strip-unknown behavior).
18#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
19#[serde(untagged)]
20pub enum Rule {
21    Os {
22        action: RuleAction,
23        os: OsConstraint,
24    },
25    Features {
26        action: RuleAction,
27        features: FeatureConstraint,
28    },
29    Plain {
30        action: RuleAction,
31    },
32}
33
34impl Rule {
35    pub fn action(&self) -> RuleAction {
36        match self {
37            Rule::Os { action, .. } | Rule::Features { action, .. } | Rule::Plain { action } => {
38                *action
39            }
40        }
41    }
42}
43
44pub fn satisfies_rule(
45    rule: &Rule,
46    os: &OsOptions,
47    feats: &[String],
48) -> Result<bool, RuleError> {
49    let allow = matches!(rule.action(), RuleAction::Allow);
50    match rule {
51        Rule::Os { os: c, .. } => Ok(satisfies_os(c, os)? == allow),
52        Rule::Features { features, .. } => Ok(satisfies_features(features, feats) == allow),
53        Rule::Plain { .. } => Ok(allow),
54    }
55}