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

preferences-ron

使用RON格式读取和写入特定用户的应用数据

2个稳定版本

使用旧Rust 2015

2.0.1 2021年6月19日
2.0.0 2021年6月16日

#1995编码

MIT许可证

21KB
187

preferences-ron

RON格式中读取和写入特定用户的Rust应用数据。

RON代表Rusty Object Notation,看起来与JSON相似,但完全编码了Rust类型信息。

这个包是基于preferences-rs的一个分支,它使用JSON。不幸的是,某些应用程序数据结构无法用JSON编写。特别是那些使用struct作为map键的。此外,该库自2017年以来似乎没有维护,并且还不支持Serde 1.0+。因此创建了这个分支。

文档

https://docs.rs/preferences-ron

安装

$ cargo add preferences-ron

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 就会为你实现映射实例。这允许你通过 Preferencessave(..)load(..) 特性方法无缝地保存和加载用户数据。

基本示例

extern crate preferences_ron;
use preferences_ron::{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_ron;
use preferences_ron::{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_ron;
use preferences_ron::{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_ron;
use preferences_ron::{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);

}

内部机制

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

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

  • 可读性高,自我描述
  • 比例如 XML 更紧凑
  • 比例如 TOML 的采用率更高,语言兼容性更好
  • 不像例如二进制那样依赖于一致的内存布局

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

依赖项

~1–13MB
~99K SLoC