A concise storage format, written for [`BonsaiDb`](https://bonsaidb.io/). ![Pot forbids unsafe code](https://img.shields.io/badge/unsafe-forbid-success) [![crate version](https://img.shields.io/crates/v/pot.svg)](https://crates.io/crates/pot) [![Live Build Status](https://img.shields.io/github/actions/workflow/status/khonsulabs/pot/rust.yml?branch=main)](https://github.com/khonsulabs/pot/actions?query=workflow:Tests) [![HTML Coverage Report for `main` branch](https://khonsulabs.github.io/pot/coverage/badge.svg)](https://khonsulabs.github.io/pot/coverage/) [![Documentation for `main` branch](https://img.shields.io/badge/docs-main-informational)](https://khonsulabs.github.io/pot/main/pot/) Pot is an encoding format used within [`BonsaiDb`](https://bonsaidb.io/). Its purpose is to provide an encoding format for [`serde`](https://serde.rs) that: * Is self-describing. * Is safe to run in production. * Is compact. While still being self-describing, Pot's main space-saving feature is not repeating symbols/identifiers more than one time while serializing. When serializing arrays of structures, this can make a major difference. The [logs.rs](https://github.com/khonsulabs/pot/blob/main/benchmarks/examples/logs.rs) example demonstrates this: ```sh $ cargo test --example logs -- average_sizes --nocapture Generating 1000 LogArchives with 100 entries. +-----------------+-----------+-----------------+ | Format | Bytes | Self-Describing | +-----------------+-----------+-----------------+ | pot | 2,627,586 | yes | +-----------------+-----------+-----------------+ | cbor | 3,072,369 | yes | +-----------------+-----------+-----------------+ | msgpack(named) | 3,059,915 | yes | +-----------------+-----------+-----------------+ | msgpack | 2,559,907 | no | +-----------------+-----------+-----------------+ | bincode(varint) | 2,506,844 | no | +-----------------+-----------+-----------------+ | bincode | 2,755,137 | no | +-----------------+-----------+-----------------+ ``` ## Example ```rust use serde_derive::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] pub struct User { id: u64, name: String, } fn main() -> Result<(), pot::Error> { let user = User { id: 42, name: String::from("ecton"), }; let serialized = pot::to_vec(&user)?; println!("User serialized: {serialized:02x?}"); let deserialized: User = pot::from_slice(&serialized)?; assert_eq!(deserialized, user); // Pot also provides a "Value" type for serializing Pot-encoded payloads // without needing the original structure. let user: pot::Value<'_> = pot::from_slice(&serialized)?; println!("User decoded as value: {user}"); Ok(()) } ``` Outputs: ```text User serialized: [50, 6f, 74, 00, a2, c4, 69, 64, 40, 2a, c8, 6e, 61, 6d, 65, e5, 65, 63, 74, 6f, 6e] User decoded as value: {id: 42, name: ecton} ``` ## Benchmarks Because benchmarks can be subjective and often don't mirror real-world usage, this library's authors aren't making any specific performance claims. The way Pot achieves space savings requires some computational overhead. As such, it is expected that a hypothetically perfect CBOR implementation could outperform a hypothetically perfect Pot implementation. The results from the current benchmark suite executed on GitHub Actions are [viewable here](https://pot.bonsaidb.io/benchmarks/report/). The current suite is only aimed at comparing the default performance for each library. ### Serialize into new `Vec` [![Serialize Benchmark Violin Chart](https://pot.bonsaidb.io/benchmarks/logs_serialize/report/violin.svg)](https://pot.bonsaidb.io/benchmarks/logs_serialize/report/index.html) ### Serialize into reused `Vec` [![Serialize with Reused Buffer Benchmark Violin Chart](https://pot.bonsaidb.io/benchmarks/logs_serialize-reuse/report/violin.svg)](https://pot.bonsaidb.io/benchmarks/logs_serialize-reuse/report/index.html) ### Deserialize [![Deserialize Benchmark Violin Chart](https://pot.bonsaidb.io/benchmarks/logs_deserialize/report/violin.svg)](https://pot.bonsaidb.io/benchmarks/logs_deserialize/report/index.html)