use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct LibraryRule {
pub action: RuleAction,
pub os: Option<OsRule>,
pub features: Option<serde_json::Value>,
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum RuleAction {
Allow,
Disallow,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct OsRule {
pub name: Option<String>,
pub version: Option<String>,
pub arch: Option<String>,
}
pub fn mojang_os() -> &'static str {
match std::env::consts::OS {
"macos" => "osx",
other => other, }
}
pub fn mojang_arch() -> &'static str {
match std::env::consts::ARCH {
"x86" => "x86",
"aarch64" => "aarch64",
"arm" => "arm",
_ => "x86_64",
}
}
pub fn skip_library(rules: &[LibraryRule]) -> bool {
if rules.is_empty() {
return false;
}
let current_os = mojang_os();
let mut should_skip = true;
for rule in rules {
if rule.features.is_some() {
continue;
}
let os_matches = match &rule.os {
None => true,
Some(os_rule) => os_rule.name.as_deref() == Some(current_os),
};
if os_matches {
should_skip = matches!(rule.action, RuleAction::Disallow);
}
}
should_skip
}
#[cfg(test)]
mod tests {
use super::*;
fn allow(os: Option<&str>) -> LibraryRule {
LibraryRule {
action: RuleAction::Allow,
os: os.map(|n| OsRule {
name: Some(n.to_string()),
version: None,
arch: None,
}),
features: None,
}
}
fn disallow(os: Option<&str>) -> LibraryRule {
LibraryRule {
action: RuleAction::Disallow,
os: os.map(|n| OsRule {
name: Some(n.to_string()),
version: None,
arch: None,
}),
features: None,
}
}
#[test]
fn no_rules_means_include() {
assert!(!skip_library(&[]));
}
#[test]
fn allow_all_includes_on_every_os() {
assert!(!skip_library(&[allow(None)]));
}
#[test]
fn last_rule_wins() {
assert!(skip_library(&[allow(None), disallow(None)]));
assert!(!skip_library(&[disallow(None), allow(None)]));
}
#[test]
fn os_specific_rule_only_matches_that_os() {
let other_os = if mojang_os() == "linux" { "windows" } else { "linux" };
let rules = vec![allow(None), disallow(Some(other_os))];
assert!(!skip_library(&rules));
}
#[test]
fn mojang_os_is_not_macos() {
if std::env::consts::OS == "macos" {
assert_eq!(mojang_os(), "osx");
}
}
}