1 个不稳定版本
0.1.0 | 2024年1月31日 |
---|
#959 在 编码
8KB
Perstruct
perstruct
是一个crate,它提供了一个宏,将Rust结构体转换为设置结构体。它简化了将结构体字段作为键值对加载和保存的过程。这对于应用程序设置或配置非常有用,其中每个设置都可以单独更新和持久化。
这种方法相对于整个结构体的序列化和反序列化具有显著优势,特别是在应用程序配置或用户偏好需要灵活性和对变化的弹性时。
字段值以json格式序列化。未来可能会支持其他格式。
以下是一个示例,演示如何使用 perstruct
宏来管理应用程序中的用户引用
use perstruct::perstruct;
// Define a struct for user preferences.
// Apply the `perstruct` macro to enable key/value storage capabilities.
#[perstruct]
struct UserPreferences {
// Define user preferences with custom keys for storage.
pub ui_theme: UiTheme, // key is the same as the field name by default
#[perstruct(key = "notifications_enabled")] // key can be overridden
#[perstruct(default = true)] // default value can be specified
pub enable_notifications: bool,
// Use `perstruct(default_fn = "default_language")` to specify a function that returns default value.
#[perstruct(default_fn = "default_language")]
pub language: String,
// Use `perstruct(skip)` to exclude fields from being persisted.
#[perstruct(skip)]
pub cache: std::collections::HashMap<String, String>
}
#[derive(serde_derive::Serialize, serde_derive::Deserialize, Default, Debug, PartialEq)]
pub enum UiTheme {
#[default]
Dark,
Light
}
fn default_language() -> String { "en".to_string() }
// Simulate loading preferences from a key-value store (like a database or config file).
// These might be values previously saved by the user.
let kv_store_simulation = vec![
("ui_theme", "\"Dark\""),
("notifications_enabled", "true"),
].into_iter().collect();
let result = UserPreferences::from_map(&kv_store_simulation);
// Access the loaded preferences, handle deserialization errors or unknown fields.
let mut preferences = result.value;
assert_eq!(preferences.ui_theme(), &UiTheme::Dark);
assert_eq!(preferences.enable_notifications(), true);
assert_eq!(preferences.language(), "en");
assert_eq!(result.deserialization_errors, vec![]);
assert!(result.unknown_fields.is_empty());
// Modify preferences using the auto-generated setters.
preferences.set_ui_theme(UiTheme::Light);
preferences.set_enable_notifications(false);
// Retrieve changes (dirty fields) to persist them.
let mut changes = preferences.perstruct_get_changes().unwrap();
changes.sort_by_key(|(k, _)| *k);
assert_eq!(
changes,
vec![
("language", "\"en\"".to_string()), // language was not loaded but defaulted to "en", so it should be included in the changes
("notifications_enabled", "false".to_string()),
("ui_theme", "\"Light\"".to_string()),
]
);
// Simulate saving the changes to the kv store.
// ...
// Mark changes as saved using `perstruct_saved`.
preferences.perstruct_saved();
// Verify that there are no unsaved changes.
assert_eq!(preferences.perstruct_get_changes().unwrap(), vec![]);
限制
perstruct
宏只能应用于满足以下要求的结构体
- 所有非跳过的字段类型都必须实现
serde::Serialize
和serde::Deserialize
。 - 所有非跳过的字段都必须实现
Default
或使用 perstruct(default = ...) 或 #[perstruct(default_fn = "...")] 指定默认值。
依赖项
~0.7–1.6MB
~34K SLoC