Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),

## [Unreleased]

## [0.6.0] - 2026-05-15

### Added

- **Generated message structs now include `with_<field>(value) -> Self`
Expand Down Expand Up @@ -745,7 +747,10 @@ This release publishes:

MSRV: Rust 1.85.

[Unreleased]: https://github.com/anthropics/buffa/compare/v0.5.0...HEAD
[Unreleased]: https://github.com/anthropics/buffa/compare/v0.6.0...HEAD
[0.6.0]: https://github.com/anthropics/buffa/compare/v0.5.2...v0.6.0
[0.5.2]: https://github.com/anthropics/buffa/compare/v0.5.1...v0.5.2
[0.5.1]: https://github.com/anthropics/buffa/compare/v0.5.0...v0.5.1
[0.5.0]: https://github.com/anthropics/buffa/compare/v0.4.0...v0.5.0
[0.4.0]: https://github.com/anthropics/buffa/compare/v0.3.0...v0.4.0
[0.3.0]: https://github.com/anthropics/buffa/compare/v0.2.0...v0.3.0
Expand Down
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ exclude = [
]

[workspace.package]
version = "0.5.2"
version = "0.6.0"
edition = "2021"
rust-version = "1.85"
license = "Apache-2.0"
Expand All @@ -42,18 +42,18 @@ lto = true
codegen-units = 1

[workspace.dependencies]
buffa = { path = "buffa", version = "0.5.2", default-features = false }
buffa-types = { path = "buffa-types", version = "0.5.2" }
buffa = { path = "buffa", version = "0.6.0", default-features = false }
buffa-types = { path = "buffa-types", version = "0.6.0" }
# `default-features = false` keeps the codegen toolchain (`buffa-codegen` /
# `buffa-build` / `protoc-gen-buffa`) lean — descriptor types are read at
# codegen time via the binary codec only, never serialised to JSON / text or
# borrowed as views, so the codegen build graph carries no `serde` /
# `serde_json` / `base64`. Downstream consumers whose protos reference
# `descriptor.proto` types as fields enable the features they need.
buffa-descriptor = { path = "buffa-descriptor", version = "0.5.2", default-features = false }
buffa-codegen = { path = "buffa-codegen", version = "0.5.2" }
buffa-build = { path = "buffa-build", version = "0.5.2" }
buffa-test = { path = "buffa-test", version = "0.5.2" }
buffa-descriptor = { path = "buffa-descriptor", version = "0.6.0", default-features = false }
buffa-codegen = { path = "buffa-codegen", version = "0.6.0" }
buffa-build = { path = "buffa-build", version = "0.6.0" }
buffa-test = { path = "buffa-test", version = "0.6.0" }
base64 = { version = "0.22", default-features = false, features = ["alloc"] }
bytes = { version = "1", default-features = false }
hashbrown = { version = "0.15", default-features = false, features = ["default-hasher"] }
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ These are gaps we intend to address in future releases:

## Semver and API stability

