https://github.com/convex-dev/cad3
Convex CAD3 encoded data structures, in Rust
https://github.com/convex-dev/cad3
cad3 convex encoding lattice rust
Last synced: about 1 month ago
JSON representation
Convex CAD3 encoded data structures, in Rust
- Host: GitHub
- URL: https://github.com/convex-dev/cad3
- Owner: Convex-Dev
- License: apache-2.0
- Created: 2026-05-23T04:28:10.000Z (about 2 months ago)
- Default Branch: master
- Last Pushed: 2026-05-23T10:17:00.000Z (about 2 months ago)
- Last Synced: 2026-05-23T11:36:56.643Z (about 2 months ago)
- Topics: cad3, convex, encoding, lattice, rust
- Language: Rust
- Size: 28.3 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# cad3
[](https://github.com/Convex-Dev/cad3/actions/workflows/ci.yml)
[](LICENSE)
Rust implementation of [Convex CAD3](https://docs.convex.world/cad/003_encoding/) — the
canonical wire and storage encoding for Convex lattice data values.
> **Status:** early. The small primitive variants are landed; collections,
> blobs/strings, and the rest are next. The Java reference implementation
> lives at [`Convex-Dev/convex`](https://github.com/Convex-Dev/convex) under
> `convex-core/src/main/java/convex/core/data/`. Architectural design lives
> in [`docs/CELL_DESIGN.md`](docs/CELL_DESIGN.md).
## What's CAD3?
CAD3 is a compact, self-describing, canonical binary encoding for immutable data values.
Every value has exactly one valid byte representation, and the SHA3-256 hash of that
encoding is the value's stable, decentralised identifier (the "value ID"). Larger values
form Merkle DAGs via embedded child encodings or external value-ID references, enabling
structural sharing, partial transmission, and arbitrary-size data structures inside
fixed-size buffers.
See the [CAD3 specification](https://docs.convex.world/cad/003_encoding/) for full details.
## Implemented
| Tag(s) | Type | Notes |
| ------------- | ----------- | ----------------------------------------------------------- |
| `0x00` | `nil` | single-byte encoding |
| `0x10`–`0x18` | Long | signed `i64`, minimal-length two's complement |
| `0x1D` | Double | IEEE 754, canonical NaN |
| `0x30` | String | UTF-8 (not enforced), leaf only — ≤ 4096 bytes |
| `0x31` | Blob | arbitrary bytes, leaf only — ≤ 4096 bytes |
| `0x3C`–`0x3E` | Char | Unicode scalar, minimal-length |
| `0xB0`–`0xBF` | Byte flags | `0xB0` = CVM `false`, `0xB1` = CVM `true` |
| `0xEA` | Address | account index, VLQ payload |
Roadmap (in rough order): BigInt, Symbol, Keyword, Ref + Vector (forces
tree form for large Blob/String), List, Map, Set, Index, signed data,
records.
## Usage
```toml
[dependencies]
cad3 = "0.0.1"
```
```rust
use cad3::Cell;
use bytes::Bytes;
// Encoding — one canonical byte sequence per value
assert_eq!(Cell::Nil.encoding(), vec![0x00]);
assert_eq!(Cell::FALSE.encoding(), vec![0xB0]);
assert_eq!(Cell::Long(19).encoding(), vec![0x11, 0x13]);
assert_eq!(Cell::Char('A').encoding(), vec![0x3C, 0x41]);
assert_eq!(Cell::Address(128).encoding(), vec![0xEA, 0x81, 0x00]);
assert_eq!(Cell::string(Bytes::from_static(b"Hi")).encoding(),
vec![0x30, 0x02, b'H', b'i']);
assert_eq!(Cell::blob(Bytes::from_static(&[1,2,3])).encoding(),
vec![0x31, 0x03, 1, 2, 3]);
// Round trip
let cell = Cell::decode(&Cell::Long(42).encoding()).unwrap();
assert_eq!(cell, Cell::Long(42));
// Cheap sharing — cloning a heavy cell is one atomic refcount bump
let blob = Cell::blob(Bytes::from(vec![0xAB; 4096]));
let shared = blob.clone(); // no copy of the 4096 bytes; Arc bumped
// Value ID = SHA3-256 of the canonical encoding (cached on heavy cells)
let id = Cell::Long(42).value_id();
println!("value id = {id}");
```
## Development
Requires Rust 1.75 or later.
```bash
cargo fmt --all
cargo clippy --all-targets -- -D warnings
cargo test
```
## License
Licensed under the [Apache License, Version 2.0](LICENSE).