summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar bigfoot547 <[email protected]>2025-02-11 17:28:51 -0600
committerLibravatar bigfoot547 <[email protected]>2025-02-11 17:28:51 -0600
commit27ee95f3d6e65bae8022afa88cb0ee3d7d19108f (patch)
tree949958a4bd75552ed31e17cbd585d3a87a8cc9f9
parentadd some documentation (diff)
unstupid some stuff
-rw-r--r--ozone/src/launcher.rs55
-rw-r--r--ozone/src/launcher/rules.rs2
-rw-r--r--ozone/src/launcher/runner.rs23
-rw-r--r--ozone/src/launcher/strsub.rs83
-rw-r--r--ozone/src/version.rs15
5 files changed, 91 insertions, 87 deletions
diff --git a/ozone/src/launcher.rs b/ozone/src/launcher.rs
index a2902da..8c5db3f 100644
--- a/ozone/src/launcher.rs
+++ b/ozone/src/launcher.rs
@@ -197,9 +197,8 @@ impl Error for LaunchError {
}
}
-struct LaunchInfo<'l, F: FeatureMatcher> {
+struct LaunchInfo<'l> {
launcher: &'l Launcher,
- feature_matcher: &'l F,
client_id: Uuid,
asset_index_name: Option<String>,
@@ -225,12 +224,13 @@ pub struct Launch {
jni_launch: bool
}
-struct InstanceFeatureMatcher<'prof> {
- instance: &'prof Instance
+#[derive(Clone, Copy)]
+struct InstanceFeatureMatcher<'inst> {
+ instance: &'inst Instance
}
-impl FeatureMatcher for InstanceFeatureMatcher<'_> {
- fn matches(&self, feature: &str) -> bool {
+impl<'a> FeatureMatcher<'a> for InstanceFeatureMatcher<'_> {
+ fn matches(self, feature: &str) -> bool {
match feature {
"has_custom_resolution" => self.instance.resolution.is_some(),
_ => false
@@ -311,17 +311,10 @@ impl Launcher {
util::ensure_file(&path, dlinfo.url.as_deref(), dlinfo.size, dlinfo.sha1, self.online, false).await
.map_err(LaunchError::EnsureFile)?;
- struct PathSub<'a>(&'a Path);
- impl<'a> SubFunc<'a> for PathSub<'a> {
- fn substitute(&self, key: &str) -> Option<Cow<'a, str>> {
- match key {
- "path" => Some(self.0.as_java_path().to_string_lossy()),
- _ => None
- }
- }
- }
-
- Ok(strsub::replace_string(config.argument.as_str(), &PathSub(path.as_ref())).to_string())
+ Ok(strsub::replace_string(config.argument.as_str(), |k| match k {
+ "path" => Some(path.as_java_path().to_string_lossy()),
+ _ => None
+ }).to_string())
}
/* TODO:
@@ -356,7 +349,7 @@ impl Launcher {
};
let ver = self.versions.resolve_version(ver.as_ref()).await.map_err(LaunchError::ResolveVersion)?;
- ver.rules_apply(&self.system_info, &feature_matcher).map_err(LaunchError::IncompatibleVersion)?;
+ ver.rules_apply(&self.system_info, feature_matcher).map_err(LaunchError::IncompatibleVersion)?;
info!("Resolved launch version {}!", ver.id);
@@ -364,7 +357,7 @@ impl Launcher {
let mut downloads = IndexMap::new();
for lib in ver.libraries.iter() {
- if lib.rules_apply(&self.system_info, &feature_matcher).is_err() {
+ if lib.rules_apply(&self.system_info, feature_matcher).is_err() {
trace!("Skipping library {}, compatibility rules failed", lib.name);
continue;
}
@@ -510,7 +503,6 @@ impl Launcher {
info!("Deriving launch arguments");
let info = LaunchInfo {
launcher: self,
- feature_matcher: &feature_matcher,
client_id,
asset_index_name: asset_idx_name.map(|s| s.to_owned()),
@@ -534,10 +526,10 @@ impl Launcher {
let mut jvm_args: Vec<_> = instance.jvm_arguments.as_ref()
.map(|a| a.iter().map(OsString::from).collect())
.unwrap_or_else(|| iter_default_arguments().map(OsString::from).collect());
- jvm_args.extend(runner::build_arguments(&info, ver.as_ref(), ArgumentType::Jvm).into_iter());
+ jvm_args.extend(runner::build_arguments(&info, feature_matcher, ver.as_ref(), ArgumentType::Jvm).into_iter());
jvm_args.extend(log_arg.iter().map(OsString::from));
- let game_args = runner::build_arguments(&info, ver.as_ref(), ArgumentType::Game);
+ let game_args = runner::build_arguments(&info, feature_matcher, ver.as_ref(), ArgumentType::Game);
let diff = Instant::now().duration_since(start);
info!("Finished preparing launch for {} in {:.02} seconds!", ver.id, diff.as_secs_f32());
@@ -569,26 +561,23 @@ impl LibraryRepository {
fn get_artifact_filename(name: &str, classifier: Option<&str>) -> Option<PathBuf> {
let n: Vec<&str> = name.splitn(4, ':').skip(1).collect();
- struct LibReplace;
- impl SubFunc<'static> for LibReplace {
- fn substitute(&self, key: &str) -> Option<Cow<'static, str>> {
- match key {
- "arch" => Some(Cow::Borrowed(ozone_arch_bits!())),
- _ => None
- }
+ fn arch_sub(key: &str) -> Option<Cow<'static, str>> {
+ match key {
+ "arch" => Some(Cow::Borrowed(ozone_arch_bits!())),
+ _ => None
}
}
if let Some(classifier) = classifier {
match n.len() {
- 2 => Some(PathBuf::from(strsub::replace_string(format!("{}-{}-{}.jar", n[0], n[1], classifier).as_str(), &LibReplace).as_ref())),
- 3 => Some(PathBuf::from(strsub::replace_string(format!("{}-{}-{}-{}.jar", n[0], n[1], classifier, n[2]).as_str(), &LibReplace).as_ref())),
+ 2 => Some(PathBuf::from(strsub::replace_string(format!("{}-{}-{}.jar", n[0], n[1], classifier).as_str(), arch_sub).as_ref())),
+ 3 => Some(PathBuf::from(strsub::replace_string(format!("{}-{}-{}-{}.jar", n[0], n[1], classifier, n[2]).as_str(), arch_sub).as_ref())),
_ => None
}
} else {
match n.len() {
- 2 => Some(PathBuf::from(strsub::replace_string(format!("{}-{}.jar", n[0], n[1]).as_str(), &LibReplace).as_ref())),
- 3 => Some(PathBuf::from(strsub::replace_string(format!("{}-{}-{}.jar", n[0], n[1], n[2]).as_str(), &LibReplace).as_ref())),
+ 2 => Some(PathBuf::from(strsub::replace_string(format!("{}-{}.jar", n[0], n[1]).as_str(), arch_sub).as_ref())),
+ 3 => Some(PathBuf::from(strsub::replace_string(format!("{}-{}-{}.jar", n[0], n[1], n[2]).as_str(), arch_sub).as_ref())),
_ => None
}
}
diff --git a/ozone/src/launcher/rules.rs b/ozone/src/launcher/rules.rs
index ceed3ef..9d36157 100644
--- a/ozone/src/launcher/rules.rs
+++ b/ozone/src/launcher/rules.rs
@@ -31,7 +31,7 @@ mod seal {
}
pub trait CompatCheck: seal::CompatCheckInner {
- fn rules_apply(&self, system: &SystemInfo, feature_matcher: &impl FeatureMatcher) -> Result<(), IncompatibleError> {
+ fn rules_apply<'a>(&'a self, system: &SystemInfo, feature_matcher: impl FeatureMatcher<'a>) -> Result<(), IncompatibleError> {
let Some(rules) = self.get_rules() else { return Ok(()) };
let mut action = RuleAction::Disallow;
diff --git a/ozone/src/launcher/runner.rs b/ozone/src/launcher/runner.rs
index 7c1a903..4e1f353 100644
--- a/ozone/src/launcher/runner.rs
+++ b/ozone/src/launcher/runner.rs
@@ -1,6 +1,7 @@
use std::borrow::Cow;
use std::ffi::{OsStr, OsString};
use std::iter;
+use std::marker::PhantomData;
use std::path::{Path, PathBuf};
use std::process::Command;
use log::{debug, warn};
@@ -12,7 +13,7 @@ use super::strsub::{self, SubFunc};
use super::{Launch, LaunchInfo};
#[derive(Clone, Copy)]
-struct LaunchArgSub<'a, 'l, F: FeatureMatcher>(&'a LaunchInfo<'l, F>);
+struct LaunchArgSub<'a, 'l>(&'a LaunchInfo<'l>);
// FIXME: this is not correct
#[cfg(windows)]
@@ -21,8 +22,8 @@ const PATH_SEP: &str = ";";
#[cfg(not(windows))]
const PATH_SEP: &str = ":";
-impl<'rep, F: FeatureMatcher> SubFunc<'rep> for LaunchArgSub<'rep, '_, F> {
- fn substitute(&self, key: &str) -> Option<Cow<'rep, str>> {
+impl<'key, 'rep> SubFunc<'key, 'rep> for LaunchArgSub<'rep, '_> {
+ fn substitute(self, key: &'key str) -> Option<Cow<'rep, str>> {
match key {
"assets_index_name" => self.0.asset_index_name.as_ref().map(|s| Cow::Borrowed(s.as_str())),
"assets_root" => Some(self.0.launcher.assets.get_home().as_java_path().to_string_lossy()),
@@ -72,7 +73,7 @@ pub enum ArgumentType {
Game
}
-pub fn build_arguments<F: FeatureMatcher>(launch: &LaunchInfo<'_, F>, version: &CompleteVersion, arg_type: ArgumentType) -> Vec<OsString> {
+pub fn build_arguments<'v, F: FeatureMatcher<'v>>(launch: &LaunchInfo<'_>, feature_matcher: F, version: &'v CompleteVersion, arg_type: ArgumentType) -> Vec<OsString> {
let sub = LaunchArgSub(launch);
let system_info = &launch.launcher.system_info;
@@ -81,9 +82,9 @@ pub fn build_arguments<F: FeatureMatcher>(launch: &LaunchInfo<'_, F>, version: &
ArgumentType::Game => args.game.as_ref()
}) {
arguments.iter()
- .filter(|wa| wa.rules_apply(system_info, launch.feature_matcher).is_ok())
+ .filter(|wa| wa.rules_apply(system_info, feature_matcher).is_ok())
.flat_map(|wa| &wa.value)
- .map(|s| OsString::from(strsub::replace_string(s, &sub).into_owned())).collect()
+ .map(|s| OsString::from(strsub::replace_string(s, sub).into_owned())).collect()
} else if let Some(arguments) = version.minecraft_arguments.as_ref() {
match arg_type {
ArgumentType::Jvm => {
@@ -98,22 +99,22 @@ pub fn build_arguments<F: FeatureMatcher>(launch: &LaunchInfo<'_, F>, version: &
.chain(iter::once("-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump")
.take_while(|_| system_info.os == OperatingSystem::Windows))
.chain(iter::once(["-Dos.name=Windows 10", "-Dos.version=10.0"])
- .take_while(|_| launch.feature_matcher.matches("__ozone_win10_hack"))
+ .take_while(|_| feature_matcher.matches("__ozone_win10_hack"))
.flatten())
.chain(iter::once(["-Xdock:icon=${asset=icons/minecraft.icns}", "-Xdock:name=Minecraft"])
.take_while(|_| system_info.os == OperatingSystem::MacOS)
.flatten())
- .map(|s| OsString::from(strsub::replace_string(s, &sub).into_owned()))
+ .map(|s| OsString::from(strsub::replace_string(s, sub).into_owned()))
.collect()
},
ArgumentType::Game => {
arguments.split(' ')
.chain(iter::once("--demo")
- .take_while(|_| launch.feature_matcher.matches("is_demo_user")))
+ .take_while(|_| feature_matcher.matches("is_demo_user")))
.chain(iter::once(["--width", "${resolution_width}", "--height", "${resolution_height}"])
- .take_while(|_| launch.feature_matcher.matches("has_custom_resolution"))
+ .take_while(|_| feature_matcher.matches("has_custom_resolution"))
.flatten())
- .map(|s| OsString::from(strsub::replace_string(s, &sub).into_owned()))
+ .map(|s| OsString::from(strsub::replace_string(s, sub).into_owned()))
.collect()
}
}
diff --git a/ozone/src/launcher/strsub.rs b/ozone/src/launcher/strsub.rs
index 5764405..307d0a1 100644
--- a/ozone/src/launcher/strsub.rs
+++ b/ozone/src/launcher/strsub.rs
@@ -8,8 +8,17 @@ const VAR_BEGIN: &str = "${";
const VAR_END: &str = "}";
const VAR_DEFAULT: &str = ":-";
-pub trait SubFunc<'rep> {
- fn substitute(&self, key: &str) -> Option<Cow<'rep, str>>;
+pub trait SubFunc<'key, 'rep>: Copy {
+ fn substitute(self, key: &'key str) -> Option<Cow<'rep, str>>;
+}
+
+impl<'key, 'rep, F> SubFunc<'key, 'rep> for F
+where
+ F: Fn(&'key str) -> Option<Cow<'rep, str>> + Copy
+{
+ fn substitute(self, key: &'key str) -> Option<Cow<'rep, str>> {
+ self(key)
+ }
}
/* NOTE: the in-place implementation has been replaced for the following reasons:
@@ -60,7 +69,7 @@ pub trait SubFunc<'rep> {
}
}*/
-pub fn replace_string<'inp, 'rep>(input: &'inp str, sub: &impl SubFunc<'rep>) -> Cow<'inp, str> {
+pub fn replace_string<'inp, 'rep>(input: &'inp str, sub: impl SubFunc<'inp, 'rep>) -> Cow<'inp, str> {
let mut ret: Option<String> = None;
let mut cursor = 0usize;
@@ -116,77 +125,73 @@ pub fn replace_string<'inp, 'rep>(input: &'inp str, sub: &impl SubFunc<'rep>) ->
mod tests {
use super::*;
- #[derive(Clone, Copy)]
- struct TestSub;
- impl SubFunc<'static> for TestSub {
- fn substitute(&self, key: &str) -> Option<Cow<'static, str>> {
- match key {
- "exists" => Some(Cow::Borrowed("value123")),
- "empty" => None,
- "borger" => Some(Cow::Borrowed("\u{1f354}")),
- _ => panic!("replace_fun called with unexpected key: {}", key)
- }
+ fn test_sub(key: &str) -> Option<Cow<'static, str>> {
+ match key {
+ "exists" => Some(Cow::Borrowed("value123")),
+ "empty" => None,
+ "borger" => Some(Cow::Borrowed("\u{1f354}")),
+ _ => panic!("replace_fun called with unexpected key: {}", key)
}
}
#[test]
fn test_standard_replace() {
- assert_eq!(replace_string("this has ${exists} and more", &TestSub), "this has value123 and more");
- assert_eq!(replace_string("multiple ${exists} repl${exists}ace", &TestSub), "multiple value123 replvalue123ace");
- assert_eq!(replace_string("${exists}${exists}", &TestSub), "value123value123");
+ assert_eq!(replace_string("this has ${exists} and more", test_sub), "this has value123 and more");
+ assert_eq!(replace_string("multiple ${exists} repl${exists}ace", test_sub), "multiple value123 replvalue123ace");
+ assert_eq!(replace_string("${exists}${exists}", test_sub), "value123value123");
}
#[test]
fn test_empty_replace() {
- assert_eq!(replace_string("this has ${empty} and more", &TestSub), "this has ${empty} and more");
- assert_eq!(replace_string("multiple ${empty} repl${empty}ace", &TestSub), "multiple ${empty} repl${empty}ace");
- assert_eq!(replace_string("${empty}${empty}", &TestSub), "${empty}${empty}");
+ assert_eq!(replace_string("this has ${empty} and more", test_sub), "this has ${empty} and more");
+ assert_eq!(replace_string("multiple ${empty} repl${empty}ace", test_sub), "multiple ${empty} repl${empty}ace");
+ assert_eq!(replace_string("${empty}${empty}", test_sub), "${empty}${empty}");
}
#[test]
fn test_homogenous_replace() {
- assert_eq!(replace_string("some ${exists} and ${empty} ...", &TestSub), "some value123 and ${empty} ...");
- assert_eq!(replace_string("some ${empty} and ${exists} ...", &TestSub), "some ${empty} and value123 ...");
- assert_eq!(replace_string("${exists}${empty}", &TestSub), "value123${empty}");
- assert_eq!(replace_string("${empty}${exists}", &TestSub), "${empty}value123");
+ assert_eq!(replace_string("some ${exists} and ${empty} ...", test_sub), "some value123 and ${empty} ...");
+ assert_eq!(replace_string("some ${empty} and ${exists} ...", test_sub), "some ${empty} and value123 ...");
+ assert_eq!(replace_string("${exists}${empty}", test_sub), "value123${empty}");
+ assert_eq!(replace_string("${empty}${exists}", test_sub), "${empty}value123");
}
#[test]
fn test_default_replace() {
- assert_eq!(replace_string("some ${exists:-def1} and ${empty:-def2} ...", &TestSub), "some value123 and def2 ...");
- assert_eq!(replace_string("some ${empty:-def1} and ${exists:-def2} ...", &TestSub), "some def1 and value123 ...");
- assert_eq!(replace_string("abc${empty:-}def", &TestSub), "abcdef");
- assert_eq!(replace_string("${empty:-}${empty:-}", &TestSub), "");
+ assert_eq!(replace_string("some ${exists:-def1} and ${empty:-def2} ...", test_sub), "some value123 and def2 ...");
+ assert_eq!(replace_string("some ${empty:-def1} and ${exists:-def2} ...", test_sub), "some def1 and value123 ...");
+ assert_eq!(replace_string("abc${empty:-}def", test_sub), "abcdef");
+ assert_eq!(replace_string("${empty:-}${empty:-}", test_sub), "");
}
#[test]
fn test_escape() {
- assert_eq!(replace_string("an $${escaped} replacement (${exists})", &TestSub), "an ${escaped} replacement (value123)");
- assert_eq!(replace_string("${exists}$${escaped}${exists}", &TestSub), "value123${escaped}value123");
+ assert_eq!(replace_string("an $${escaped} replacement (${exists})", test_sub), "an ${escaped} replacement (value123)");
+ assert_eq!(replace_string("${exists}$${escaped}${exists}", test_sub), "value123${escaped}value123");
// make sure this weird behavior is preserved... (the original code seemed to show it)
- assert_eq!(replace_string("some $${ else", &TestSub), "some ${ else");
+ assert_eq!(replace_string("some $${ else", test_sub), "some ${ else");
}
#[test]
fn test_weird() {
- assert_eq!(replace_string("${exists}", &TestSub), "value123");
- assert_eq!(replace_string("$${empty}", &TestSub), "${empty}");
- assert_eq!(replace_string("${empty:-a}", &TestSub), "a");
- assert_eq!(replace_string("${empty:-}", &TestSub), "");
+ assert_eq!(replace_string("${exists}", test_sub), "value123");
+ assert_eq!(replace_string("$${empty}", test_sub), "${empty}");
+ assert_eq!(replace_string("${empty:-a}", test_sub), "a");
+ assert_eq!(replace_string("${empty:-}", test_sub), "");
}
// these make sure it doesn't chop up multibyte characters illegally
#[test]
fn test_multibyte_surround() {
- assert_eq!(replace_string("\u{1f354}$${}\u{1f354}", &TestSub), "\u{1f354}${}\u{1f354}");
- assert_eq!(replace_string("\u{1f354}${exists}\u{1f354}${empty:-}\u{1f354}", &TestSub), "\u{1f354}value123\u{1f354}\u{1f354}");
+ assert_eq!(replace_string("\u{1f354}$${}\u{1f354}", test_sub), "\u{1f354}${}\u{1f354}");
+ assert_eq!(replace_string("\u{1f354}${exists}\u{1f354}${empty:-}\u{1f354}", test_sub), "\u{1f354}value123\u{1f354}\u{1f354}");
}
#[test]
fn test_multibyte_replace() {
- assert_eq!(replace_string("borger ${borger}", &TestSub), "borger \u{1f354}");
- assert_eq!(replace_string("${exists:-\u{1f354}}${empty:-\u{1f354}}", &TestSub), "value123\u{1f354}");
- assert_eq!(replace_string("${borger}$${}${borger}", &TestSub), "\u{1f354}${}\u{1f354}");
+ assert_eq!(replace_string("borger ${borger}", test_sub), "borger \u{1f354}");
+ assert_eq!(replace_string("${exists:-\u{1f354}}${empty:-\u{1f354}}", test_sub), "value123\u{1f354}");
+ assert_eq!(replace_string("${borger}$${}${borger}", test_sub), "\u{1f354}${}\u{1f354}");
}
}
diff --git a/ozone/src/version.rs b/ozone/src/version.rs
index 27c2a6d..458ed80 100644
--- a/ozone/src/version.rs
+++ b/ozone/src/version.rs
@@ -81,12 +81,21 @@ pub struct CompatibilityRule {
pub os: Option<OSRestriction>
}
-pub trait FeatureMatcher {
- fn matches(&self, feature: &str) -> bool;
+pub trait FeatureMatcher<'feat>: Copy {
+ fn matches(self, feature: &'feat str) -> bool;
+}
+
+impl<'feat, F> FeatureMatcher<'feat> for F
+where
+ F: Fn(&'feat str) -> bool + Copy
+{
+ fn matches(self, feature: &'feat 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 {