5个不稳定版本
0.11.1 | 2023年8月21日 |
---|---|
0.10.0 | 2023年7月31日 |
0.9.10 | 2022年7月14日 |
0.9.1 | 2019年11月29日 |
0.9.0 | 2019年9月18日 |
#458 in 数据库接口
39 每月下载次数
100KB
1.5K SLoC
- infos =
- infos/author = Philipp Gackstatter [email protected]
- infos/status = experimental maintained
- infos/provides =
- infos/description =
Rust对Elektra的绑定
Elektra作为一个通用的、安全的框架,用于访问全局、分层键数据库中的配置参数。
有关Elektra的更多信息,请访问网站。
构建
根据您如何安装libelektra,您应该使用不同的方式来获取绑定。如果您使用包管理器安装,您应该使用crates.io上的crates。如果您本地构建了libelektra,您应该使用在build
目录中构建的绑定。
包管理器
如果您通过包管理器安装了elektra,您应该使用elektra crate或者如果您需要原始绑定,则使用elektra-sys crate。在这种情况下,您将需要libelektra
本身以及用于绑定生成的开发头文件(通常称为libelektra-dev
)。在这种情况下,elektra-sys
以及elektra
crate都有一个名为pkg-config
的功能,您可以通过将其添加到依赖部分来启用以查找elektra的安装及其头文件。默认情况下,它没有被启用,但推荐启用,并且您可以通过添加以下内容来实现这一点:features = ["pkg-config"]
,如以下所示。然后需要安装pkg-config
实用工具。您的Cargo.toml依赖项可能如下所示:
[dependencies]
elektra = { version = "0.9.10", features = ["pkg-config"] }
# Directly depending on elektra-sys is only needed if you need to use the raw bindings
elektra-sys = { version = "0.9.10", features = ["pkg-config"] }
如果您不使用pkg-config
功能,构建脚本将在/usr/local/include/elektra
和/usr/include/elektra
中查找Elektra的安装。
设置好之后,当您运行cargo build
时,应该会构建绑定。
本地构建
要将绑定显式地作为Elektra构建过程的一部分构建,我们将选项rust
添加到-DBINDINGS
。现在构建libelektra,绑定将在构建过程中构建。
您的Cargo.toml依赖项可能如下所示
[dependencies]
elektra = { path = "../libelektra/build/src/bindings/rust/elektra/"}
示例
请注意,您的动态链接器必须能够找到libelektra-{core,meta,kdb}
。如果您刚刚编译了它,您可以从build
目录运行source ../scripts/dev/run_env
来适当地修改您的PATH
。
请参阅example
目录以获取完整设置的项目。要运行它,请将工作目录更改为build/src/bindings/rust/example/
,然后运行cargo run --bin key
。
要从头开始一个新的项目,使用cargo new elektra_rust
。现在将elektra
crate添加到依赖项。该crate位于您的build
目录的src/bindings/rust
子目录中,因此确切路径取决于您的系统。适当地更改路径(并可能更改版本),并将以下依赖项添加到您的Cargo.toml
中。
[dependencies]
elektra = { version = "0.9.10", path = "~/git/libelektra/build/src/bindings/rust/elektra" }
# Directly depending on elektra-sys is only needed if you need to use the raw bindings
elektra-sys = { version = "0.9.10", path = "~/git/libelektra/build/src/bindings/rust/elektra-sys" }
如果您运行cargo run
并且一切构建正确并打印出Hello, world!
,您可以将main.rs
的内容替换为下一节中显示的示例。
用法
键
使用 StringKey
的示例。在 example
目录下运行,使用以下命令:cargo run --bin key
。更多示例请参阅完整示例。
extern crate elektra;
use elektra::{ReadableKey, StringKey, WriteableKey};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// To create a simple key with a name and value
let mut key = StringKey::new("user:/test/language")?;
key.set_value("rust");
println!("Key with name {} has value {}", key.name(), key.value());
Ok(())
}
与 C-API 相比,存在两种不同的键类型,StringKey
和 BinaryKey
。使用它们,在 BinaryKey
上调用 keyString
等类型不匹配的情况是不可能的。它们之间的唯一区别是你可以从它们设置和获取的值的类型。它们只是 C-API 中的 Key
的包装。
使用 BinaryKey
设置任意字节数值。
extern crate elektra;
use elektra::{BinaryKey, ReadableKey, WriteableKey};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let binary_content: [u8; 7] = [25, 34, 0, 254, 1, 0, 7];
let mut key = BinaryKey::new("user:/test/rust")?;
key.set_value(&binary_content);
let read_content = key.value();
println!(
"Key with name {} holds bytes {:?}",
key.name(),
read_content
);
Ok(())
}
键的功能分为两个特质,ReadableKey
和 WritableKey
,分别定义了只从键中读取信息的方法和修改键的方法。例如,检索元键的方法只返回实现 ReadableKey
的键,它是 ReadOnly
包装中的一个键。
KeySet
KeySet 是一组 StringKey。
- 你可以使用
new
创建一个空键集,或者使用with_capacity
预分配一定数量的键的空间。 - 它有两个
Iterator
特质的实现,因此你可以以不可变或可变的方式迭代。
更多示例请参阅完整示例。在 example
目录下运行,使用以下命令:cargo run --bin keyset
。
extern crate elektra;
use elektra::{KeyBuilder, KeySet, ReadableKey, StringKey, keyset};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// keyset! works just like vec!
let keyset = keyset![
KeyBuilder::<StringKey>::new("user:/sw/app/#1/host")?
.value("localhost")
.build(),
KeyBuilder::<StringKey>::new("user:/sw/app/#1/port")?
.value("8080")
.build(),
];
// Iterate the keyset
for key in keyset.iter() {
println!("Key ({}, {})", key.name(), key.value());
}
Ok(())
}
KeySet
只包含 StringKey
,因为它们比 BinaryKey
更常见。然而,由于底层 KeySet 持有泛型 Key
,BinaryKey
也可能发生。您可以使用 From
特质在这两种键之间进行转换。这在内存方面是安全的,但如果将包含任意字节的 BinaryKey
转换为 StringKey
,则可能是非安全的。您可以使用 is_string
或 is_binary
来确定转换是否安全。
let mut key = StringKey::new("user:/test/language")?;
// Cast the StringKey to BinaryKey
let binary_key = BinaryKey::from(key);
// And cast it back
let string_key = StringKey::from(binary_key);
KDB
使用 KDB
结构可以访问键数据库。更多示例请参阅完整示例。在 example
目录下运行,使用以下命令:cargo run --bin kdb
。
KDB 错误类型是嵌套的,因此您可以在高级别或特定级别上进行匹配。您可能希望使用 kdb_error.is_validation()
匹配所有验证错误,这将包括语法和语义验证错误。有关错误类型的深入解释,请参阅错误指南。
extern crate elektra;
use elektra::{KeySet, StringKey, WriteableKey, KDB};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let contract = KeySet::with_capacity(0);
// Open a KDB session
let mut kdb = KDB::open(contract)?;
// Create a keyset that will hold the keys we get from the get call
let mut ks = KeySet::with_capacity(10);
// Get the current state of the key database
let mut parent_key = StringKey::new("user:/test")?;
let get_res = kdb.get(&mut ks, &mut parent_key);
if let Err(kdb_error) = get_res {
if kdb_error.is_validation() {
// Handle the validation error, which could be syntactic or semantic
// You could use is_semantic() or is_syntactic() to match further.
Ok(())
} else {
// Otherwise propagate the error up
Err(Box::new(kdb_error))
}
} else {
Ok(())
}
}
原始绑定
在 elektra
包中提供了安全包装,但您也可以直接使用来自 elektra_sys
的原始绑定。例如,Rust 不允许定义可变参数函数,但允许调用它们。因此,您可以像在 C 中一样调用 keyNew
。
extern crate elektra_sys;
use elektra_sys::{keyDel, keyName, keyNew, keyString, KEY_END, KEY_VALUE};
use std::ffi::{CStr, CString};
fn main() {
let key_name = CString::new("user:/test/key").unwrap();
let key_val = CString::new("rust-bindings").unwrap();
let key = unsafe { keyNew(key_name.as_ptr(), KEY_VALUE, key_val.as_ptr(), KEY_END) };
let name_str = unsafe { CStr::from_ptr(keyName(key)) };
let val_str = unsafe { CStr::from_ptr(keyString(key)) };
println!("Key with name {:?} has value {:?}", name_str, val_str);
assert_eq!(unsafe { keyDel(key) }, 0);
}
文档
对于 elektra 和 elektra-sys,文档会在 docs.rs
上自动构建。请注意,由于 elektra-sys
是 C API 的一对一翻译,它没有文档,您应该直接使用 C 文档。
您还可以在 build 目录的 src/bindings/rust/
子目录中构建文档,通过运行 cargo doc
并打开 target/doc/elektra/index.html
。
生成
在构建 elektra-sys
包时,使用 rust-bindgen
生成绑定。在 elektra-sys
包中的 build.rs
脚本会调用并配置 bindgen。它还会为 rustc
发出额外的配置,以告诉它链接哪个库以及在哪里找到它。Bindgen 预期一个 wrapper.h
文件,该文件包含所有应为其生成绑定的头文件。最后,bindgen 将绑定输出到一个文件中,然后将其包含在 elektra-sys/lib.rs
文件中,以便其他包可以使用。
故障排除
Rust-bindgen 需要 clang 生成绑定,因此如果您遇到以下错误,请确保已安装 clang(3.9 或更高版本)。
/usr/include/limits.h:123:16: fatal error: 'limits.h' file not found
/usr/include/limits.h:123:16: fatal error: 'limits.h' file not found, err: true
thread 'main' panicked at 'Unable to generate bindings: ()', src/libcore/result.rs:999:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
依赖关系
~0–2MB
~38K SLoC