Skip to content

buffa-test-fixtures: minimal #[derive(Message)] for tests and doc examples #226

Description

@iainmcgin

Motivation

While spiking a buffa port for axum-extra's protobuf extractor, the main ergonomics gap relative to prost was the lack of an inline #[derive] for test and example code. prost users write:

#[derive(prost::Message)]
struct Input {
    #[prost(string, tag = "1")]
    foo: String,
}

directly inside #[cfg(test)] modules and doc examples. buffa is codegen-only, so the equivalent today is either:

  • pull in buffa-types and use a well-known type (StringValue, Int32Value) as a stand-in fixture, or
  • add a build.rs + .proto file just for tests.

The first works but reads oddly in docs ("where MyMessage is a type generated by protoc-gen-buffa…"); the second is heavyweight for a downstream crate that only wants one tiny test message.

This will recur on every downstream port (prometheus-client, pprof, libp2p-identity, etc.) — each has prost-derive test fixtures that need a buffa equivalent.

Proposal

A buffa-test-fixtures crate (or buffa-derive, name TBD) that provides a #[derive(buffa::Message)] proc-macro covering the minimal field set needed for tests and examples:

  • scalar fields (string, int32, int64, uint32, uint64, bool, bytes)
  • optional / repeated
  • nested messages
  • explicit tag = N

Explicitly out of scope (to keep it from becoming a parallel production codegen path): maps, oneofs, enums, groups, extensions, editions feature resolution, view types, reflection, JSON/textproto. If a test needs those, it should use real codegen.

Positioning

The crate docs and README should be unambiguous that this is for tests and examples only — protoc-gen-buffa / buffa-build remain the supported path for production schemas. Something along the lines of:

This derive exists so downstream crates can write self-contained tests and doc examples without a build.rs. It supports a deliberately small subset of protobuf. For application code, generate types from .proto files.

A #[doc(hidden)] re-export from the main buffa crate behind a derive feature would let examples write #[derive(buffa::Message)] without a second dependency line, but that may invite production use — open to leaving it as a separate explicit dep instead.

Prior art

  • prost's prost-derive (the thing we're matching ergonomically)
  • serde's split between serde and serde_derive

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions