Skip to content

Commit

Permalink
Add include_file_descriptor_set to prost-build
Browse files Browse the repository at this point in the history
This commit adds support for writing an encoded version of the
appropriate FileDescriptorSet to a file named `file_descriptor_set.bin`
in the output directory. This can be used with the `include_bytes` macro
by consuming applications or libraries.

The rationale for this pull request is to support the gRPC Server
Reflection Protocol, which operates in terms of FileDescriptorProto, in
Tonic. FileDescriptorProto instances are contained inside a
FileDescriptorSet.
  • Loading branch information
jen20 committed Nov 28, 2020
1 parent b664fef commit 286c0cc
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 2 deletions.
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ Compared to other Protocol Buffers implementations, `prost`
* Respects the Protobuf `package` specifier when organizing generated code
into Rust modules.
* Preserves unknown enum values during deserialization.
* Does not include support for runtime reflection or message descriptors.
* Does not include support for runtime reflection or message descriptors, but
allows encoded `FileDescriptorSet` messages to be saved alongside generated
code for use of consumers.

## Using `prost` in a Cargo Project

Expand Down Expand Up @@ -59,6 +61,12 @@ package foo.bar;

All Rust types generated from the file will be in the `foo::bar` module.

If the `include_file_descriptor_set` option is set on the `prost_build::Config`
for the invocation of `prost_build`, an additional file named `file_descriptor_set.bin`
will be written to the output directory. This can be used in conjunction with the
`include_bytes` macro, and decoded using the `FileDescriptorSet` type from the
`prost-types` crate in applications or libraries using Prost.

### Messages

Given a simple message declaration:
Expand Down
19 changes: 18 additions & 1 deletion prost-build/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ use std::env;
use std::ffi::{OsStr, OsString};
use std::fmt;
use std::fs;
use std::io::{Error, ErrorKind, Result};
use std::io::{Error, ErrorKind, Result, Write};
use std::path::{Path, PathBuf};
use std::process::Command;

Expand Down Expand Up @@ -183,6 +183,7 @@ pub trait ServiceGenerator {
///
/// This configuration builder can be used to set non-default code generation options.
pub struct Config {
include_file_descriptor_set: bool,
service_generator: Option<Box<dyn ServiceGenerator>>,
btree_map: Vec<String>,
bytes: Vec<String>,
Expand Down Expand Up @@ -522,6 +523,15 @@ impl Config {
self
}

/// Configures the code generator to output the encoded bytes of the `FileDescriptorSet`
/// for this `protoc` invocation to a file named `file_descriptor_set.bin` in the configured
/// output directory. This can be used in conjunction with the `include_bytes!` macro and
/// the types in the `prost-types` crate for implementing some reflection capabilities.
pub fn include_file_descriptor_set(&mut self) -> &mut Self {
self.include_file_descriptor_set = true;
self
}

/// Configures the code generator to not strip the enum name from variant names.
///
/// Protobuf enum definitions commonly include the enum name as a prefix of every variant name.
Expand Down Expand Up @@ -644,6 +654,12 @@ impl Config {
)
})?;

if self.include_file_descriptor_set {
let filename = target.join("file_descriptor_set.bin");
let mut file = std::fs::File::create(filename)?;
file.write_all(&buf)?;
}

let modules = self.generate(descriptor_set.file)?;
for (module, content) in modules {
let mut filename = module.join(".");
Expand Down Expand Up @@ -710,6 +726,7 @@ impl Config {
impl default::Default for Config {
fn default() -> Config {
Config {
include_file_descriptor_set: false,
service_generator: None,
btree_map: Vec::new(),
bytes: Vec::new(),
Expand Down

0 comments on commit 286c0cc

Please sign in to comment.