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