diff options
Diffstat (limited to 'crates/utils')
| -rw-r--r-- | crates/utils/cfg_file/Cargo.toml | 1 | ||||
| -rw-r--r-- | crates/utils/cfg_file/cfg_file_test/src/lib.rs | 44 | ||||
| -rw-r--r-- | crates/utils/cfg_file/src/config.rs | 48 |
3 files changed, 80 insertions, 13 deletions
diff --git a/crates/utils/cfg_file/Cargo.toml b/crates/utils/cfg_file/Cargo.toml index 7c09892..0685329 100644 --- a/crates/utils/cfg_file/Cargo.toml +++ b/crates/utils/cfg_file/Cargo.toml @@ -20,3 +20,4 @@ serde_yaml = "0.9.34" serde_json = "1.0.145" ron = "0.11.0" toml = "0.9.8" +bincode2 = "2.0.1" 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 4db4c22..f70d00d 100644 --- a/crates/utils/cfg_file/cfg_file_test/src/lib.rs +++ b/crates/utils/cfg_file/cfg_file_test/src/lib.rs @@ -14,6 +14,15 @@ mod test_cfg_file { secret: HashMap<String, String>, } + #[derive(ConfigFile, Deserialize, Serialize, Default)] + #[cfg_file(path = "./.temp/example_bincode.bcfg")] + struct ExampleBincodeConfig { + name: String, + age: i32, + hobby: Vec<String>, + secret: HashMap<String, String>, + } + #[tokio::test] async fn test_config_file_serialization() { let mut example = ExampleConfig { @@ -48,4 +57,39 @@ mod test_cfg_file { assert_eq!(read_cfg.secret["No comments"], secret_no_comments); assert_eq!(read_cfg.secret["Peek"], secret_peek); } + + #[tokio::test] + async fn test_bincode_config_file_serialization() { + let mut example = ExampleBincodeConfig { + name: "Weicao".to_string(), + age: 22, + hobby: ["Programming", "Painting"] + .iter() + .map(|m| m.to_string()) + .collect(), + secret: HashMap::new(), + }; + let secret_no_comments = + "Actually, I'm really too lazy to write comments, documentation, and unit tests."; + example + .secret + .entry("No comments".to_string()) + .insert_entry(secret_no_comments.to_string()); + + let secret_peek = "Of course, it's peeking at you who's reading the source code."; + example + .secret + .entry("Peek".to_string()) + .insert_entry(secret_peek.to_string()); + + ExampleBincodeConfig::write(&example).await.unwrap(); // Write to default path. + + // Read from default path. + let read_cfg = ExampleBincodeConfig::read().await.unwrap(); + assert_eq!(read_cfg.name, "Weicao"); + assert_eq!(read_cfg.age, 22); + assert_eq!(read_cfg.hobby, vec!["Programming", "Painting"]); + assert_eq!(read_cfg.secret["No comments"], secret_no_comments); + assert_eq!(read_cfg.secret["Peek"], secret_peek); + } } diff --git a/crates/utils/cfg_file/src/config.rs b/crates/utils/cfg_file/src/config.rs index a38da9a..8f9edc9 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 bincode2; use ron; use serde::{Deserialize, Serialize}; use std::{ @@ -15,6 +16,7 @@ enum ConfigFormat { Toml, Ron, Json, + Bincode, } impl ConfigFormat { @@ -27,6 +29,8 @@ impl ConfigFormat { Some(Self::Ron) } else if filename.ends_with(".json") { Some(Self::Json) + } else if filename.ends_with(".bcfg") { + Some(Self::Bincode) } else { None } @@ -134,6 +138,12 @@ pub trait ConfigFile: Serialize + for<'a> Deserialize<'a> + Default { .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))?, + ConfigFormat::Bincode => { + // For Bincode, we need to read the file as bytes + let bytes = fs::read(&file_path).await?; + bincode2::deserialize(&bytes) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))? + } }; Ok(result) @@ -192,25 +202,37 @@ pub trait ConfigFile: Serialize + for<'a> Deserialize<'a> + Default { .and_then(ConfigFormat::from_filename) .unwrap_or(ConfigFormat::Json); // Default to JSON - let contents = match format { - 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))?, + match format { + ConfigFormat::Yaml => { + let contents = serde_yaml::to_string(val) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; + fs::write(&file_path, contents).await? + } + ConfigFormat::Toml => { + let contents = toml::to_string(val) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; + fs::write(&file_path, contents).await? + } 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) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))? + let contents = ron::ser::to_string_pretty(val, pretty_config) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; + fs::write(&file_path, contents).await? } - ConfigFormat::Json => serde_json::to_string(val) - .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?, - }; - - // Write to file - fs::write(&file_path, contents).await?; + ConfigFormat::Json => { + let contents = serde_json::to_string(val) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; + fs::write(&file_path, contents).await? + } + ConfigFormat::Bincode => { + let bytes = bincode2::serialize(val) + .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?; + fs::write(&file_path, bytes).await? + } + } Ok(()) } |
