diff options
| author | Filip Wandzio <contact@philw.dev> | 2026-02-25 16:10:23 +0100 |
|---|---|---|
| committer | Filip Wandzio <contact@philw.dev> | 2026-02-25 16:10:23 +0100 |
| commit | f7b4b643ebc52a4d72d90d9adbdddc9aa0721e4a (patch) | |
| tree | c96432be342b02bc0409e5b78b6b5d54afcc7cd6 /src/config/loader.rs | |
| parent | 2e10b0713f5369f489d2ababd70108cc359c5d2d (diff) | |
| download | dml-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 'src/config/loader.rs')
| -rw-r--r-- | src/config/loader.rs | 129 |
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 @@ | |||
| 1 | use std::{env::var, fs::read_to_string, path::PathBuf}; | 1 | use std::{env, fs::read_to_string, path::PathBuf}; |
| 2 | |||
| 3 | use directories::ProjectDirs; | 2 | use directories::ProjectDirs; |
| 4 | use serde::Deserialize; | 3 | use uuid::Uuid; |
| 5 | 4 | ||
| 5 | use super::{file::FileConfig, runtime::RuntimeConfig}; | ||
| 6 | use crate::{constants::*, errors::McError}; | 6 | use crate::{constants::*, errors::McError}; |
| 7 | #[allow(dead_code)] | 7 | |
| 8 | #[derive(Debug, Deserialize)] | 8 | pub struct ConfigLoader; |
| 9 | pub struct Config { | 9 | |
| 10 | pub username: String, | 10 | impl 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 | } | ||
| 21 | impl 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 | } |
| 61 | fn 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 | } | ||
