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