diff options
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/utils/cfg_file/cfg_file_test/src/lib.rs | 8 | ||||
| -rw-r--r-- | crates/utils/cfg_file/src/config.rs | 161 |
2 files changed, 57 insertions, 112 deletions
diff --git a/crates/utils/cfg_file/cfg_file_test/src/lib.rs b/crates/utils/cfg_file/cfg_file_test/src/lib.rs index fd805f1..800dfe7 100644 --- a/crates/utils/cfg_file/cfg_file_test/src/lib.rs +++ b/crates/utils/cfg_file/cfg_file_test/src/lib.rs @@ -1,7 +1,3 @@ -pub fn add(left: u64, right: u64) -> u64 { - left + right -} - #[cfg(test)] mod test_cfg_file { use cfg_file::ConfigFile; @@ -42,10 +38,10 @@ mod test_cfg_file { .entry("Peek".to_string()) .insert_entry(secret_peek.to_string()); - ExampleConfig::write(&example).await; // Write to default path. + ExampleConfig::write(&example).await.unwrap(); // Write to default path. // Read from default path. - let read_cfg = ExampleConfig::read().await; + let read_cfg = ExampleConfig::read().await.unwrap(); assert_eq!(read_cfg.name, "Weicao"); assert_eq!(read_cfg.age, 22); assert_eq!(read_cfg.hobby, vec!["Programming", "Painting"]); diff --git a/crates/utils/cfg_file/src/config.rs b/crates/utils/cfg_file/src/config.rs index 2333ab7..75c598b 100644 --- a/crates/utils/cfg_file/src/config.rs +++ b/crates/utils/cfg_file/src/config.rs @@ -1,4 +1,5 @@ use async_trait::async_trait; +use ron; use serde::{Deserialize, Serialize}; use std::{ borrow::Cow, @@ -38,96 +39,67 @@ pub trait ConfigFile: Serialize + for<'a> Deserialize<'a> + Default { fn default_path() -> Result<PathBuf, Error>; - async fn read() -> Self::DataType + async fn read() -> Result<Self::DataType, std::io::Error> where Self: Sized + Send + Sync, { - let Ok(path) = Self::default_path() else { - return Self::DataType::default(); - }; - + let path = Self::default_path()?; Self::read_from(path).await } - async fn read_from(path: impl AsRef<Path> + Send) -> Self::DataType + async fn read_from(path: impl AsRef<Path> + Send) -> Result<Self::DataType, std::io::Error> where Self: Sized + Send + Sync, { let path = path.as_ref(); - let file_path = match current_dir() { - Ok(cwd) => cwd.join(path), - Err(e) => { - eprintln!("Failed to get current directory: {}", e); - return Self::DataType::default(); - } - }; + let cwd = current_dir()?; + let file_path = cwd.join(path); // Check if file exists - match fs::metadata(&file_path).await { - Ok(_) => { - // Open file - let mut file = match fs::File::open(&file_path).await { - Ok(file) => file, - Err(e) => { - eprintln!("Failed to open file {}: {}", path.display(), e); - return Self::DataType::default(); - } - }; - - let mut contents = String::new(); - - // Read contents - if let Err(e) = file.read_to_string(&mut contents).await { - eprintln!("Failed to read file {}: {}", path.display(), e); - return Self::DataType::default(); - } - - // Determine file format - let format = file_path - .file_name() - .and_then(|name| name.to_str()) - .and_then(ConfigFormat::from_filename) - .unwrap_or(ConfigFormat::Json); // Default to JSON - - // Deserialize based on format - match format { - ConfigFormat::Yaml => serde_yaml::from_str(&contents).unwrap_or_else(|e| { - eprintln!("Failed to parse YAML file {}: {}", path.display(), e); - Self::DataType::default() - }), - ConfigFormat::Toml => toml::from_str(&contents).unwrap_or_else(|e| { - eprintln!("Failed to parse TOML file {}: {}", path.display(), e); - Self::DataType::default() - }), - ConfigFormat::Ron => ron::from_str(&contents).unwrap_or_else(|e| { - eprintln!("Failed to parse RON file {}: {}", path.display(), e); - Self::DataType::default() - }), - ConfigFormat::Json => serde_json::from_str(&contents).unwrap_or_else(|e| { - eprintln!("Failed to parse JSON file {}: {}", path.display(), e); - Self::DataType::default() - }), - } - } - Err(_) => { - // Return default value when file doesn't exist - Self::DataType::default() - } + if !fs::metadata(&file_path).await.is_ok() { + return Ok(Self::DataType::default()); } + + // Open file + let mut file = fs::File::open(&file_path).await?; + + let mut contents = String::new(); + file.read_to_string(&mut contents).await?; + + // Determine file format + let format = file_path + .file_name() + .and_then(|name| name.to_str()) + .and_then(ConfigFormat::from_filename) + .unwrap_or(ConfigFormat::Json); // Default to JSON + + // Deserialize based on format + let result = match format { + ConfigFormat::Yaml => serde_yaml::from_str(&contents) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?, + ConfigFormat::Toml => toml::from_str(&contents) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?, + ConfigFormat::Ron => ron::from_str(&contents) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?, + ConfigFormat::Json => serde_json::from_str(&contents) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?, + }; + + Ok(result) } - async fn write(val: &Self::DataType) + async fn write(val: &Self::DataType) -> Result<(), std::io::Error> where Self: Sized + Send + Sync, { - let Ok(path) = Self::default_path() else { - return; - }; - - Self::write_to(val, path).await; + let path = Self::default_path()?; + Self::write_to(val, path).await } - async fn write_to(val: &Self::DataType, path: impl AsRef<Path> + Send) + async fn write_to( + val: &Self::DataType, + path: impl AsRef<Path> + Send, + ) -> Result<(), std::io::Error> where Self: Sized + Send + Sync, { @@ -136,16 +108,11 @@ pub trait ConfigFile: Serialize + for<'a> Deserialize<'a> + Default { if let Some(parent) = path.parent() && !parent.exists() { - let _ = tokio::fs::create_dir_all(parent).await; + tokio::fs::create_dir_all(parent).await?; } - let file_path = match current_dir() { - Ok(cwd) => cwd.join(path), - Err(e) => { - eprintln!("Failed to get current directory: {}", e); - return; - } - }; + let cwd = current_dir()?; + let file_path = cwd.join(path); // Determine file format let format = file_path @@ -155,43 +122,25 @@ pub trait ConfigFile: Serialize + for<'a> Deserialize<'a> + Default { .unwrap_or(ConfigFormat::Json); // Default to JSON let contents = match format { - ConfigFormat::Yaml => serde_yaml::to_string(val).unwrap_or_else(|e| { - eprintln!("Failed to serialize to YAML: {}", e); - String::new() - }), - ConfigFormat::Toml => toml::to_string(val).unwrap_or_else(|e| { - eprintln!("Failed to serialize to TOML: {}", e); - String::new() - }), + ConfigFormat::Yaml => serde_yaml::to_string(val) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?, + ConfigFormat::Toml => toml::to_string(val) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?, ConfigFormat::Ron => { let mut pretty_config = ron::ser::PrettyConfig::new(); pretty_config.new_line = Cow::from("\n"); pretty_config.indentor = Cow::from(" "); - ron::ser::to_string_pretty(val, pretty_config).unwrap_or_else(|e| { - eprintln!("Failed to serialize to RON: {}", e); - String::new() - }) + ron::ser::to_string_pretty(val, pretty_config) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))? } - ConfigFormat::Json => serde_json::to_string(val).unwrap_or_else(|e| { - eprintln!("Failed to serialize to JSON: {}", e); - String::new() - }), + ConfigFormat::Json => serde_json::to_string(val) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?, }; - // Don't write if serialization failed - if contents.is_empty() { - eprintln!( - "Serialization failed for file {}, not writing", - path.display() - ); - return; - } - // Write to file - if let Err(e) = fs::write(&file_path, contents).await { - eprintln!("Failed to write file {}: {}", path.display(), e); - } + fs::write(&file_path, contents).await?; + Ok(()) } /// Check if the file returned by `default_path` exists |
