pub struct Config { /* private fields */ }Expand description
Builder for configuring and running protobuf compilation.
Implementations§
Source§impl Config
impl Config
Sourcepub fn includes(self, includes: &[impl AsRef<Path>]) -> Self
pub fn includes(self, includes: &[impl AsRef<Path>]) -> Self
Add include directories for protoc to search for imports.
Sourcepub fn out_dir(self, dir: impl Into<PathBuf>) -> Self
pub fn out_dir(self, dir: impl Into<PathBuf>) -> Self
Set the output directory for generated files.
Defaults to $OUT_DIR if not set.
Sourcepub fn generate_views(self, enabled: bool) -> Self
pub fn generate_views(self, enabled: bool) -> Self
Enable or disable view type generation (default: true).
Sourcepub fn generate_json(self, enabled: bool) -> Self
pub fn generate_json(self, enabled: bool) -> Self
Enable or disable serde Serialize/Deserialize derive generation for generated message structs and enum types (default: false).
When enabled, the downstream crate must depend on serde and enable
the buffa/json feature for the runtime helpers.
Sourcepub fn generate_arbitrary(self, enabled: bool) -> Self
pub fn generate_arbitrary(self, enabled: bool) -> Self
Enable or disable #[derive(arbitrary::Arbitrary)] on generated
types (default: false).
The derive is gated behind #[cfg_attr(feature = "arbitrary", ...)]
so the downstream crate compiles with or without the feature enabled.
Sourcepub fn preserve_unknown_fields(self, enabled: bool) -> Self
pub fn preserve_unknown_fields(self, enabled: bool) -> Self
Enable or disable unknown field preservation (default: true).
When enabled (the default), unrecognized fields encountered during decode are stored and re-emitted on encode — essential for proxy / middleware services and round-trip fidelity across schema versions.
Disabling is primarily a memory optimization (24 bytes/message for
the UnknownFields Vec header), not a throughput one. When no unknown
fields appear on the wire — the common case for schema-aligned
services — decode and encode costs are effectively identical in
either mode. Consider disabling for embedded / no_std targets or
large in-memory collections of small messages.
Sourcepub fn strict_utf8_mapping(self, enabled: bool) -> Self
pub fn strict_utf8_mapping(self, enabled: bool) -> Self
Honor features.utf8_validation = NONE by emitting Vec<u8> / &[u8]
for such string fields instead of String / &str (default: false).
When disabled (the default), all string fields map to String and
UTF-8 is validated on decode — stricter than proto2 requires, but
ergonomic and safe.
When enabled, string fields with utf8_validation = NONE become
Vec<u8> / &[u8]. Decode skips validation; the caller chooses
whether to std::str::from_utf8 (checked) or from_utf8_unchecked
(trusted-input fast path). This is the only sound Rust mapping when
strings may actually contain non-UTF-8 bytes.
Note for proto2 users: proto2’s default is utf8_validation = NONE,
so enabling this turns ALL proto2 string fields into Vec<u8>. Use
only for new code or when profiling identifies UTF-8 validation as a
bottleneck (it can be 10%+ of decode CPU for string-heavy messages).
JSON note: fields normalized to bytes serialize as base64 in JSON
(the proto3 JSON encoding for bytes). Keep strict mapping disabled
for fields that need JSON string interop with other implementations.
Sourcepub fn extern_path(
self,
proto_path: impl Into<String>,
rust_path: impl Into<String>,
) -> Self
pub fn extern_path( self, proto_path: impl Into<String>, rust_path: impl Into<String>, ) -> Self
Declare an external type path mapping.
Types under the given protobuf path prefix will reference the specified Rust module path instead of being generated. This allows shared proto packages to be compiled once in a dedicated crate and referenced from others.
proto_path is a fully-qualified protobuf package path, e.g.,
".my.common" or "my.common" (the leading dot is optional and will
be added automatically). rust_path is the Rust module path where
those types are accessible (e.g., "::common_protos").
§Example
buffa_build::Config::new()
.extern_path(".my.common", "::common_protos")
.files(&["proto/my_service.proto"])
.includes(&["proto/"])
.compile()
.unwrap();Sourcepub fn use_bytes_type_in(self, paths: &[impl AsRef<str>]) -> Self
pub fn use_bytes_type_in(self, paths: &[impl AsRef<str>]) -> Self
Configure bytes fields to use bytes::Bytes instead of Vec<u8>.
Each path is a fully-qualified proto path prefix. Use "." to apply
to all bytes fields, or specify individual field paths like
".my.pkg.MyMessage.data".
§Example
buffa_build::Config::new()
.bytes(&["."]) // all bytes fields use Bytes
.files(&["proto/my_service.proto"])
.includes(&["proto/"])
.compile()
.unwrap();Sourcepub fn use_bytes_type(self) -> Self
pub fn use_bytes_type(self) -> Self
Use bytes::Bytes for all bytes fields in all messages.
This is a convenience for .use_bytes_type_in(&["."]). Use .use_bytes_type_in(&[...]) with
specific proto paths if you only want Bytes for certain fields.
Sourcepub fn use_buf(self) -> Self
pub fn use_buf(self) -> Self
Use buf build instead of protoc for descriptor generation.
buf is often easier to install and keep current than protoc
(which many distros pin to old versions). This mode is intended for
the single-crate case: a buf.yaml at the crate root defining
the module layout.
Requires buf on PATH and a buf.yaml at the crate root. The
includes() setting is ignored — buf resolves
imports via its own module configuration.
Each path given to files() must be relative to its
owning module’s directory (the path: value inside buf.yaml), not
the crate root where buf.yaml itself lives. buf strips the module
path when producing FileDescriptorProto.name, so for
modules: [{path: proto}] and a file on disk at
proto/api/v1/service.proto, the descriptor name is
api/v1/service.proto — that is what .files() must contain.
Multiple modules in one buf.yaml work fine; buf enforces that
module-relative names are unique across the workspace.
§Monorepo / multi-module setups
For a workspace-root buf.yaml with many modules, this mode is a
poor fit. Prefer running buf generate with the protoc-gen-buffa
plugin and checking in the generated code, or use
descriptor_set() with the output of
buf build --as-file-descriptor-set -o fds.binpb <module-path>
run as a pre-build step.
§Example
// buf.yaml (at crate root):
// version: v2
// modules:
// - path: proto
//
// build.rs:
buffa_build::Config::new()
.use_buf()
.files(&["api/v1/service.proto"]) // relative to module root
.compile()
.unwrap();Sourcepub fn descriptor_set(self, path: impl Into<PathBuf>) -> Self
pub fn descriptor_set(self, path: impl Into<PathBuf>) -> Self
Use a pre-compiled FileDescriptorSet binary file as input.
Skips invoking protoc or buf entirely. The file must contain a
serialized google.protobuf.FileDescriptorSet (as produced by
protoc --descriptor_set_out or buf build --as-file-descriptor-set).
When using this, .files() specifies which proto files in the
descriptor set to generate code for (matching by proto file name).
Sourcepub fn include_file(self, name: impl Into<String>) -> Self
pub fn include_file(self, name: impl Into<String>) -> Self
Generate a module-tree include file alongside the per-package .rs
files.
The include file contains nested pub mod declarations with
include!() directives that assemble the generated code into a
module hierarchy matching the protobuf package structure. Users can
then include this single file instead of manually creating the
module tree.
The form of the emitted include! directives depends on whether
out_dir was set:
- Default (
$OUT_DIR): emitsinclude!(concat!(env!("OUT_DIR"), "/foo.rs")), for use frombuild.rsviainclude!(concat!(env!("OUT_DIR"), "/<name>")). - Explicit
out_dir: emits sibling-relativeinclude!("foo.rs"), for checking the generated code into the source tree and referencing it as a module (e.g.mod gen;).
§Example — build.rs / $OUT_DIR
// build.rs
buffa_build::Config::new()
.files(&["proto/my_service.proto"])
.includes(&["proto/"])
.include_file("_include.rs")
.compile()
.unwrap();
// lib.rs
include!(concat!(env!("OUT_DIR"), "/_include.rs"));§Example — checked-in source
// codegen.rs (run manually, not from build.rs)
buffa_build::Config::new()
.files(&["proto/my_service.proto"])
.includes(&["proto/"])
.out_dir("src/gen")
.include_file("mod.rs")
.compile()
.unwrap();
// lib.rs
mod gen;Sourcepub fn compile(self) -> Result<(), Box<dyn Error>>
pub fn compile(self) -> Result<(), Box<dyn Error>>
Compile proto files and generate Rust source.
§Errors
Returns an error if:
OUT_DIRis not set and noout_dirwas configuredprotocorbufcannot be found onPATH(when using those sources)- the proto compiler exits with a non-zero status (syntax errors, missing imports, etc.)
- a precompiled descriptor set file cannot be read
- the descriptor set bytes cannot be decoded as a
FileDescriptorSet - code generation fails (e.g. unsupported proto feature)
- the output directory cannot be created or written to