Expand description
§flashdb-rs
这是一个为 FlashDB 编写的安全、高性能的 Rust 绑定库。FlashDB 是一款专注于嵌入式产品的超轻量级数据库。
本库旨在为 Rust 开发者提供一个安全且符合人体工程学的接口,以便在 Rust 项目中(包括 no_std 环境)无缝使用 FlashDB 强大的键值(KV)和时序(TSDB)存储功能,而无需直接编写 unsafe 的 C 代码。
§原始库介绍
FlashDB 是一款超轻量级的嵌入式数据库,专注于提供嵌入式产品的数据存储方案。FlashDB 不仅支持传统的基于文件系统的数据库模式,而且结合了 Flash 的特性,具有较强的性能及可靠性,并在保证极低的资源占用前提下,尽可能延长 Flash 使用寿命。
它提供两种数据库模式:
- 键值数据库 (KVDB):将数据存储为键值对集合,操作简洁,可扩展性强。
- 时序数据库 (TSDB):将数据按照时间顺序存储,适用于日志记录、传感器数据等场景,具有高性能的插入和查询能力。
§flashdb-rs 的特性
- 内存安全保证:通过 Rust 的所有权和生命周期管理,将底层的 C 库接口封装在安全的 API 之后。
- 符合人体工程学的 API:提供
Result进行错误处理,并为数据访问提供了流式读取器(Reader)和迭代器(Iterator)。 - 灵活的存储后端:通过
embedded_storage::nor_flash::NorFlashtrait 将存储层完全抽象。您可以为任何 Flash 硬件(内部 Flash、QSPI、SPI Nor/NAND 等)实现自己的存储后端。 - 内置文件系统支持:在
std环境下,提供开箱即用的文件存储后端(StdStorage),方便在桌面环境进行开发和测试。 no_std兼容:专为嵌入式和裸机环境设计,只需实现NorFlashtrait 即可在不同平台上运行。- 特性控制(Feature Gates):您可以根据需要仅启用
kvdb或tsdb功能,最大限度地减少固件体积。
§快速上手
§1. 添加依赖
将以下内容添加到您的 Cargo.toml 中:
[dependencies]
flashdb-rs = { version = "0.2.1", features = ["kvdb", "tsdb", "std", "time64"] }
# 用于桌面测试
anyhow = "1.0"
tempfile = "3.4.0"§2. KVDB (键值数据库) 示例
use flashdb_rs::KVDB;
use std::ffi::CStr;
use tempfile::tempdir;
fn main() -> anyhow::Result<()> {
// 1. 创建一个临时目录用于存储数据库文件
let temp_dir = tempdir()?;
let db_path = temp_dir.path().to_str().unwrap();
// 2. 使用 `new_file` 创建数据库实例。
// 它返回一个 `Box` 以确保其内存地址稳定,防止悬空指针。
let mut db = KVDB::new_file(
"kv_db",
db_path,
4096, // sec_size
128 * 1024, // max_size
None, // default_kvs
)?;
// 3. 设置键值对
let key = "boot_count"; // 直接使用 &str,更简洁
let value = b"10";
db.set(key, value)?;
println!("Set '{}' = '{}'", key, std::str::from_utf8(value)?);
// 4. 获取键值对
if let Some(retrieved_value) = db.get(key)? {
let value_str = std::str::from_utf8(&retrieved_value)?;
println!("Get '{}' = '{}'", key, value_str);
assert_eq!(value_str.as_bytes(), value);
}
// 5. 迭代所有键值对
println!("\nIterating all KVs:");
for entry in db.iter() {
// entry 是一个 KVEntry
if let Some(name) = entry.name() {
println!("- Found key: '{}', value_len: {}", name, entry.value_len());
}
}
Ok(())
}§3. TSDB (时序数据库) 示例
use flashdb_rs::tsdb::TSDB;
use tempfile::tempdir;
fn main() -> anyhow::Result<()> {
// 1. 创建临时目录
let temp_dir = tempdir()?;
let db_path = temp_dir.path().to_str().unwrap();
// 2. 使用 `new_file` 创建 TSDB 实例
let mut tsdb = TSDB::new_file(
"ts_db",
db_path,
4096, // sec_size
128 * 1024, // max_size
1024, // 单条日志最大长度
)?;
// 3. 追加带时间戳的日志
let timestamp1 = 1686451200; // Unix aarch
let data1 = b"log entry 1: system started";
tsdb.append_with_timestamp(timestamp1, data1)?;
println!("Appended log at timestamp {}", timestamp1);
let timestamp2 = 1686451260;
let data2 = b"log entry 2: sensor reading OK";
tsdb.append_with_timestamp(timestamp2, data2)?;
println!("Appended log at timestamp {}", timestamp2);
// 4. 按时间范围迭代日志 (通过回调)
println!("\nIterating logs from {} to {}:", timestamp1, timestamp2);
tsdb.tsdb_iter_by_time(timestamp1, timestamp2, |db, tsl| {
if let Ok(Some(value)) = db.get_value(tsl) {
println!(
" - Time: {}, Data: '{}'",
tsl.time(), // 使用 .time() 方法
std::str::from_utf8(&value).unwrap()
);
}
true // 返回 true 继续迭代
});
Ok(())
}§在嵌入式 (no_std) 环境中使用
-
修改
Cargo.toml: 禁用默认的std特性,并根据需要启用kvdb或tsdb。[dependencies] flashdb-rs = { version = "0.2.1", default-features = false, features = ["kvdb", "time64"] } -
实现
NorFlashTrait: 您需要为您目标平台的 Flash 存储器(例如 STM32 的内部 Flash 或 ESP32 的 SPI Flash)实现embedded_storage::nor_flash::NorFlashtrait。// 伪代码示例 // 您需要为您的硬件实现这些 Trait -
初始化数据库: 在
no_std环境下,您需要手动创建存储实例,然后创建KVDB或TSDB实例,最后调用.init()方法。use flashdb_rs::KVDB; use core::ffi::CStr; fn my_embedded_main() { let my_flash_storage = MyHardwareFlash; // 1. 创建您的存储实例 // 2. 创建数据库实例 let mut db = KVDB::new(my_flash_storage); // 3. 在使用前必须调用 init() db.set_name("config").unwrap(); // (可选, 用于日志) db.init(None).expect("Failed to initialize db"); // 4. 现在可以正常使用 db let key = CStr::from_bytes_with_nul(b"wifi_ssid\0").unwrap(); db.set(key, b"MyNetwork").unwrap(); }
§许可证
本项目采用 Apache-2.0 开源协议。
§致谢
- 感谢 armink 开发了如此出色的
FlashDBC 库。 - 本项目依赖于原始的 FlashDB 仓库。
Re-exports§
pub use storage::StdStorage;pub use self::fdb_kv_status as fdb_kv_status_t;pub use self::fdb_tsl_status as fdb_tsl_status_t;pub use self::fdb_sector_store_status as fdb_sector_store_status_t;pub use self::fdb_sector_dirty_status as fdb_sector_dirty_status_t;pub use error::*;pub use kvdb::*;pub use tsdb::*;pub use utils::*;
Modules§
Macros§
- define_
default_ kvs - 在编译时定义一组默认的键值对。
Structs§
- Sync
Wrapper - fdb_
blob - fdb_
blob__ bindgen_ ty_ 1 - fdb_db
- fdb_
db__ bindgen_ ty_ 1 - fdb_
default_ kv - fdb_
default_ kv_ node - fdb_kv
- fdb_
kv__ bindgen_ ty_ 1 - fdb_
kv_ iterator - fdb_
kvdb - fdb_
tsdb - fdb_tsl
- fdb_
tsl__ bindgen_ ty_ 1 - kv_
cache_ node - kvdb_
sec_ info - kvdb_
sec_ info__ bindgen_ ty_ 1 - tsdb_
sec_ info
Constants§
- FDB_
FILE_ CACHE_ TABLE_ SIZE - FDB_
KVDB_ CTRL_ GET_ SEC_ SIZE - FDB_
KVDB_ CTRL_ SET_ FILE_ MODE - FDB_
KVDB_ CTRL_ SET_ LOCK - FDB_
KVDB_ CTRL_ SET_ MAX_ SIZE - FDB_
KVDB_ CTRL_ SET_ NOT_ FORMAT - FDB_
KVDB_ CTRL_ SET_ SEC_ SIZE - FDB_
KVDB_ CTRL_ SET_ UNLOCK - FDB_
KV_ CACHE_ TABLE_ SIZE - FDB_
KV_ NAME_ MAX - FDB_
KV_ STATUS_ NUM - FDB_
SECTOR_ CACHE_ TABLE_ SIZE - FDB_
SECTOR_ DIRTY_ STATUS_ NUM - FDB_
SECTOR_ STORE_ STATUS_ NUM - FDB_
SW_ VERSION - FDB_
SW_ VERSION_ NUM - FDB_
TSDB_ CTRL_ GET_ LAST_ TIME - FDB_
TSDB_ CTRL_ GET_ ROLLOVER - FDB_
TSDB_ CTRL_ GET_ SEC_ SIZE - FDB_
TSDB_ CTRL_ SET_ FILE_ MODE - FDB_
TSDB_ CTRL_ SET_ LOCK - FDB_
TSDB_ CTRL_ SET_ MAX_ SIZE - FDB_
TSDB_ CTRL_ SET_ NOT_ FORMAT - FDB_
TSDB_ CTRL_ SET_ ROLLOVER - FDB_
TSDB_ CTRL_ SET_ SEC_ SIZE - FDB_
TSDB_ CTRL_ SET_ UNLOCK - FDB_
TSL_ STATUS_ NUM - FDB_
WRITE_ GRAN - fdb_
db_ type_ FDB_ DB_ TYPE_ KV - fdb_
db_ type_ FDB_ DB_ TYPE_ TS - fdb_
err_ t_ FDB_ ERASE_ ERR - fdb_
err_ t_ FDB_ INIT_ FAILED - fdb_
err_ t_ FDB_ KV_ NAME_ ERR - fdb_
err_ t_ FDB_ KV_ NAME_ EXIST - fdb_
err_ t_ FDB_ NO_ ERR - fdb_
err_ t_ FDB_ PART_ NOT_ FOUND - fdb_
err_ t_ FDB_ READ_ ERR - fdb_
err_ t_ FDB_ SAVED_ FULL - fdb_
err_ t_ FDB_ WRITE_ ERR - fdb_
kv_ status_ FDB_ KV_ DELETED - fdb_
kv_ status_ FDB_ KV_ ERR_ HDR - fdb_
kv_ status_ FDB_ KV_ PRE_ DELETE - fdb_
kv_ status_ FDB_ KV_ PRE_ WRITE - fdb_
kv_ status_ FDB_ KV_ UNUSED - fdb_
kv_ status_ FDB_ KV_ WRITE - fdb_
sector_ dirty_ status_ FDB_ SECTOR_ DIRTY_ FALSE - fdb_
sector_ dirty_ status_ FDB_ SECTOR_ DIRTY_ GC - fdb_
sector_ dirty_ status_ FDB_ SECTOR_ DIRTY_ TRUE - fdb_
sector_ dirty_ status_ FDB_ SECTOR_ DIRTY_ UNUSED - fdb_
sector_ store_ status_ FDB_ SECTOR_ STORE_ EMPTY - fdb_
sector_ store_ status_ FDB_ SECTOR_ STORE_ FULL - fdb_
sector_ store_ status_ FDB_ SECTOR_ STORE_ UNUSED - fdb_
sector_ store_ status_ FDB_ SECTOR_ STORE_ USING - fdb_
storage_ type_ FDB_ STORAGE_ CUSTOM - fdb_
storage_ type_ FDB_ STORAGE_ FAL - fdb_
storage_ type_ FDB_ STORAGE_ FILE - fdb_
tsl_ status_ FDB_ TSL_ DELETED - fdb_
tsl_ status_ FDB_ TSL_ PRE_ WRITE - fdb_
tsl_ status_ FDB_ TSL_ UNUSED - fdb_
tsl_ status_ FDB_ TSL_ USER_ STATU S1 - fdb_
tsl_ status_ FDB_ TSL_ USER_ STATU S2 - fdb_
tsl_ status_ FDB_ TSL_ WRITE
Traits§
Functions§
- fdb_
blob_ ⚠make - fdb_
blob_ ⚠read - fdb_
calc_ ⚠crc32 - fdb_
custom_ ⚠erase - fdb_
custom_ ⚠read - fdb_
custom_ ⚠write - fdb_
kv_ ⚠del - fdb_
kv_ ⚠get - fdb_
kv_ ⚠get_ blob - fdb_
kv_ ⚠get_ obj - fdb_
kv_ ⚠iterate - fdb_
kv_ ⚠iterator_ init - fdb_
kv_ ⚠print - fdb_
kv_ ⚠set - fdb_
kv_ ⚠set_ blob - fdb_
kv_ ⚠set_ default - fdb_
kv_ ⚠to_ blob - fdb_
kvdb_ ⚠check - fdb_
kvdb_ ⚠control - fdb_
kvdb_ ⚠deinit - fdb_
kvdb_ ⚠init - fdb_
tsdb_ ⚠control - fdb_
tsdb_ ⚠deinit - fdb_
tsdb_ ⚠init - fdb_
tsl_ ⚠append - fdb_
tsl_ ⚠append_ with_ ts - fdb_
tsl_ ⚠clean - fdb_
tsl_ ⚠iter - fdb_
tsl_ ⚠iter_ by_ time - fdb_
tsl_ ⚠iter_ reverse - fdb_
tsl_ ⚠query_ count - fdb_
tsl_ ⚠set_ status - fdb_
tsl_ ⚠to_ blob - rust_
log