use std::{env, fs::read_to_string, path::PathBuf}; use directories::ProjectDirs; use uuid::Uuid; use super::{file::FileConfig, runtime::RuntimeConfig}; use crate::{constants::*, errors::McError}; pub struct ConfigLoader; impl ConfigLoader { pub fn load(cfg_file: Option<&PathBuf>) -> Result { let path = match cfg_file { | Some(p) => p.clone(), | None => Self::default_config_path()?, }; let mut file_cfg = if path.exists() { Self::read_file(&path)? } else { Self::default_file_config()? }; Self::apply_env_overrides(&mut file_cfg); Ok(RuntimeConfig::from_file(file_cfg)) } fn read_file(path: &PathBuf) -> Result { let content = read_to_string(path).map_err(|e| { McError::Config(format!( "Failed to read config file {}: {}", path.display(), e )) })?; toml::from_str(&content).map_err(|e| { McError::Config(format!("Failed to parse config file: {}", e)) }) } fn apply_env_overrides(cfg: &mut FileConfig) { cfg.username = env::var(ENV_USERNAME) .unwrap_or_else(|_| DEFAULT_USERNAME.to_string()); cfg.version = env::var(ENV_VERSION) .unwrap_or_else(|_| DEFAULT_VERSION.to_string()); cfg.java_path = env::var(ENV_JAVA_PATH) .unwrap_or_else(|_| DEFAULT_JAVA_PATH.to_string()); cfg.max_memory_mb = env::var(ENV_MAX_MEMORY_MB) .ok() .and_then(|v| v.parse().ok()) .unwrap_or(DEFAULT_MAX_MEMORY_MB); } fn default_config_path() -> Result { let base = ProjectDirs::from( DEFAULT_COMPANY, DEFAULT_PROJECT_GROUP, DEFAULT_PROJECT_NAME, ) .ok_or_else(|| McError::Config(DEFAULT_ERR_PLATFORM_DIR.into()))?; Ok(base.config_dir().join(DEFAULT_CONFIG_FILENAME)) } fn default_file_config() -> Result { let base = ProjectDirs::from( DEFAULT_COMPANY, DEFAULT_PROJECT_GROUP, DEFAULT_PROJECT_NAME, ) .ok_or_else(|| McError::Config(DEFAULT_ERR_PLATFORM_DIR.into()))?; Ok(FileConfig { username: DEFAULT_USERNAME.into(), uuid: Uuid::new_v4().to_string(), version: DEFAULT_VERSION.into(), max_memory_mb: DEFAULT_MAX_MEMORY_MB, java_path: DEFAULT_JAVA_PATH.into(), data_dir: base.data_dir().into(), // cache_dir: base.cache_dir().into(), // config_dir: base.config_dir().into(), jvm_args: vec![], runtimes: vec![], }) } }