tx_di_core/di/comp/
config.rs1use std::any::TypeId;
2use std::fs;
3use std::path::{Path, PathBuf};
4use serde::de::DeserializeOwned;
5use toml::Value::Table;
6use crate::{BuildContext, CompInit, ComponentDescriptor, Scope};
7
8pub struct AppAllConfig{
10 pub toml_value: toml::Value,
11}
12impl AppAllConfig {
13 pub fn new<P: Into<PathBuf>>(config_path: Option<P>) -> Self {
14 let final_config_path = if let Some(path) = config_path {
17 path.into()
18 } else {
19 let exe_path = std::env::current_exe().unwrap_or_else(|e| {
21 eprintln!("[di] 警告:无法获取可执行文件路径: {}", e);
22 PathBuf::from(".")
23 });
24
25 let config_dir = exe_path.parent().unwrap_or_else(|| {
26 eprintln!("[di] 警告:无法获取可执行文件父目录");
27 Path::new(".")
28 }).join("config");
29
30 config_dir.join("config.toml")
31 };
32 let toml_value = Self::load_config(final_config_path.as_path());
33 AppAllConfig {
34 toml_value,
35 }
36 }
37 fn load_config(path: &Path) -> toml::Value {
39 let config = Table(toml::map::Map::new());
40 if !path.exists() {
41 eprintln!("[di] 配置文件不存在: {:?},将使用默认配置", path);
42 return config;
43 }
44
45 let content = match fs::read_to_string(path) {
46 Ok(c) => c,
47 Err(e) => {
48 eprintln!("[di] 警告:无法读取配置文件 '{:?}': {}", path, e);
49 return config;
50 }
51 };
52
53 let config: toml::Value = match toml::from_str(&content) {
55 Ok(v) => v,
56 Err(e) => {
57 eprintln!("[di] 警告:配置文件 '{:?}' 解析失败: {}", path, e);
58 return config;
59 }
60 };
61 eprintln!("[di] 配置文件加载成功: {:?}", path);
63 config
64 }
65
66 pub fn get<T: DeserializeOwned>(&self, key: &str) -> Option<T> {
67 let value = self.get_value(key)?;
68 T::deserialize(value.clone()).ok()
69 }
70 pub fn get_or_default<T: DeserializeOwned>(&self, key: &str, default: T) -> T {
71 self.get(key).unwrap_or(default)
72 }
73
74 pub fn get_value(&self, key: &str) -> Option<&toml::Value> {
75 let keys: Vec<&str> = key.split('.').collect();
76 let mut current = &self.toml_value;
77 for k in keys {
78 current = current.get(k)?;
79 }
80 Some(current)
81 }
82}
83
84impl CompInit for AppAllConfig {}
85
86impl ComponentDescriptor for AppAllConfig {
87 const DEP_IDS: &'static [fn() -> TypeId] = &[];
88 const SCOPE: Scope = Scope::Singleton;
89
90 fn build(_ctx: &mut BuildContext) -> Self {
91 panic!("AppAllConfig should not be built via ComponentDescriptor::build. It is manually created in BuildContext::new().")
92 }
93}