Buffa is pre-1.0. We follow the [Rust community convention](https://doc.rust-lang.org/cargo/reference/semver.html) for 0.x crates: breaking changes increment the **minor** version (0.1.x → 0.2.0), additive changes increment the **patch** version (0.1.0 → 0.1.1). Pin to a minor version (`buffa = "0.5"`) to avoid surprises.
Buffa is pre-1.0. We follow the [Rust community convention](https://doc.rust-lang.org/cargo/reference/semver.html) for 0.x crates: breaking changes increment the **minor** version (0.1.x → 0.2.0), additive changes increment the **patch** version (0.1.0 → 0.1.1). Pin to a minor version (`buffa = "0.6"`) to avoid surprises.

The generated code API (struct shapes, `Message` trait, `MessageView` trait, `EnumValue`, `MessageField`) is considered the primary stability surface. Internal helper modules marked `#[doc(hidden)]` (`__private`, `__buffa_*` fields) may change at any time.

Expand Down
2 changes: 1 addition & 1 deletion buffa-build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,6 @@ categories = ["development-tools::build-utils"]
rustdoc-args = ["--cfg", "docsrs"]

[dependencies]
buffa = { path = "../buffa", version = "0.5.2" }
buffa = { path = "../buffa", version = "0.6.0" }
buffa-codegen = { workspace = true }
tempfile = "3"
2 changes: 1 addition & 1 deletion buffa-codegen/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ categories = ["development-tools::build-utils"]

[dependencies]
# `path` wins for local workspace development; `version` is used on publish.
buffa = { path = "../buffa", version = "0.5.2" }
buffa = { path = "../buffa", version = "0.6.0" }
# Codegen reads descriptors via the binary codec only — no views / json /
# text. The workspace dep already declares `default-features = false`; add
# back `std` (it's a build-time tool, never `no_std`).
Expand Down
61 changes: 39 additions & 22 deletions docs/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ Add buffa to your project:
```toml
# Cargo.toml
[dependencies]
buffa = "0.5"
buffa-types = "0.5" # well-known types (Timestamp, Duration, Any, etc.)
buffa = "0.6"
buffa-types = "0.6" # well-known types (Timestamp, Duration, Any, etc.)

[build-dependencies]
buffa-build = "0.5"
buffa-build = "0.6"
```

### Feature flags
Expand All @@ -28,8 +28,8 @@ Both `buffa` and `buffa-types` share the same feature flag names:

```toml
# Enable JSON support
buffa = { version = "0.5", features = ["json"] }
buffa-types = { version = "0.5", features = ["json"] }
buffa = { version = "0.6", features = ["json"] }
buffa-types = { version = "0.6", features = ["json"] }
```

## Prerequisites
Expand Down Expand Up @@ -196,7 +196,7 @@ This requires `buffa-types` as a dependency in your `Cargo.toml`:

```toml
[dependencies]
buffa-types = "0.5"
buffa-types = "0.6"
```

`buffa-types` is a pure source crate — it does **not** run `protoc` or any code generation at build time. If your protos use WKTs but you generate your own Rust code ahead-of-time (via `buf generate` or a `protoc` script), then `buffa` + `buffa-types` is your entire runtime dependency surface.
Expand All @@ -219,12 +219,20 @@ This disables the automatic mapping and routes all `google.protobuf.*` reference

```toml
[dependencies]
buffa-descriptor = "0.5"
buffa-descriptor = "0.6"
```

If your protos import `descriptor.proto` only to declare custom options (`extend google.protobuf.MessageOptions { ... }`) and never reference a descriptor type as a *field type*, no `buffa-descriptor` dependency is required — extension declarations don't generate field-type references.

`buffa-descriptor` is generated without views, JSON, or text impls (it exists primarily to bootstrap `buffa-codegen`). Its **enum** types — the only descriptor types referenced as field types in practice — work with all codegen modes. Descriptor **message** types referenced as fields with `views=true`, `json=true`, or `text=true` will not currently compile; if you hit this, please [file an issue](https://github.com/anthropics/buffa/issues).
`buffa-descriptor` ships its view, JSON, text, and arbitrary impls behind crate features (`views`, `json`, `text`, `arbitrary`), all off by default. The codegen toolchain depends on it with `default-features = false`, so building `buffa-codegen` / `buffa-build` / `protoc-gen-buffa` doesn't pull in `serde` or `serde_json`. **If your protos reference a descriptor message type as a field type and you generate with `views=true`, `json=true`, or `text=true`, enable the matching `buffa-descriptor` features**:

```toml
[dependencies]
# Codegen with .generate_views(true).generate_json(true)
buffa-descriptor = { version = "0.6", features = ["views", "json"] }
```

Descriptor **enum** types referenced as field types (the most common case — e.g. `google.protobuf.FieldDescriptorProto.Type` in protovalidate) work with the default feature set. The features are only needed for descriptor **message** types referenced as fields (e.g. `FileDescriptorSet`, `FileDescriptorProto`). If you hit a missing-impl error like `the trait bound FileDescriptorSet: serde::Deserialize is not satisfied`, add `buffa-descriptor` with the right features.

A user-provided `.google.protobuf` extern_path covers descriptor types too — the auto-routing yields to it, preserving the behaviour from before `buffa-descriptor` routing existed.

Expand Down Expand Up @@ -350,25 +358,25 @@ Download the binaries for your platform from the [releases page](https://github.

```sh
# Download binaries + cosign signatures + certificates (both plugins match)
gh release download v0.5.2 --repo anthropics/buffa \
gh release download v0.6.0 --repo anthropics/buffa \
--pattern 'protoc-gen-buffa*-linux-x86_64*'

# Verify with GitHub attestations (requires gh CLI ≥ 2.49)
gh attestation verify protoc-gen-buffa-v0.5.2-linux-x86_64 --repo anthropics/buffa
gh attestation verify protoc-gen-buffa-packaging-v0.5.2-linux-x86_64 --repo anthropics/buffa
gh attestation verify protoc-gen-buffa-v0.6.0-linux-x86_64 --repo anthropics/buffa
gh attestation verify protoc-gen-buffa-packaging-v0.6.0-linux-x86_64 --repo anthropics/buffa

# Or with cosign (standalone, no gh required) — shown for one binary
cosign verify-blob \
--signature protoc-gen-buffa-v0.5.2-linux-x86_64.sig \
--certificate protoc-gen-buffa-v0.5.2-linux-x86_64.pem \
--signature protoc-gen-buffa-v0.6.0-linux-x86_64.sig \
--certificate protoc-gen-buffa-v0.6.0-linux-x86_64.pem \
--certificate-identity-regexp "github.com/anthropics/buffa" \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
protoc-gen-buffa-v0.5.2-linux-x86_64
protoc-gen-buffa-v0.6.0-linux-x86_64

# Install both
chmod +x protoc-gen-buffa-v0.5.2-linux-x86_64 protoc-gen-buffa-packaging-v0.5.2-linux-x86_64
mv protoc-gen-buffa-v0.5.2-linux-x86_64 ~/.local/bin/protoc-gen-buffa
mv protoc-gen-buffa-packaging-v0.5.2-linux-x86_64 ~/.local/bin/protoc-gen-buffa-packaging
chmod +x protoc-gen-buffa-v0.6.0-linux-x86_64 protoc-gen-buffa-packaging-v0.6.0-linux-x86_64
mv protoc-gen-buffa-v0.6.0-linux-x86_64 ~/.local/bin/protoc-gen-buffa
mv protoc-gen-buffa-packaging-v0.6.0-linux-x86_64 ~/.local/bin/protoc-gen-buffa-packaging
```

Available platforms: `linux-x86_64`, `linux-aarch64`, `darwin-x86_64`, `darwin-aarch64`, `windows-x86_64` (`.exe`). All releases include SHA-256 checksums, Sigstore cosign signatures, and signed SLSA build provenance for supply chain verification.
Expand Down Expand Up @@ -409,7 +417,7 @@ pub mod example {
mod gen;
```

Pin the plugin version for reproducible builds: `remote: buf.build/anthropics/buffa:v0.5.3`. Match it to the `buffa` runtime crate version in your `Cargo.toml` — generated code from a newer plugin may reference items that don't exist in an older runtime.
Pin the plugin version for reproducible builds: `remote: buf.build/anthropics/buffa:v0.6.0`. Match it to the `buffa` runtime crate version in your `Cargo.toml` — generated code from a newer plugin may reference items that don't exist in an older runtime.

The complete, runnable [`examples/bsr-quickstart/`](../examples/bsr-quickstart/) project uses this layout.

Expand Down Expand Up @@ -1081,7 +1089,7 @@ Enable the `json` feature and `generate_json(true)` in your build config:
```toml
# Cargo.toml
[dependencies]
buffa = { version = "0.5", features = ["json"] }
buffa = { version = "0.6", features = ["json"] }
# Required: generated `#[derive(::serde::Serialize, ::serde::Deserialize)]`
# expands to `extern crate serde as _serde;`, so the consumer crate must
# depend on `serde` directly. `serde_json` is *not* required by generated
Expand Down Expand Up @@ -1118,6 +1126,15 @@ let json = serde_json::to_string(&msg)?;
let msg: Person = serde_json::from_str(&json)?;
```

When `generate_views(true)` is also enabled, generated **view** types implement
`serde::Serialize` directly, so you can serialize a decoded view to JSON without
first calling `to_owned_message()`. `OwnedView<V>` has a blanket `Serialize` impl
too, so `serde_json::to_string(&owned_view)` works the same way. Two limitations
relative to the owned form: extension fields are not included in view JSON output
(serialize the owned form to include them), and the view impl uses
`serialize_map(None)`, which `serde_json` accepts but length-prefixed formats like
`bincode` reject — use the owned form for those serializers.

### JSON parse options

For lenient parsing (e.g., ignoring unknown enum string values):
Expand All @@ -1143,7 +1160,7 @@ Enable the `text` feature and `generate_text(true)`:
```toml
# Cargo.toml
[dependencies]
buffa = { version = "0.5", features = ["text"] }
buffa = { version = "0.6", features = ["text"] }
```

```rust,ignore
Expand Down Expand Up @@ -1274,8 +1291,8 @@ let obj = Struct::from_fields([
Buffa works without `std` (requires `alloc`):

```toml
buffa = { version = "0.5", default-features = false }
buffa-types = { version = "0.5", default-features = false }
buffa = { version = "0.6", default-features = false }
buffa-types = { version = "0.6", default-features = false }
```

In `no_std` mode:
Expand Down
10 changes: 5 additions & 5 deletions docs/migration-from-prost.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ A step-by-step guide for migrating an existing prost-based project to buffa.
[dependencies]
-prost = "0.13"
-prost-types = "0.13"
+buffa = "0.5"
+buffa-types = "0.5"
+buffa = "0.6"
+buffa-types = "0.6"

[build-dependencies]
-prost-build = "0.13"
+buffa-build = "0.5"
+buffa-build = "0.6"
```

If you use JSON serialization via `pbjson`:
Expand All @@ -23,8 +23,8 @@ If you use JSON serialization via `pbjson`:
[dependencies]
-pbjson = "0.7"
-pbjson-types = "0.7"
+buffa = { version = "0.5", features = ["json"] }
+buffa-types = { version = "0.5", features = ["json"] }
+buffa = { version = "0.6", features = ["json"] }
+buffa-types = { version = "0.6", features = ["json"] }
serde_json = "1"
-
-[build-dependencies]
Expand Down
12 changes: 6 additions & 6 deletions docs/migration-from-protobuf.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,26 @@ This guide covers migration from both versions of the `protobuf` crate:
```diff
[dependencies]
-protobuf = "3"
+buffa = "0.5"
+buffa-types = "0.5"
+buffa = "0.6"
+buffa-types = "0.6"

[build-dependencies]
-protobuf-codegen = "3"
-protoc-bin-vendored = "3" # if using vendored protoc
+buffa-build = "0.5"
+buffa-build = "0.6"
```

### From Google v4

```diff
[dependencies]
-protobuf = "=4.33.1-release"
+buffa = "0.5"
+buffa-types = "0.5"
+buffa = "0.6"
+buffa-types = "0.6"

[build-dependencies]
-protobuf-codegen = "=4.33.1-release"
+buffa-build = "0.5"
+buffa-build = "0.6"
```

## 2. Rewrite `build.rs`
Expand Down
4 changes: 2 additions & 2 deletions examples/bsr-quickstart/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ plugin with `file_per_package=true` and a hand-written `mod.rs`. See
# example also acts as a forward-compat canary: if an in-tree runtime change
# ever breaks code generated by the published plugin, this example fails to
# build. In a real downstream project, use crates.io versions instead:
# buffa = { version = "0.5", features = ["json"] }
# buffa-types = { version = "0.5", features = ["json"] }
# buffa = { version = "0.6", features = ["json"] }
# buffa-types = { version = "0.6", features = ["json"] }
# serde = { version = "1", features = ["derive"] }
# serde_json = "1"
buffa = { path = "../../buffa", features = ["json"] }
Expand Down
2 changes: 1 addition & 1 deletion protoc-gen-buffa-packaging/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ keywords = ["protobuf", "protocol-buffers", "protoc", "plugin", "codegen"]
categories = ["development-tools::build-utils", "command-line-utilities"]

[dependencies]
buffa = { path = "../buffa", version = "0.5.2" }
buffa = { path = "../buffa", version = "0.6.0" }
buffa-codegen = { workspace = true }
2 changes: 1 addition & 1 deletion protoc-gen-buffa/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ keywords = ["protobuf", "protocol-buffers", "protoc", "plugin", "codegen"]
categories = ["development-tools::build-utils", "command-line-utilities"]

[dependencies]
buffa = { path = "../buffa", version = "0.5.2" }
buffa = { path = "../buffa", version = "0.6.0" }
buffa-codegen = { workspace = true }
Loading