serde_columnar
serde_columnar is an ergonomic columnar storage encoding crate that offers forward and backward compatibility.
It allows the contents that need to be serialized and deserialized to be encoded into binary using columnar storage, all by just employing simple macro annotations.
For more detailed introduction, please refer to this Notion link: Serde-Columnar.
🚧 This crate is in progress and not stable, should not be used in production environments
Features 🚀
serde_columnar comes with several remarkable features:
- 🗜️ Utilizes columnar storage in conjunction with various compression strategies to significantly reduce the size of the encoded content.
- 🔄 Built-in forward and backward compatibility solutions, eliminating the need for maintaining additional version codes.
- 🌳 Supports nested columnar storage.
- 🗃️ Offers additional compression for each column.
- 📦 Supports list and map containers
How to use
Install
cargo add serde_columnar
Or edit your Cargo.toml and add serde_columnar as dependency:
[]
= "0.3.0"
Container Attribute
vec:map:ser:- Automatically derive
Serializetrait for this struct
- Automatically derive
de:- Automatically derive
Deserializetrait for this struct
- Automatically derive
Field Attribute
strategy:- The columnar compression strategy applied to this field.
- Optional value:
Rle/DeltaRle/BoolRle. - Only available for
rowstruct.
class:- Declare this field is a container for rows. The field's type is usually
VecorHashMapand their variants. - Optional value:
vecormap. - Only available for
tablestruct.
- Declare this field is a container for rows. The field's type is usually
skip:- Same as
#[serde(skip)], do not serialize or deserialize this field. - Only available for
tablestruct for now.
- Same as
borrow:- Same as
#[serde(borrow)], borrow data for this field from the deserializer by using zero-copy deserialization. - use
#[columnar(borrow="'a + 'b")]to specify explicitly which lifetimes should be borrowed. - Only available for
tablestruct for now.
- Same as
optional&index:- In order to achieve forward and backward compatibility, some fields that may change can be marked as
optional. - And in order to avoid the possibility of errors in the future, such as change the order of optional fields, it is necessary to mark the
index. - All
optionalfields must be after other fields. - The
indexis the unique identifier of the optional field, which will be encoded into the result. If the corresponding identifier cannot be found during deserialization,Defaultwill be used. optionalfields can be added or removed in future versions. The compatibility premise is that the field type of the same index does not change or the encoding format is compatible (such as changingu32tou64).
- In order to achieve forward and backward compatibility, some fields that may change can be marked as
compress:- This attribute needs to enable the
compressfeature - This attribute is whether compress the columnar encoded bytes by default settings of Deflate algorithm.
#[columnar(compress(min_size=N))]: compress the columnar encoded bytes when the size of the bytes is larger than N, default N is 256.#[columnar(compress(level=N))]: compress the columnar encoded bytes by Deflate algorithm with level N, N is in [0, 9], default N is 6, 0 is no compression, and 9 is the best compression. See flate2 for more details.#[columnar(compress(method="fast"|"best"|"default"))]: compress the columnar encoded bytes by Deflate algorithm with method "fast", "best" or "default", this attribute is equivalent to#[columnar(compress(level=1|9|6))].- Note:
levelandmethodcan not be used at the same time. - Only available for
rowstruct.
- This attribute needs to enable the
Examples
use ;
// this struct can be a row of vec-like container
// derive `Serialize` and `Deserialize`
let store = new;
let bytes = to_vec.unwrap;
let store_from_bytes = .unwrap;
You can find more examples of serde_columnar in examples and tests.
Acknowledgements
- serde: Serialization framework for Rust.
- postcard: Postcard is a #![no_std] focused serializer and deserializer for Serde. We use it as serializer and deserializer in order to provide VLE and ZigZag encoding.
- Automerge: Automerge is an excellent crdt framework, we reused the code related to RLE Encoding in it.