#preferences #data #read-write #user #persistent #storage #replace

preferences-serde1

读取和写入特定用户的应用数据

1个稳定版本

使用旧的Rust 2015

2.0.0 2023年10月30日

#1816编码

Download history 192/week @ 2024-03-13 154/week @ 2024-03-20 205/week @ 2024-03-27 178/week @ 2024-04-03 262/week @ 2024-04-10 313/week @ 2024-04-17 109/week @ 2024-04-24 184/week @ 2024-05-01 80/week @ 2024-05-08 88/week @ 2024-05-15 88/week @ 2024-05-22 200/week @ 2024-05-29 68/week @ 2024-06-05 165/week @ 2024-06-12 81/week @ 2024-06-19 66/week @ 2024-06-26

389 每月下载量

MIT 许可证

19KB
171

preferences-serde1

在Rust中读取和写入特定用户的应用数据

这是旧版 preferences 包的替代品,用于使用 serde 版本 1.0。要更新以前看起来像这样的 Cargo.toml

preferences = "1.1"

使用这个

preferences = {version="2.0.0", package = "preferences-serde1"}

lib.rs:

读取和写入特定用户的应用数据

该库允许Rust开发者以灵活且适合平台的方式存储和检索用户本地首选项和其他应用数据。

虽然最初是受Java方便的 Preferences API 的启发,但这个库更加灵活。 任何 实现 serdeSerializeDeserialize 特性的结构体或枚举都可以作为用户数据存储和检索。实现这些特性很简单;只需包含库 serde_derive (别忘了 #[macro_use]!) 并在结构体定义中添加 #[derive(Serialize, Deserialize) 即可。(见下例。)

用法

为了方便,提供了类型 PreferencesMap<T>。实际上,它只是 std::collections::HashMap<String, T>,其中 T 默认为 String)。这反映了Java API,它将用户数据建模为不透明的键值存储。只要 T 可序列化和反序列化,Preferences 就会为您的映射实例实现。这允许您通过 Preferences 中的 save(..)load(..) 特性方法无缝地保存和加载用户数据。

基本示例

extern crate preferences_serde1 as preferences;
use preferences::{AppInfo, PreferencesMap, Preferences};

const APP_INFO: AppInfo = AppInfo{name: "preferences", author: "Rust language community"};

fn main() {

    // Create a new preferences key-value map
    // (Under the hood: HashMap<String, String>)
    let mut faves: PreferencesMap<String> = PreferencesMap::new();

    // Edit the preferences (std::collections::HashMap)
    faves.insert("color".into(), "blue".into());
    faves.insert("programming language".into(), "Rust".into());

    // Store the user's preferences
    let prefs_key = "tests/docs/basic-example";
    let save_result = faves.save(&APP_INFO, prefs_key);
    assert!(save_result.is_ok());

    // ... Then do some stuff ...

    // Retrieve the user's preferences
    let load_result = PreferencesMap::<String>::load(&APP_INFO, prefs_key);
    assert!(load_result.is_ok());
    assert_eq!(load_result.unwrap(), faves);

}

使用自定义数据类型

#[macro_use]
extern crate serde_derive;
extern crate preferences_serde1 as preferences;
use preferences::{AppInfo, Preferences};

const APP_INFO: AppInfo = AppInfo{name: "preferences", author: "Rust language community"};

// Deriving `Serialize` and `Deserialize` on a struct/enum automatically implements
// the `Preferences` trait.
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct PlayerData {
    level: u32,
    health: f32,
}

fn main() {

    let player = PlayerData{level: 2, health: 0.75};

    let prefs_key = "tests/docs/custom-types";
    let save_result = player.save(&APP_INFO, prefs_key);
    assert!(save_result.is_ok());

    // Method `load` is from trait `Preferences`.
    let load_result = PlayerData::load(&APP_INFO, prefs_key);
    assert!(load_result.is_ok());
    assert_eq!(load_result.unwrap(), player);

}

使用自定义数据类型与 PreferencesMap 结合

#[macro_use]
extern crate serde_derive;
extern crate preferences_serde1 as preferences;
use preferences::{AppInfo, PreferencesMap, Preferences};

const APP_INFO: AppInfo = AppInfo{name: "preferences", author: "Rust language community"};

#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Point(f32, f32);

fn main() {

    let mut places = PreferencesMap::new();
    places.insert("treasure".into(), Point(1.0, 1.0));
    places.insert("home".into(), Point(-1.0, 6.6));

    let prefs_key = "tests/docs/custom-types-with-preferences-map";
    let save_result = places.save(&APP_INFO, prefs_key);
    assert!(save_result.is_ok());

    let load_result = PreferencesMap::load(&APP_INFO, prefs_key);
    assert!(load_result.is_ok());
    assert_eq!(load_result.unwrap(), places);

}

使用自定义数据类型与可序列化容器结合

#[macro_use]
extern crate serde_derive;
extern crate preferences_serde1 as preferences;
use preferences::{AppInfo, Preferences};

const APP_INFO: AppInfo = AppInfo{name: "preferences", author: "Rust language community"};

#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Point(usize, usize);

fn main() {

    let square = vec![
        Point(0,0),
        Point(1,0),
        Point(1,1),
        Point(0,1),
    ];

    let prefs_key = "tests/docs/custom-types-in-containers";
    let save_result = square.save(&APP_INFO, prefs_key);
    assert!(save_result.is_ok());

    let load_result = Vec::<Point>::load(&APP_INFO, prefs_key);
    assert!(load_result.is_ok());
    assert_eq!(load_result.unwrap(), square);

}

内部原理

数据被写入活动用户的家目录下的扁平文件中,该位置由操作系统特定。这个位置由 directories 包的 config_dir() 函数决定。在数据目录内,文件存储在一个文件夹层次结构中,该结构映射到传递给 save(..) 的偏好键的净化版本。

数据以JSON格式存储。这有几个优点

  • 人类可读且自描述
  • 比例如XML更紧凑
  • 比例如TOML的采用率和语言兼容性更好
  • 不依赖于例如二进制的一致内存布局

当然,您可以自己实现 Preferences 并将您的用户数据存储在您想要的任何位置和格式中。但这将违背这个库的目的。😊

依赖项

~0.4–1.2MB
~21K SLoC