Skip to main content

Config

Struct Config 

Source
pub struct Config { /* private fields */ }
Expand description

Builder for configuring and running protobuf compilation.

Implementations§

Source§

impl Config

Source

pub fn new() -> Self

Create a new configuration with defaults.

Source

pub fn files(self, files: &[impl AsRef<Path>]) -> Self

Add .proto files to compile.

Source

pub fn includes(self, includes: &[impl AsRef<Path>]) -> Self

Add include directories for protoc to search for imports.

Source

pub fn out_dir(self, dir: impl Into<PathBuf>) -> Self

Set the output directory for generated files. Defaults to $OUT_DIR if not set.

Source

pub fn generate_views(self, enabled: bool) -> Self

Enable or disable view type generation (default: true).

Source

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.

Source

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.

Source

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.

Source

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.

Source

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();
Source

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();
Source

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.

Source

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();
Source

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).

Source

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): emits include!(concat!(env!("OUT_DIR"), "/foo.rs")), for use from build.rs via include!(concat!(env!("OUT_DIR"), "/<name>")).
  • Explicit out_dir: emits sibling-relative include!("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;
Source

pub fn compile(self) -> Result<(), Box<dyn Error>>

Compile proto files and generate Rust source.

§Errors

Returns an error if:

  • OUT_DIR is not set and no out_dir was configured
  • protoc or buf cannot be found on PATH (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

Trait Implementations§

Source§

impl Default for Config

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.