# pack-io v1.0.0 — Stable
**The stable release.** `pack-io 1.0.0` freezes the complete public surface, wire format, and performance baseline for the entire `1.x` line. The codec ships exactly as it has run since v0.6.0; v0.7–v0.9 added the hardening, integration coverage, and the frozen reference data table this release locks in.
This is the contract: pack-io is a compact binary wire format for Rust that combines **speed**, **schema evolution**, **zero-copy deserialization**, and a **normative wire-format spec a third-party implementer can read from one page**. No other Rust serialization crate owns all four properties together.
## Frozen for the `1.x` line
| Public API — every type, trait, free function, attribute, feature flag | [`docs/API.md` § Frozen public surface](https://github.com/jamesgober/pack-io/blob/main/docs/API.md#frozen-public-surface) | Source-compatible across all `1.x` releases |
| Wire format — byte-level spec (version 1.2) | [`docs/WIRE_FORMAT.md`](https://github.com/jamesgober/pack-io/blob/main/docs/WIRE_FORMAT.md) | Any `1.x` decoder reads any `1.x`-or-earlier encoding |
| Performance — comparative baseline | [`docs/PERFORMANCE_BASELINE.md`](https://github.com/jamesgober/pack-io/blob/main/docs/PERFORMANCE_BASELINE.md) | Any change exceeding 5 % regression on any row blocks the merge |
Source-breaking and wire-format-breaking changes are deferred to `2.x`. `1.x` minor releases ship bug fixes, hardening, performance work, and strictly *additive* changes (new variants on the `#[non_exhaustive]` `SerialError` enum, new built-in `Serialize` / `Deserialize` impls for additional `core` / `alloc` types).
## What changed in v1.0.0
### `#[derive(DeserializeView)]` on enums — new
The derive previously rejected enums. v1.0 emits the same `varint(variant_index) ++ fields` wire shape as `#[derive(Deserialize)]`, with each variant's fields decoded via `DeserializeView` so borrow-shaped fields land as `&'a str` / `&'a [u8]` rather than `String` / `Vec<u8>`:
```rust
use pack_io::DeserializeView;
#[derive(DeserializeView)]
enum EnvelopeView<'a> {
Empty,
Note(&'a str),
Frame { header: &'a str, body: &'a [u8] },
}
```
Four new tests in [`tests/derive.rs`](https://github.com/jamesgober/pack-io/blob/main/tests/derive.rs) cover unit variants, tuple variants with borrowed `&str`, named-field variants with borrowed `&str` + `&[u8]`, and the unknown-variant rejection path.
This is the last v1.0-blocking gap from the pre-1.0 deferred-work list. Nothing else is deferred.
### Doc + status sweep
- README + API.md status banners flipped from "beta — bug-fixes-only" to **"stable (v1.0.0)"**.
- README roadmap section replaced with a `## Stability contract` section listing the three frozen surfaces and pointing at their reference docs.
- README + API.md + crate-level rustdoc + install snippets bumped from `0.9` → `1`.
- API.md `Compatibility & semver` section rewritten — drops the pre-1.0 / post-1.0 framing for strict SemVer language.
- WIRE_FORMAT.md spec banner drops "Breaking changes inside the `0.x` series…" for "Wire-format-breaking changes are deferred to `2.x`".
- PERFORMANCE_BASELINE.md banner rewritten as the frozen reference with the contractual 5 % regression policy stated up front. Added a "Why these workloads" section explaining what each row is representative of.
- `fuzz/README.md` target table flattened — the 13 targets no longer carry per-version "(v0.9)" markers.
- Stale `(v0.3.0)` / "new in v0.3" / "currently:" / "pack-io v0.2" markers swept out of crate-level rustdoc, `src/codec.rs` doc comments, and three example source files.
## What `pack-io 1.0` is
A compact binary wire format with one coherent contract:
| **Round-trip integrity** — `decode(encode(v)) == v` | [WIRE_FORMAT.md](https://github.com/jamesgober/pack-io/blob/main/docs/WIRE_FORMAT.md) | 25 proptest properties in `tests/roundtrip.rs` |
| **Determinism** — same value → same bytes | [WIRE_FORMAT.md §4.1](https://github.com/jamesgober/pack-io/blob/main/docs/WIRE_FORMAT.md#41-canonical-ordering-the-determinism-contract) | 21 proptest properties + 29 golden vectors in `tests/byte_equivalence.rs` |
| **Safe decode** — no panic, no unbounded allocation | [WIRE_FORMAT.md §6](https://github.com/jamesgober/pack-io/blob/main/docs/WIRE_FORMAT.md#6-error-categories) | 20 adversarial + 17 hostile-input tests + 13 fuzz targets in CI |
| **Cross-platform byte equivalence** | n/a (consequence of the spec) | 29 golden-vector assertions running on Linux × macOS × Windows × stable × MSRV |
| **Schema evolution** — append-only forward/backward compatibility | [WIRE_FORMAT.md §3.8](https://github.com/jamesgober/pack-io/blob/main/docs/WIRE_FORMAT.md#38-versioned-structs) | 15 schema-evolution tests + `examples/protocol_handshake.rs` |
| **Zero-copy** — `View<T>` borrows directly from the input buffer | [API.md](https://github.com/jamesgober/pack-io/blob/main/docs/API.md#zero-copy-decode) | Runtime pointer-equality assertion in `tests/integration_scenarios.rs` |
| **`no_std`-capable** | [API.md](https://github.com/jamesgober/pack-io/blob/main/docs/API.md#installation) | `cargo build --no-default-features` in CI |
| **No `unsafe` on the safe-decode path** | [`#![forbid(unsafe_code)]`](https://github.com/jamesgober/pack-io/blob/main/src/lib.rs) | enforced by the compiler |
## Performance — the frozen baseline
High-fidelity Criterion medians (100 samples × 10 s measurement × 2 s warmup, Windows x86_64, Rust stable release build). These are the numbers v1.0 ships and the contract the `1.x` line maintains. Full numbers + methodology + per-row analysis in [`docs/PERFORMANCE_BASELINE.md`](https://github.com/jamesgober/pack-io/blob/main/docs/PERFORMANCE_BASELINE.md).
| owned struct encode | **37.9 ns** | 39.4 ns | 232.6 ns | 112.6 ns | **pack-io fastest** |
| 64-byte `String` round-trip | **44.7 ns** | 48.8 ns | — | — | **pack-io fastest** |
| zero-copy view of 64-byte `&str` | **5.2 ns** | — | — | — | **uncontested** |
| 4 KiB `Vec<u8>` decode | **59.7 ns** | 63.0 ns | — | — | **pack-io fastest** |
| `u64` round-trip | 22.3 ns | **20.6 ns** | — | — | within 8 % of bincode |
| owned struct decode | 158.9 ns | 165.1 ns | 285.1 ns | **154.6 ns** | within 3 % of rkyv, beats bincode |
| zero-copy view of struct | 34.7 ns | — | — | **12.0 ns** | rkyv 3× faster (intentional — rkyv reads raw memory, pack-io walks varints by the wire-format spec) |
**Wins on 4 of 7**, **within 8 % on 2 of 7**, **one intentional loss** to rkyv's archived path (which trades the wire-format spec for raw-memory access — a trade pack-io declines on purpose, because the wire-format spec is what makes the codec implementable from a one-page document).
## Breaking changes
**None.** Every v0.9 source file compiles unchanged. Every payload encoded by any pre-1.0 release decodes identically under v1.0. The one new feature — enum support in `#[derive(DeserializeView)]` — is purely additive.
## Verification
All gates green on **both stable and MSRV 1.85** across Linux / macOS / Windows:
```bash
cargo fmt --all -- --check
cargo +1.85 fmt --all -- --check
cargo clippy --all-targets --all-features -- -D warnings
cargo +1.85 clippy --all-targets --all-features -- -D warnings
cargo test --all-features
cargo +1.85 test --all-features
cargo build --no-default-features
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features
cargo audit
cargo deny check
cd fuzz && cargo +nightly check
```
Test counts at this tag (stable, `--all-features`): **278 total**, every one passing.
| Unit tests | 71 | every primitive impl, varint corners, codec mechanics |
| `tests/roundtrip.rs` | 25 | `decode(encode(v)) == v` proptest per primitive |
| `tests/determinism.rs` | 21 | same value → same bytes per primitive |
| `tests/adversarial.rs` | 20 | random bytes / truncations / hostile lengths |
| `tests/collections.rs` | 19 | round-trip + canonical encoding + OOM regression |
| `tests/streaming.rs` | 11 | `IoEncoder` / `IoDecoder` byte equivalence |
| `tests/derive.rs` | **18** | every struct shape, every enum variant shape, generics, view derive (struct + enum), unknown variants — **+4 new for enum `DeserializeView`** |
| `tests/schema_evolution.rs` | 15 | v1↔v1, v1→v2, v2→v1, deprecated round-trip |
| `tests/byte_equivalence.rs` | 29 | golden vectors, runs on every CI platform |
| `tests/hostile_inputs.rs` | 17 | hand-crafted attack vectors |
| `tests/integration_scenarios.rs` | 8 | consumer-shape end-to-end stress |
| Doctests | 24 | every public-item example compiles and runs |
All 10 example programs run end-to-end. All 13 fuzz targets compile cleanly under nightly and run on every push to `main` for 60 s per target on Ubuntu nightly with ASAN.
## What `2.x` will (eventually) do
Nothing on the immediate roadmap. The post-1.0 work, in order of likelihood:
- A native `serde` interop layer behind the existing reserved `serde` feature flag, if real consumers need it.
- A second wire-format version (`1.3`+) for additive features that don't break `1.x` decoders — e.g. new built-in `Serialize` / `Deserialize` impls for additional `core` types as they stabilize.
- ossfuzz integration for continuous out-of-band fuzzing beyond what CI's 60-second smoke window covers.
A `2.0` only happens if the codec needs a wire-format or source-breaking change that can't be expressed additively. The bar is high.
## Installation
```toml
[dependencies]
pack-io = "1" # in-memory + streaming codec
pack-io = { version = "1", features = ["derive"] } # + #[derive(Serialize, Deserialize, DeserializeView)]
pack-io = { version = "1", features = ["schema"] } # + #[pack_io(version = N)] schema evolution attributes
pack-io = { version = "1", default-features = false } # no_std (core + alloc only)
```
MSRV: Rust 1.85 (2024 edition).
## Documentation
- [README](https://github.com/jamesgober/pack-io/blob/main/README.md) — positioning, features, install, quick start
- [API Reference](https://github.com/jamesgober/pack-io/blob/main/docs/API.md) — every public item with the frozen-surface enumeration
- [Wire Format Spec](https://github.com/jamesgober/pack-io/blob/main/docs/WIRE_FORMAT.md) — normative byte-level spec (version 1.2)
- [Performance overview](https://github.com/jamesgober/pack-io/blob/main/docs/PERFORMANCE.md) — methodology + per-row analysis
- [Performance baseline](https://github.com/jamesgober/pack-io/blob/main/docs/PERFORMANCE_BASELINE.md) — frozen reference data
- [CHANGELOG](https://github.com/jamesgober/pack-io/blob/main/CHANGELOG.md)
---
**Full diff:** [`v0.9.0...v1.0.0`](https://github.com/jamesgober/pack-io/compare/v0.9.0...v1.0.0).
**Changelog:** [`CHANGELOG.md`](https://github.com/jamesgober/pack-io/blob/main/CHANGELOG.md#100---2026-06-05).