15个版本
| 0.3.7 | 2024年8月9日 |
|---|---|
| 0.3.6 | 2024年6月14日 |
| 0.3.5 | 2024年5月27日 |
| 0.3.3 | 2023年11月21日 |
| 0.1.0 | 2022年11月17日 |
#265 in 编码
每月401次下载
在 5 个crate中(直接使用4个) 使用
62KB
1.5K SLoC
serde_columnar
serde_columnar是一个舒适列式存储编码crate,提供前后兼容性。
它允许需要序列化和反序列化的内容通过列式存储编码为二进制,只需使用简单的宏注释即可。
有关更详细的介绍,请参阅此Notion链接:Serde-Columnar。
🚧 此crate正在开发中,尚不稳定,不应在生产环境中使用
特性 🚀
serde_columnar具有几个显著特性
- 🗜️ 结合各种压缩策略使用列式存储,显著减少编码内容的体积。
- 🔄 内置前后兼容解决方案,无需维护额外的版本代码。
- 🌳 支持嵌套列式存储。
- 📦 支持列表和映射容器
- 🔄 支持使用迭代器格式进行反序列化。
如何使用
安装
cargo add serde_columnar
或编辑您的Cargo.toml并将serde_columnar作为依赖项添加
[dependencies]
serde_columnar = "0.3.4"
容器属性
vec:map:ser:- 自动为该结构体推导
Serialize特性
- 自动为该结构体推导
de:- 自动为该结构体推导
Deserialize特性
- 自动为该结构体推导
iterable:- 声明该结构体可迭代
- 仅适用于
row结构体 - 可迭代 了解更多详情
字段属性
strategy:- 应用于该字段的列压缩策略。
- 可选值:
Rle/DeltaRle/BoolRle。 - 仅适用于
row结构体。
class:- 声明该字段是行容器。字段类型通常是
Vec或HashMap及其变体。 - 可选值:
vec或map。 - 仅适用于
table结构体。
- 声明该字段是行容器。字段类型通常是
skip:- 与
#[serde(skip)]相同,不序列化或反序列化此字段。
- 与
borrow:- 与
#[serde(borrow)]相同,使用零拷贝反序列化从反序列化器借用数据。 - 使用
#[columnar(borrow="'a + 'b")]明确指定应该借用哪些生命周期。 - 目前仅适用于
table结构体。
- 与
iter:- 在以 iter 模式反序列化时声明可迭代行类型。
- 仅适用于标记为
class的字段。 - 仅适用于
class="vec"。
optional&index- 为了实现向前和向后兼容,一些可能发生变化的字段可以标记为
optional。 - 为了避免将来可能出现的错误,例如更改可选字段的顺序,需要标记
index。 - 所有
optional字段都必须在其他字段之后。 index是可选字段的唯一标识符,它将被编码到结果中。如果在反序列化期间找不到相应的标识符,则将使用Default。optional字段可以在未来版本中添加或删除。兼容性的前提是相同索引的字段类型没有改变或编码格式是兼容的(例如,将u32更改为u64)。
- 为了实现向前和向后兼容,一些可能发生变化的字段可以标记为
示例
use serde_columnar::{columnar, from_bytes, to_vec};
#[columnar(vec, ser, de)] // this struct can be a row of vec-like container
struct RowStruct {
name: String,
#[columnar(strategy = "DeltaRle")] // this field will be encoded by `DeltaRle`
id: u64,
#[columnar(strategy = "Rle")] // this field will be encoded by `Rle`
gender: String,
#[columnar(strategy = "BoolRle")] // this field will be encoded by `BoolRle`
married: bool
#[columnar(optional, index = 0)] // This field is optional, which means that this field can be added in this version or deleted in a future version
future: String
}
#[columnar(ser, de)] // derive `Serialize` and `Deserialize`
struct TableStruct<'a> {
#[columnar(class = "vec")] // this field is a vec-like table container
pub data: Vec<RowStruct>,
#[columnar(borrow)] // the same as `#[serde(borrow)]`
pub text: Cow<'a, str>
#[columnar(skip)] // the same as `#[serde(skip)]`
pub ignore: u8
#[columnar(optional, index = 0)] // table container also supports optional field
pub other_data: u64
}
let table = TableStruct::new(...);
let bytes = serde_columnar::to_vec(&table).unwrap();
let table_from_bytes = serde_columnar::from_bytes::<TableStruct>(&bytes).unwrap();
您可以在 examples 和 tests 中找到更多 serde_columnar 的示例。
可迭代
当我们在压缩编码中使用列模式时,有一个前提是字段是可迭代的。因此,在反序列化时,我们可以完全借用编码的字节以迭代器的形式获取所有数据,而无需直接分配所有数据的内存。这种实现也可以完全通过宏来完成。
在反序列化时使用iter模式,你只需要做3件事
- 使用
iterable标记所有行结构体 - 使用
iter="..."标记行容器的字段 - 使用
serde_columnar::iter_from_bytes进行反序列化
#[columnar(vec, ser, de, iterable)]
struct Row{
#[columnar(strategy="Rle")]
rle: String
#[columnar(strategy="DeltaRle")]
delta_rle: u64
other: u8
}
#[columnar(ser, de)]
struct Table{
#[columnar(class="vec", iter="Row")]
vec: Vec<Row>,
other: u8
}
let table = Table::new(...);
let bytes = serde_columnar::to_vec(&table).unwrap();
let table_iter = serde_columnar::iter_from_bytes::<Table>(&bytes).unwrap();
致谢
依赖项
~1.4–2.2MB
~46K SLoC