4 个版本 (2 个重大更改)

新增 0.3.0 2024 年 8 月 13 日
0.2.2 2024 年 8 月 11 日
0.2.0 2024 年 8 月 10 日
0.1.0 2024 年 8 月 7 日

#953Rust 模式

Download history 109/week @ 2024-08-03 351/week @ 2024-08-10

每月 460 次下载
用于 2 crates

MIT/Apache

3KB

Redb 模型

用于生成 redb 表定义和 DTO 对象转换方法/实现的 derive 宏。

功能

该软件包旨在统一数据库条目 DTO 定义和 redb::TableDefinition。通过使用 #[derive(Model)] 装饰结构体,将为该类型实现 Model,定义 redb::TableDefinition 作为关联常量,并生成辅助方法。

示例


#[derive(Model)]
struct User {
    #[entry(position(key))]
    id: u32,
    #[entry(position(value))]
    name: String,
    #[entry(position(value))]
    email: String,
}

let user = User {
    id: 0,
    name: "User".to_owned(),
    email: "[email protected]".to_owned(),
};

let txn = db.begin_write().unwrap();
{
    let mut table = txn.open_table(User::DEFINITION).unwrap();
    let (k, v) = user.as_values();
    table.insert(k, v).unwrap();
}
txn.commit().unwrap();

指定键和值

键和值通过使用 #[entry(position(...))] 装饰表字段进行指定,将 keyvalue 传递给内部字段。复合键/值将组合成一个元组。

#[derive(Model)]
struct User {
    #[entry(position(key))]
    uuid: [u8; 16],
    #[entry(position(value))]
    username: String,
    #[entry(position(value))]
    email: String,
}

let user_key = [0; 16];
let user_value = ("my_name".to_string(), "[email protected]".to_string());

let user = User::from_values((user_key, user_value));
let (k, v) = user.into_values();

// Only the value is a tuple for this model.
assert_eq!(k, [0; 16]);
assert_eq!(v, ("my_name".to_string(), "[email protected]".to_string()));

指定表名

默认情况下,表名与结构体名称相同(区分大小写)。这可以通过使用 #[model(name = "...")] 属性覆盖。

#[derive(Model)]
#[model(name = "user_table")]
struct User {
    #[entry(position(key))]
    uuid: [u8; 16],
    #[entry(position(value))]
    username: String,
}

assert_eq!(User::DEFINITION.name(), "user_table");

类型转换

生成的Model特质的实现提供了实例化、借用和获取模型DTO中的键/值对的方法。使用#[model(impl_from)]装饰结构体将进一步实现From<T>,将T映射到from_values(T)from_guards(T)方法。

#[derive(Model)]
#[model(impl_from)]
struct User {
    #[entry(position(key))]
    uuid: [u8; 16],
    #[entry(position(value))]
    username: String,
    #[entry(position(value))]
    email: String,
}

let user_key = [0; 16];
let user_value = ("my_name".to_string(), "[email protected]".to_string());

let user: User = ((user_key, user_value)).into();

实现细节

以下是一些关于实现的通用说明。

String表定义

redb_model将使用&str替换String用于表定义。这样,复合(元组)变量可以在不解构DTO的情况下被借用和传递给数据库处理器。使用String目前是不可能的。

const TABLE: TableDefinition<(String, String), ()> = TableDefinition::new("table");

let string_0 = "string_0".to_string();
let string_1 = "string_1".to_string();

let txn = db.begin_write().unwrap();
let mut table = txn.open_table(TABLE).unwrap();
// This doesn't work.
table.insert((&string_0, &string_1), ());
// Neither does this.
table.insert((string_0.as_str(), string_1.as_str()), ());
```rust

### Unit type values

The unit type `()` must be passed if no value is defined.
```rust
#[derive(Model)]
#[model(name = "outbound_edge")]
struct Edge {
    #[entry(position(key))]
    source: [u8; 16],
    #[entry(position(key))]
    target: [u8; 16],
}
let k = ([0; 16], [1; 16]);
let v = ();
let e = Edge::from_values((k, v));

变量顺序

所有复合键/值变量都按照定义的顺序组合为一个元组。这是预期的,但如果有必要,可以进行更改。

Model定义和redb::TableDefinition

redb::TableDefinition使用'static引用在Model中定义的类型,除了String,它使用一个'static字符串切片。这是为了确保调用as_values返回适合数据库调用的引用。

许可证:MIT OR Apache-2.0

依赖项

~645KB
~16K SLoC