summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-01-02 23:17:26 +0800
committer魏曹先生 <1992414357@qq.com>2026-01-02 23:17:26 +0800
commit118f24df4024099b6fbdd6d74fca46ae089ac07a (patch)
tree62211f21987137d2f3e09ad489f3fc105a2d97db
parentba11b73da83d5f6c66129b52cff7a45d8994a6a0 (diff)
Add support for Bincode config file format
-rw-r--r--Cargo.lock11
-rw-r--r--crates/utils/cfg_file/Cargo.toml1
-rw-r--r--crates/utils/cfg_file/cfg_file_test/src/lib.rs44
-rw-r--r--crates/utils/cfg_file/src/config.rs48
4 files changed, 91 insertions, 13 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 17cd6a5..41087f2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -101,6 +101,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
[[package]]
+name = "bincode2"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f49f6183038e081170ebbbadee6678966c7d54728938a3e7de7f4e780770318f"
+dependencies = [
+ "byteorder",
+ "serde",
+]
+
+[[package]]
name = "bitflags"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -197,6 +207,7 @@ name = "cfg_file"
version = "0.1.0"
dependencies = [
"async-trait",
+ "bincode2",
"cfg_file_derive",
"ron",
"serde",
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(())
}