pub struct Generator { /* private fields */ }Expand description
Protobuf code generator
Use this in build.rs to compile .proto files into a Rust module.
The main way to control the compilation process is to call configure,
which allows the user to customize how code is generated from Protobuf types and fields of
their choosing.
§Note
It’s recommended to call one of use_container_alloc,
use_container_heapless, or
use_container_alloc to ensure that container types are
configured for string, bytes, repeated, and map fields. The generator will throw an
error if it reaches any such field that doesn’t have a container configured.
§Example
use micropb_gen::{Generator, Config};
let mut gen = Generator::new();
// Use container types from `heapless`
gen.use_container_heapless()
// Set max length of repeated fields in .test.Data to 4
.configure(".test.Data", Config::new().max_len(4))
// Wrap .test.Data.value inside a Box
.configure(".test.Data.value", Config::new().boxed(true))
// Compile test.proto into a Rust module
.compile_protos(
&["test.proto"],
std::env::var("OUT_DIR").unwrap() + "/test_proto.rs",
)
.unwrap();Implementations§
Source§impl Generator
impl Generator
Sourcepub fn new() -> Self
pub fn new() -> Self
Create new generator with default settings
By default, the generator assumes it’s running inside a Cargo build script, so all warnings
will be emitted as compiler warnings. If the generator is not running inside a build
script, use with_warning_callback.
Sourcepub fn with_warning_callback(warning_cb: fn(Arguments<'_>)) -> Self
pub fn with_warning_callback(warning_cb: fn(Arguments<'_>)) -> Self
Create a generator with a custom callback for emitting warnings
Sourcepub fn configure(&mut self, proto_path: &str, config: Config) -> &mut Self
pub fn configure(&mut self, proto_path: &str, config: Config) -> &mut Self
Apply code generator configurations to Protobuf types and fields. See
Config for possible configuration options.
The proto_path argument is a fully-qualified Protobuf path that points to a package,
type, or field in the compiled .proto files. The configurations are applied to the
element specified by proto_path, as well as its children.
§Example
// Configure field attributes on a specific field of a message type
gen.configure(".pkg.Message.int_field", Config::new().field_attributes("#[serde(skip)]"));
// Configure field attributes on all fields of a message type
gen.configure(".pkg.Message", Config::new().field_attributes("#[serde(skip)]"));
// Configure field attributes on all fields in a package
gen.configure(".pkg", Config::new().field_attributes("#[serde(skip)]"));
// Configure field attributes on all fields
gen.configure(".", Config::new().field_attributes("#[serde(skip)]"));
// Configure types attributes on a specific message type
gen.configure(".pkg.Message", Config::new().type_attributes("#[derive(Serialize)]"));
// Configure boxing behaviour on an oneof in a message type
gen.configure(".pkg.Message.my_oneof", Config::new().boxed(true));
// Configure the int size on a variant of an oneof
gen.configure(".pkg.Message.my_oneof_variant", Config::new().int_size(IntSize::S8));
// Configure the int size of an enum
// Note that enum variants cannot be configured
gen.configure(".pkg.Enum", Config::new().enum_int_size(IntSize::S8));§Special paths
configure also supports special path suffixes for configuring fields in the generated
code that don’t have a corresponding Protobuf path.
// Configure the int size of the elements in a repeated field via ".elem"
gen.configure(".pkg.Message.repeated_field.elem", Config::new().int_size(IntSize::S8));
// Configure the int size of the keys in a map field via ".key"
gen.configure(".pkg.Message.map_field.key", Config::new().int_size(IntSize::S8));
// Configure the int size of the values in a map field via ".value"
gen.configure(".pkg.Message.map_field.value", Config::new().int_size(IntSize::S16));
// Configure the field attributes of hazzer field and the type attributes of
// the hazzer struct in the message via "._has"
gen.configure(".pkg.Message._has",
Config::new().field_attributes("#[serde(skip)]").type_attributes("#[derive(Serialize)]"));
// Configure the field attributes for the unknown handler field of the message via "._unknown"
gen.configure(".pkg.Message._unknown", Config::new().field_attributes("#[serde(skip)]"));
Sourcepub fn configure_many(
&mut self,
proto_paths: &[&str],
config: Config,
) -> &mut Self
pub fn configure_many( &mut self, proto_paths: &[&str], config: Config, ) -> &mut Self
Apply one set of configurations to all provided Protobuf paths.
See configure for how configurations are applied.
Sourcepub fn parse_config_file(
&mut self,
file_path: &Path,
package: &str,
) -> Result<(), Error>
pub fn parse_config_file( &mut self, file_path: &Path, package: &str, ) -> Result<(), Error>
Parse configurations from a TOML file and apply them to the specified Protobuf pacakge.
§Example
For example, if we have the following configuration in build.rs:
let mut gen = micropb_gen::Generator::new();
gen.configure(
".my.pkg.Message.int_field",
Config::new().int_size(IntSize::S16).optional_repr(OptionalRepr::Option)
);
gen.configure("my.pkg.Message.bad_field", Config::new().skip(true));We can instead load the configuration for .my.pkg from a TOML file:
gen.parse_config_file(Path::new("my.pkg.toml"), ".my.pkg")?;my.pkg.toml
# Each Config is represented as a table in the TOML document, keyed by the Protobuf path
["Message.int_field"]
int_size = "S16"
optional_repr = "Option"
["Message.bad_field"]
skip = trueSourcepub fn use_container_heapless(&mut self) -> &mut Self
pub fn use_container_heapless(&mut self) -> &mut Self
Configure the generator to generate heapless containers for Protobuf string, bytes,
repeated, and map fields.
If using this option, micropb should have the container-heapless feature enabled.
Specifically, heapless::String<N> is generated for string fields, heapless::Vec<u8, N>
for bytes fields, heapless::Vec<T, N> for repeated fields, and
heapless::FnvIndexMap<K, V, N> for map fields. This uses configure
under the hood, so configurations set by this call can all be overriden.
§Note
Since heapless containers are fixed size, max_len or
max_bytes must be set for all fields that generate these containers.
Sourcepub fn use_container_arrayvec(&mut self) -> &mut Self
pub fn use_container_arrayvec(&mut self) -> &mut Self
Configure the generator to generate arrayvec containers for Protobuf string, bytes,
and repeated fields.
If using this option, micropb should have the container-arrayvec feature enabled.
Specifically, arrayvec::ArrayString<N> is generated for string fields,
arrayvec::ArrayVec<u8, N> for bytes fields, and arrayvec::ArrayVec<T, N> for repeated
fields. This uses configure under the hood, so configurations set by
this call can all be overriden.
§Note
No container is configured for map fields, since arrayvec doesn’t have a suitable map
type. If the .proto files contain map fields, map_type will need to
be configured separately.
Since arrayvec containers are fixed size, max_len or
max_bytes must be set for all fields that generate these containers.
Sourcepub fn use_container_alloc(&mut self) -> &mut Self
pub fn use_container_alloc(&mut self) -> &mut Self
Configure the generator to generate alloc containers for Protobuf string, bytes,
repeated, and map fields.
If using this option, micropb should have the alloc feature enabled.
Specifically, alloc::string::String is generated for string fields,
alloc::vec::Vec<u8> is for bytes fields, alloc::vec::Vec<T> for repeated fields, and
alloc::collections::BTreeMap<K, V> for map fields. This uses
configure under the hood, so configurations set by this call can all
be overriden by future configurations.
Sourcepub fn use_container_std(&mut self) -> &mut Self
pub fn use_container_std(&mut self) -> &mut Self
Configure the generator to generate std containers for Protobuf string, bytes,
repeated, and map fields.
If using this option, micropb should have the std feature enabled.
Specifically, std::string::String is generated for string fields, std::vec::Vec<u8>
for bytes fields, std::vec::Vec<T> for repeated fields, and
std::collections::HashMap<K, V> for map fields. This uses
configure under the hood, so configurations set by this call can all
be overriden by future configurations.
Sourcepub fn compile_protos(
&mut self,
protos: &[impl AsRef<Path>],
out_filename: impl AsRef<Path>,
) -> Result<()>
pub fn compile_protos( &mut self, protos: &[impl AsRef<Path>], out_filename: impl AsRef<Path>, ) -> Result<()>
Compile .proto files into a single Rust file.
§Example
// build.rs
let mut gen = micropb_gen::Generator::new();
gen.compile_protos(&["server.proto", "client.proto"],
std::env::var("OUT_DIR").unwrap() + "/output.rs").unwrap();Sourcepub fn compile_fdset_file(
&mut self,
fdset_file: impl AsRef<Path>,
out_filename: impl AsRef<Path>,
) -> Result<()>
pub fn compile_fdset_file( &mut self, fdset_file: impl AsRef<Path>, out_filename: impl AsRef<Path>, ) -> Result<()>
Compile a Protobuf file descriptor set into a Rust file.
Similar to compile_protos, but it does not invoke protoc and
instead takes a file descriptor set.
Sourcepub fn retain_enum_prefix(&mut self, retain_enum_prefix: bool) -> &mut Self
pub fn retain_enum_prefix(&mut self, retain_enum_prefix: bool) -> &mut Self
Determine whether the generator strips enum names from variant names.
Protobuf enums commonly include the enum name as a prefix of variant names. micropb
strips this enum name prefix by default. Setting this to true prevents the prefix from
being stripped.
Sourcepub fn format(&mut self, format: bool) -> &mut Self
pub fn format(&mut self, format: bool) -> &mut Self
Determine whether the generator formats the output code.
If the format feature isn’t enabled, this does nothing.
Sourcepub fn encode_decode(&mut self, encode_decode: EncodeDecode) -> &mut Self
pub fn encode_decode(&mut self, encode_decode: EncodeDecode) -> &mut Self
Determine whether to generate logic for encoding and decoding Protobuf messages.
Some applications don’t need to support both encoding and decoding. This setting allows either the encoding or decoding logic to be omitted from the output. By default, both encoding and decoding are included.
This setting allows omitting the encode or decode feature flag from micropb.
Sourcepub fn file_descriptor_set_path<P: Into<PathBuf>>(
&mut self,
path: P,
) -> &mut Self
pub fn file_descriptor_set_path<P: Into<PathBuf>>( &mut self, path: P, ) -> &mut Self
When set, the file descriptor set generated by protoc is written to the provided path,
instead of a temporary directory.
Sourcepub fn add_protoc_arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self
pub fn add_protoc_arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self
Add an argument to the protoc invocation when compiling Protobuf files.
Sourcepub fn extern_type_path<P1: AsRef<str>, P2: AsRef<str>>(
&mut self,
proto_path: P1,
rust_path: P2,
) -> &mut Self
pub fn extern_type_path<P1: AsRef<str>, P2: AsRef<str>>( &mut self, proto_path: P1, rust_path: P2, ) -> &mut Self
Declare an externally-provided Protobuf type.
When compiling a .proto file that imports types from another .proto file, micropb
won’t compile the imported file if it’s not included in the
compile_protos invocation. This is because the imported file may
have already been compiled in another crate. In order to recognize externally-imported
types, use extern_type_path to map the full Protobuf path of the imported type to the
full path of the corresponding Rust type.
§Example
For example, let’s say we have app.proto:
// app.proto
syntax = "proto3";
package app;
message App {
time.Timestamp timestamp = 1;
time.TZ timezone = 2;
}app.proto imports from time.proto, which has already been compiled into the
time crate:
// time.proto
syntax = "proto3";
package time;
message Timestamp {
uint32 ts = 1;
}
enum TZ {
TZ_UTC = 0;
TZ_PST = 1;
}For our application, we’re only interested in compiling app.proto, since time.proto has
already been compiled by another crate. As such, we need to substitute Protobuf types
imported from time.proto with Rust definitions from the time crate.
// build.rs of app
let mut gen = micropb_gen::Generator::new();
// Substitute Timestamp message
gen.extern_type_path(".time.Timestamp", "time::Timestamp");
// Substitute TZ enum
gen.extern_type_path(".time.TZ", "time::Tz");
// Compile only app.proto, not time.proto
gen.compile_protos(&["app.proto"], std::env::var("OUT_DIR").unwrap() + "/output.rs").unwrap();§Note
It’s technically possible to substitute in Rust types that aren’t generated by micropb-gen.
However, the generated code expects substituted messages to implement MessageDecode and
MessageEncode, and substituted enums to have the “open-enum” structure.
Sourcepub fn calculate_max_size(&mut self, flag: bool) -> &mut Self
pub fn calculate_max_size(&mut self, flag: bool) -> &mut Self
Determines whether to generate code to calculate the MAX_SIZE constant on each message.
By default, micropb-gen generates code to calculate the MAX_SIZE associated constant
for each message struct, which determines the max buffer size needed to encode it. If this
is set to false, then it replaces the calculations with None, effectively disabling the
use of MAX_SIZE. This has no runtime impact, but it can reduce the size of the output
file.
Sourcepub fn suffixed_package_names(&mut self, suffixed: bool) -> &mut Self
pub fn suffixed_package_names(&mut self, suffixed: bool) -> &mut Self
Determines whether the modules names generated from package specifiers are suffixed with an underscore.
This is on by default. Even when off, module names like “super” and modules created from from message names will still be suffixed.
Sourcepub fn single_oneof_msg_as_enum(&mut self, as_enum: bool) -> &mut Self
pub fn single_oneof_msg_as_enum(&mut self, as_enum: bool) -> &mut Self
For messages with only a single oneof and no other fields, generate an enum representing the oneof rather than a struct.
§Example
Given the following message:
message Number {
oneof inner {
sint32 signed = 1;
uint32 unsigned = 2;
float fraction = 3;
}
}The following enum type will be generated:
pub enum Number {
Signed(i32),
Unsigned(u32),
Fraction(f32),
None,
}All other message structures, including those with multiple oneofs or a single oneof plus normal fields, will be generated as normal message structs.
§Ignored configs
With this option, configurations that apply to the oneof itself (.Number.inner) will be
ignored. Also, unknown_handler will be ignored.
Sourcepub fn comments_to_docs(&mut self, flag: bool) -> &mut Self
pub fn comments_to_docs(&mut self, flag: bool) -> &mut Self
If enabled, comments in the Proto file will be used to generate doc comments on the messages, enums, oneofs, and fields in the generated code.
Enabled by default.