summaryrefslogtreecommitdiffstats
path: root/src/launcher
diff options
context:
space:
mode:
Diffstat (limited to 'src/launcher')
-rw-r--r--src/launcher/jre.rs101
-rw-r--r--src/launcher/jre/arch.rs45
-rw-r--r--src/launcher/jre/manifest.rs49
3 files changed, 195 insertions, 0 deletions
diff --git a/src/launcher/jre.rs b/src/launcher/jre.rs
new file mode 100644
index 0000000..2979c52
--- /dev/null
+++ b/src/launcher/jre.rs
@@ -0,0 +1,101 @@
+use std::error::Error;
+use std::fmt::{Display, Formatter};
+use std::path::{Path, PathBuf};
+use log::{debug, info, warn};
+use tokio::{fs, io};
+
+mod arch;
+mod manifest;
+
+use arch::JRE_ARCH;
+use manifest::JavaRuntimesManifest;
+use crate::launcher::jre::manifest::JavaRuntimeManifest;
+use super::constants;
+
+pub struct JavaRuntimeRepository {
+ home: PathBuf,
+ manifest: JavaRuntimesManifest
+}
+
+impl JavaRuntimeRepository {
+ pub async fn new(home: impl AsRef<Path>) -> Result<Self, JavaRuntimeError> {
+ info!("Java runtime architecture is \"{}\".", JRE_ARCH);
+
+ fs::create_dir_all(&home).await.map_err(|e| JavaRuntimeError::IO { what: "creating home directory", error: e })?;
+
+ let manifest: JavaRuntimesManifest = reqwest::get(constants::URL_JRE_MANIFEST).await
+ .map_err(|e| JavaRuntimeError::Download {
+ what: "runtime manifest (all.json)",
+ error: e
+ })?.json().await
+ .map_err(|e| JavaRuntimeError::Download {
+ what: "runtime manifest (all.json)",
+ error: e
+ })?;
+
+ Ok(JavaRuntimeRepository {
+ home: home.as_ref().to_path_buf(),
+ manifest
+ })
+ }
+
+ pub async fn choose_runtime(&self, component: &str) -> Result<JavaRuntimeManifest, JavaRuntimeError> {
+ let Some(runtime_components) = self.manifest.get(JRE_ARCH) else {
+ return Err(JavaRuntimeError::UnsupportedArch(JRE_ARCH));
+ };
+
+ let Some(runtime_component) = runtime_components.get(component) else {
+ return Err(JavaRuntimeError::UnsupportedComponent { arch: JRE_ARCH, component: component.to_owned() });
+ };
+
+ let Some(runtime) = runtime_component.iter().filter(|r| r.availability.progress == 100).next() else {
+ if !runtime_components.is_empty() {
+ warn!("Weird: the only java runtimes in {JRE_ARCH}.{component} has a progress of less than 100!");
+ }
+
+ return Err(JavaRuntimeError::UnsupportedComponent { arch: JRE_ARCH, component: component.to_owned() });
+ };
+
+ let Some(ref url) = runtime.manifest.url else {
+ return Err(JavaRuntimeError::MalformedManifest);
+ };
+
+ debug!("Ensuring manifest for runtime {JRE_ARCH}.{component}: {url}");
+
+
+ // hmm maybe
+
+ todo!()
+ }
+}
+
+#[derive(Debug)]
+pub enum JavaRuntimeError {
+ IO { what: &'static str, error: io::Error },
+ Download { what: &'static str, error: reqwest::Error },
+ UnsupportedArch(&'static str),
+ UnsupportedComponent { arch: &'static str, component: String },
+ MalformedManifest
+}
+
+impl Display for JavaRuntimeError {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ match self {
+ JavaRuntimeError::IO { what, error } => write!(f, "i/o error ({}): {}", what, error),
+ JavaRuntimeError::Download { what, error } => write!(f, "error downloading {}: {}", what, error),
+ JavaRuntimeError::UnsupportedArch(arch) => write!(f, r#"unsupported architecture "{arch}""#),
+ JavaRuntimeError::UnsupportedComponent { arch, component } => write!(f, r#"unsupported component "{component}" for architecture "{arch}""#),
+ JavaRuntimeError::MalformedManifest => f.write_str("malformed runtime manifest (launcher bug?)"),
+ }
+ }
+}
+
+impl Error for JavaRuntimeError {
+ fn source(&self) -> Option<&(dyn Error + 'static)> {
+ match self {
+ JavaRuntimeError::IO { error, .. } => Some(error),
+ JavaRuntimeError::Download { error, .. } => Some(error),
+ _ => None
+ }
+ }
+}
diff --git a/src/launcher/jre/arch.rs b/src/launcher/jre/arch.rs
new file mode 100644
index 0000000..e984171
--- /dev/null
+++ b/src/launcher/jre/arch.rs
@@ -0,0 +1,45 @@
+use cfg_if::cfg_if;
+
+macro_rules! define_arch {
+ ($arch:expr) => {
+ pub const JRE_ARCH: &str = $arch;
+ }
+}
+
+cfg_if! {
+ if #[cfg(target_os = "windows")] {
+ cfg_if! {
+ if #[cfg(target_arch = "x86_64")] {
+ define_arch!("windows-x64");
+ } else if #[cfg(target_arch = "x86")] {
+ define_arch!("windows-x86");
+ } else if #[cfg(target_arch = "aarch64")] {
+ define_arch!("windows-arm64");
+ } else {
+ define_arch!("gamecore");
+ }
+ }
+ } else if #[cfg(target_os = "linux")] {
+ cfg_if! {
+ if #[cfg(target_arch = "x86_64")] {
+ define_arch!("linux");
+ } else if #[cfg(target_arch = "x86")] {
+ define_arch!("linux-i386");
+ } else {
+ define_arch!("gamecore");
+ }
+ }
+ } else if #[cfg(target_os = "macos")] {
+ cfg_if! {
+ if #[cfg(target_arch = "aarch64")] {
+ define_arch!("mac-os-arm64");
+ } else if #[cfg(target_arch = "x86_64")] {
+ define_arch!("mac-os");
+ } else {
+ define_arch!("gamecore");
+ }
+ }
+ } else {
+ define_arch!("gamecore");
+ }
+}
diff --git a/src/launcher/jre/manifest.rs b/src/launcher/jre/manifest.rs
new file mode 100644
index 0000000..9b84377
--- /dev/null
+++ b/src/launcher/jre/manifest.rs
@@ -0,0 +1,49 @@
+use std::collections::HashMap;
+use serde::Deserialize;
+use crate::version::DownloadInfo;
+
+#[derive(Debug, Deserialize)]
+pub struct Availability {
+ pub group: u32, // unknown meaning
+ pub progress: u32 // unknown meaning
+}
+
+#[derive(Debug, Deserialize)]
+pub struct Version {
+ pub name: String,
+ pub version: String
+}
+
+#[derive(Debug, Deserialize)]
+pub struct JavaRuntimeInfo {
+ // I don't see how half of this information is useful with how the JRE system currently functions -figboot
+ pub availability: Availability,
+ pub manifest: DownloadInfo,
+ pub version: Version
+}
+
+pub type JavaRuntimesManifest = HashMap<String, HashMap<String, Vec<JavaRuntimeInfo>>>;
+
+#[derive(Debug, Deserialize, Clone, Copy, Eq, PartialEq)]
+#[serde(rename_all = "lowercase")]
+pub enum FileType {
+ File,
+ Directory,
+ Link
+}
+
+#[derive(Debug, Deserialize)]
+pub struct JavaRuntimeFile {
+ #[serde(rename = "type")]
+ pub file_type: FileType,
+ #[serde(default)]
+ pub executable: bool,
+
+ pub lzma: DownloadInfo,
+ pub raw: DownloadInfo
+}
+
+#[derive(Debug, Deserialize)]
+pub struct JavaRuntimeManifest {
+ pub files: HashMap<String, JavaRuntimeFile>
+}