aboutsummaryrefslogtreecommitdiffstats
path: root/src/config/loader.rs
diff options
context:
space:
mode:
authorFilip Wandzio <contact@philw.dev>2026-02-25 16:10:23 +0100
committerFilip Wandzio <contact@philw.dev>2026-02-25 16:10:23 +0100
commitf7b4b643ebc52a4d72d90d9adbdddc9aa0721e4a (patch)
treec96432be342b02bc0409e5b78b6b5d54afcc7cd6 /src/config/loader.rs
parent2e10b0713f5369f489d2ababd70108cc359c5d2d (diff)
downloaddml-f7b4b643ebc52a4d72d90d9adbdddc9aa0721e4a.tar.gz
dml-f7b4b643ebc52a4d72d90d9adbdddc9aa0721e4a.zip
Feat: Refactor core download logic with concurrency and async features
Implement basic unit testing Implement automatic java executable switching based on game version Split loader module into smaller modules Implement basic documentation
Diffstat (limited to '')
-rw-r--r--src/config/loader.rs129
1 files changed, 77 insertions, 52 deletions
diff --git a/src/config/loader.rs b/src/config/loader.rs
index d4b142e..47514e5 100644
--- a/src/config/loader.rs
+++ b/src/config/loader.rs
@@ -1,65 +1,90 @@
1use std::{env::var, fs::read_to_string, path::PathBuf}; 1use std::{env, fs::read_to_string, path::PathBuf};
2
3use directories::ProjectDirs; 2use directories::ProjectDirs;
4use serde::Deserialize; 3use uuid::Uuid;
5 4
5use super::{file::FileConfig, runtime::RuntimeConfig};
6use crate::{constants::*, errors::McError}; 6use crate::{constants::*, errors::McError};
7#[allow(dead_code)] 7
8#[derive(Debug, Deserialize)] 8pub struct ConfigLoader;
9pub struct Config { 9
10 pub username: String, 10impl ConfigLoader {
11 pub uuid: String, 11 pub fn load(cfg_file: Option<&PathBuf>) -> Result<RuntimeConfig, McError> {
12 pub version: String, 12 let path = match cfg_file {
13 pub java_path: String, 13 | Some(p) => p.clone(),
14 pub max_memory_mb: u32, 14 | None => Self::default_config_path()?,
15 pub data_dir: PathBuf, 15 };
16 pub cache_dir: PathBuf, 16
17 pub config_dir: PathBuf, 17 let mut file_cfg = if path.exists() {
18 #[serde(default)] 18 Self::read_file(&path)?
19 pub jvm_args: Vec<String>,
20}
21impl Config {
22 pub fn load() -> Result<Self, McError> {
23 let cfg_path = default_config_path()?;
24 let mut cfg: Config = if cfg_path.exists() {
25 let txt = read_to_string(&cfg_path)?;
26 toml::from_str(&txt).map_err(|e| McError::Config(e.to_string()))?
27 } else { 19 } else {
28 Self::default() 20 Self::default_file_config()?
29 }; 21 };
30 if let Ok(v) = var("MC_USERNAME") { 22
31 cfg.username = v; 23 Self::apply_env_overrides(&mut file_cfg);
32 } 24
33 if let Ok(v) = var("MC_VERSION") { 25 Ok(RuntimeConfig::from_file(file_cfg))
34 cfg.version = v; 26 }
35 } 27
36 if let Ok(v) = var("MC_JAVA_PATH") { 28 fn read_file(path: &PathBuf) -> Result<FileConfig, McError> {
37 cfg.java_path = v; 29 let content = read_to_string(path).map_err(|e| {
38 } 30 McError::Config(format!(
39 if let Ok(v) = var("MC_MAX_MEMORY_MB") { 31 "Failed to read config file {}: {}",
40 cfg.max_memory_mb = v.parse().unwrap_or(cfg.max_memory_mb); 32 path.display(),
41 } 33 e
42 Ok(cfg) 34 ))
35 })?;
36
37 toml::from_str(&content).map_err(|e| {
38 McError::Config(format!("Failed to parse config file: {}", e))
39 })
43 } 40 }
44 41
45 fn default() -> Self { 42 fn apply_env_overrides(cfg: &mut FileConfig) {
46 let base = 43 cfg.username = env::var(ENV_USERNAME)
47 ProjectDirs::from("com", "example", "dml").expect("platform dirs"); 44 .unwrap_or_else(|_| DEFAULT_USERNAME.to_string());
48 Self { 45
49 username: "Player".into(), 46 cfg.version = env::var(ENV_VERSION)
50 uuid: uuid::Uuid::new_v4().to_string(), 47 .unwrap_or_else(|_| DEFAULT_VERSION.to_string());
48
49 cfg.java_path = env::var(ENV_JAVA_PATH)
50 .unwrap_or_else(|_| DEFAULT_JAVA_PATH.to_string());
51
52 cfg.max_memory_mb = env::var(ENV_MAX_MEMORY_MB)
53 .ok()
54 .and_then(|v| v.parse().ok())
55 .unwrap_or(DEFAULT_MAX_MEMORY_MB);
56 }
57
58 fn default_config_path() -> Result<PathBuf, McError> {
59 let base = ProjectDirs::from(
60 DEFAULT_COMPANY,
61 DEFAULT_PROJECT_GROUP,
62 DEFAULT_PROJECT_NAME,
63 )
64 .ok_or_else(|| McError::Config(DEFAULT_ERR_PLATFORM_DIR.into()))?;
65
66 Ok(base.config_dir().join(DEFAULT_CONFIG_FILENAME))
67 }
68
69 fn default_file_config() -> Result<FileConfig, McError> {
70 let base = ProjectDirs::from(
71 DEFAULT_COMPANY,
72 DEFAULT_PROJECT_GROUP,
73 DEFAULT_PROJECT_NAME,
74 )
75 .ok_or_else(|| McError::Config(DEFAULT_ERR_PLATFORM_DIR.into()))?;
76
77 Ok(FileConfig {
78 username: DEFAULT_USERNAME.into(),
79 uuid: Uuid::new_v4().to_string(),
51 version: DEFAULT_VERSION.into(), 80 version: DEFAULT_VERSION.into(),
52 java_path: DEFAULT_JAVA_PATH.into(),
53 max_memory_mb: DEFAULT_MAX_MEMORY_MB, 81 max_memory_mb: DEFAULT_MAX_MEMORY_MB,
82 java_path: DEFAULT_JAVA_PATH.into(),
54 data_dir: base.data_dir().into(), 83 data_dir: base.data_dir().into(),
55 cache_dir: base.cache_dir().into(), 84 // cache_dir: base.cache_dir().into(),
56 config_dir: base.config_dir().into(), 85 // config_dir: base.config_dir().into(),
57 jvm_args: vec![], 86 jvm_args: vec![],
58 } 87 runtimes: vec![],
88 })
59 } 89 }
60} 90}
61fn default_config_path() -> Result<PathBuf, McError> {
62 let base = ProjectDirs::from("com", "example", "dml")
63 .ok_or_else(|| McError::Config("cannot determine config dir".into()))?;
64 Ok(base.config_dir().join("config.toml"))
65}