Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master' into sink
Browse files Browse the repository at this point in the history
# Conflicts:
#	Cargo.toml
  • Loading branch information
Jasperav committed Dec 28, 2023
2 parents adb204d + 907e9f6 commit ce0c421
Show file tree
Hide file tree
Showing 15 changed files with 185 additions and 31 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:
matrix:
toolchain:
- stable
- "1.64"
- "1.65"
os:
- ubuntu-latest
- macos-latest
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "prost"
version = "0.12.1"
version = "0.12.3"
authors = [
"Dan Burkert <[email protected]>",
"Lucio Franco <[email protected]",
Expand Down Expand Up @@ -49,7 +49,7 @@ std = []

[dependencies]
bytes = { version = "1", default-features = false }
prost-derive = { version = "0.12.1", path = "prost-derive", optional = true }
prost-derive = { version = "0.12.3", path = "prost-derive", optional = true }
uuid = { version = "1", features = ["v4"] }

[dev-dependencies]
Expand Down
6 changes: 3 additions & 3 deletions prost-build/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "prost-build"
version = "0.12.1"
version = "0.12.3"
authors = [
"Dan Burkert <[email protected]>",
"Lucio Franco <[email protected]>",
Expand All @@ -27,8 +27,8 @@ itertools = { version = ">=0.10, <0.12", default-features = false, features = ["
log = "0.4"
multimap = { version = "0.8", default-features = false }
petgraph = { version = "0.6", default-features = false }
prost = { version = "0.12.1", path = "..", default-features = false }
prost-types = { version = "0.12.1", path = "../prost-types", default-features = false }
prost = { version = "0.12.3", path = "..", default-features = false }
prost-types = { version = "0.12.3", path = "../prost-types", default-features = false }
tempfile = "3"
once_cell = "1.17.1"
regex = { version = "1.8.1", default-features = false, features = ["std", "unicode-bool"] }
Expand Down
90 changes: 77 additions & 13 deletions prost-build/src/code_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ enum Syntax {
pub struct CodeGenerator<'a> {
config: &'a mut Config,
package: String,
type_path: Vec<String>,
source_info: Option<SourceCodeInfo>,
syntax: Syntax,
message_graph: &'a MessageGraph,
Expand Down Expand Up @@ -69,6 +70,7 @@ impl<'a> CodeGenerator<'a> {
let mut code_gen = CodeGenerator {
config,
package: file.package.unwrap_or_default(),
type_path: Vec::new(),
source_info,
syntax,
message_graph,
Expand Down Expand Up @@ -121,10 +123,16 @@ impl<'a> CodeGenerator<'a> {

let message_name = message.name().to_string();
let fq_message_name = format!(
"{}{}.{}",
if self.package.is_empty() { "" } else { "." },
self.package,
message.name()
"{}{}{}{}.{}",
if self.package.is_empty() && self.type_path.is_empty() {
""
} else {
"."
},
self.package.trim_matches('.'),
if self.type_path.is_empty() { "" } else { "." },
self.type_path.join("."),
message_name,
);

// Skip external types.
Expand Down Expand Up @@ -261,6 +269,53 @@ impl<'a> CodeGenerator<'a> {

self.pop_mod();
}

if self.config.enable_type_names {
self.append_type_name(&message_name, &fq_message_name);
}
}

fn append_type_name(&mut self, message_name: &str, fq_message_name: &str) {
self.buf.push_str(&format!(
"impl {}::Name for {} {{\n",
self.config.prost_path.as_deref().unwrap_or("::prost"),
to_upper_camel(&message_name)
));
self.depth += 1;

self.buf.push_str(&format!(
"const NAME: &'static str = \"{}\";\n",
message_name,
));
self.buf.push_str(&format!(
"const PACKAGE: &'static str = \"{}\";\n",
self.package,
));

let prost_path = self.config.prost_path.as_deref().unwrap_or("::prost");
let string_path = format!("{}::alloc::string::String", prost_path);
let format_path = format!("{}::alloc::format", prost_path);

self.buf.push_str(&format!(
r#"fn full_name() -> {string_path} {{
{format_path}!("{}{}{}{}{{}}", Self::NAME)
}}"#,
self.package.trim_matches('.'),
if self.package.is_empty() { "" } else { "." },
self.type_path.join("."),
if self.type_path.is_empty() { "" } else { "." },
));

if let Some(domain_name) = self.config.type_name_domains.get_first(fq_message_name) {
self.buf.push_str(&format!(
r#"fn type_url() -> {string_path} {{
{format_path}!("{domain_name}/{{}}", Self::full_name())
}}"#,
));
}

self.depth -= 1;
self.buf.push_str("}\n");
}

fn append_type_attributes(&mut self, fq_message_name: &str) {
Expand Down Expand Up @@ -675,11 +730,18 @@ impl<'a> CodeGenerator<'a> {

let enum_values = &desc.value;
let fq_proto_enum_name = format!(
"{}{}.{}",
if self.package.is_empty() { "" } else { "." },
self.package,
proto_enum_name
"{}{}{}{}.{}",
if self.package.is_empty() && self.type_path.is_empty() {
""
} else {
"."
},
self.package.trim_matches('.'),
if self.type_path.is_empty() { "" } else { "." },
self.type_path.join("."),
proto_enum_name,
);

if self
.extern_paths
.resolve_ident(&fq_proto_enum_name)
Expand Down Expand Up @@ -897,17 +959,15 @@ impl<'a> CodeGenerator<'a> {
self.buf.push_str(&to_snake(module));
self.buf.push_str(" {\n");

self.package.push('.');
self.package.push_str(module);
self.type_path.push(module.into());

self.depth += 1;
}

fn pop_mod(&mut self) {
self.depth -= 1;

let idx = self.package.rfind('.').unwrap();
self.package.truncate(idx);
self.type_path.pop();

self.push_indent();
self.buf.push_str("}\n");
Expand Down Expand Up @@ -957,7 +1017,11 @@ impl<'a> CodeGenerator<'a> {
return proto_ident;
}

let mut local_path = self.package.split('.').peekable();
let mut local_path = self
.package
.split('.')
.chain(self.type_path.iter().map(String::as_str))
.peekable();

// If no package is specified the start of the package name will be '.'
// and split will return an empty string ("") which breaks resolution
Expand Down
48 changes: 47 additions & 1 deletion prost-build/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![doc(html_root_url = "https://docs.rs/prost-build/0.12.1")]
#![doc(html_root_url = "https://docs.rs/prost-build/0.12.2")]
#![allow(clippy::option_as_ref_deref, clippy::format_push_string)]

//! `prost-build` compiles `.proto` files into Rust.
Expand Down Expand Up @@ -259,6 +259,8 @@ pub struct Config {
out_dir: Option<PathBuf>,
extern_paths: Vec<(String, String)>,
default_package_filename: String,
enable_type_names: bool,
type_name_domains: PathMap<String>,
protoc_args: Vec<OsString>,
disable_comments: PathMap<()>,
custom_type: PathMap<CustomType>,
Expand Down Expand Up @@ -866,6 +868,46 @@ impl Config {
self
}

/// Configures the code generator to include type names.
///
/// Message types will implement `Name` trait, which provides type and package name.
/// This is needed for encoding messages as `Any` type.
pub fn enable_type_names(&mut self) -> &mut Self {
self.enable_type_names = true;
self
}

/// Specify domain names to use with message type URLs.
///
/// # Domains
///
/// **`paths`** - a path matching any number of types. It works the same way as in
/// [`btree_map`](#method.btree_map), just with the field name omitted.
///
/// **`domain`** - an arbitrary string to be used as a prefix for type URLs.
///
/// # Examples
///
/// ```rust
/// # let mut config = prost_build::Config::new();
/// // Full type URL of the message `google.profile.Person`,
/// // will be `type.googleapis.com/google.profile.Person`.
/// config.type_name_domain(&["."], "type.googleapis.com");
/// ```
pub fn type_name_domain<I, S, D>(&mut self, paths: I, domain: D) -> &mut Self
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
D: AsRef<str>,
{
self.type_name_domains.clear();
for matcher in paths {
self.type_name_domains
.insert(matcher.as_ref().to_string(), domain.as_ref().to_string());
}
self
}

/// Configures the path that's used for deriving `Message` for generated messages.
/// This is mainly useful for generating crates that wish to re-export prost.
/// Defaults to `::prost::Message` if not specified.
Expand Down Expand Up @@ -1321,6 +1363,8 @@ impl default::Default for Config {
out_dir: None,
extern_paths: Vec::new(),
default_package_filename: "_".to_string(),
enable_type_names: false,
type_name_domains: PathMap::default(),
protoc_args: Vec::new(),
disable_comments: PathMap::default(),
custom_type: PathMap::default(),
Expand Down Expand Up @@ -1349,6 +1393,8 @@ impl fmt::Debug for Config {
.field("out_dir", &self.out_dir)
.field("extern_paths", &self.extern_paths)
.field("default_package_filename", &self.default_package_filename)
.field("enable_type_names", &self.enable_type_names)
.field("type_name_domains", &self.type_name_domains)
.field("protoc_args", &self.protoc_args)
.field("disable_comments", &self.disable_comments)
.field("skip_debug", &self.skip_debug)
Expand Down
2 changes: 1 addition & 1 deletion prost-derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "prost-derive"
version = "0.12.1"
version = "0.12.3"
authors = [
"Dan Burkert <[email protected]>",
"Lucio Franco <[email protected]>",
Expand Down
2 changes: 1 addition & 1 deletion prost-derive/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![doc(html_root_url = "https://docs.rs/prost-derive/0.12.1")]
#![doc(html_root_url = "https://docs.rs/prost-derive/0.12.2")]
// The `quote!` macro requires deep recursion.
#![recursion_limit = "4096"]

Expand Down
4 changes: 2 additions & 2 deletions prost-types/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "prost-types"
version = "0.12.1"
version = "0.12.3"
authors = [
"Dan Burkert <[email protected]>",
"Lucio Franco <[email protected]",
Expand All @@ -22,7 +22,7 @@ default = ["std"]
std = ["prost/std"]

[dependencies]
prost = { version = "0.12.1", path = "..", default-features = false, features = ["prost-derive"] }
prost = { version = "0.12.3", path = "..", default-features = false, features = ["prost-derive"] }

[dev-dependencies]
proptest = "1"
2 changes: 1 addition & 1 deletion prost-types/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![doc(html_root_url = "https://docs.rs/prost-types/0.12.1")]
#![doc(html_root_url = "https://docs.rs/prost-types/0.12.2")]

//! Protocol Buffers well-known types.
//!
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![doc(html_root_url = "https://docs.rs/prost/0.12.1")]
#![doc(html_root_url = "https://docs.rs/prost/0.12.2")]
#![cfg_attr(not(feature = "std"), no_std)]
#![doc = include_str!("../README.md")]

Expand Down
14 changes: 9 additions & 5 deletions src/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,27 @@ use alloc::{format, string::String};

/// Associate a type name with a [`Message`] type.
pub trait Name: Message {
/// Type name for this [`Message`]. This is the camel case name,
/// e.g. `TypeName`.
/// Simple name for this [`Message`].
/// This name is the same as it appears in the source .proto file, e.g. `FooBar`.
const NAME: &'static str;

/// Package name this message type is contained in. They are domain-like
/// and delimited by `.`, e.g. `google.protobuf`.
const PACKAGE: &'static str;

/// Full name of this message type containing both the package name and
/// type name, e.g. `google.protobuf.TypeName`.
/// Fully-qualified unique name for this [`Message`].
/// It's prefixed with the package name and names of any parent messages,
/// e.g. `google.rpc.BadRequest.FieldViolation`.
/// By default, this is the package name followed by the message name.
/// Fully-qualified names must be unique within a domain of Type URLs.
fn full_name() -> String {
format!("{}.{}", Self::PACKAGE, Self::NAME)
}

/// Type URL for this message, which by default is the full name with a
/// Type URL for this [`Message`], which by default is the full name with a
/// leading slash, but may also include a leading domain name, e.g.
/// `type.googleapis.com/google.profile.Person`.
/// This can be used when serializing with the [`Any`] type.
fn type_url() -> String {
format!("/{}", Self::full_name())
}
Expand Down
6 changes: 6 additions & 0 deletions tests/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,12 @@ fn main() {
)
.unwrap();

prost_build::Config::new()
.enable_type_names()
.type_name_domain(&[".type_names.Foo"], "tests")
.compile_protos(&[src.join("type_names.proto")], includes)
.unwrap();

// Check that attempting to compile a .proto without a package declaration does not result in an error.
config
.compile_protos(&[src.join("no_package.proto")], includes)
Expand Down
2 changes: 2 additions & 0 deletions tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ mod no_unused_results;
#[cfg(test)]
#[cfg(feature = "std")]
mod skip_debug;
#[cfg(test)]
mod type_names;

mod test_enum_named_option_value {
include!(concat!(env!("OUT_DIR"), "/myenum.optionn.rs"));
Expand Down
11 changes: 11 additions & 0 deletions tests/src/type_names.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
syntax = "proto3";

package type_names;

message Foo {
message Bar {
}
}

message Baz {
}
Loading

0 comments on commit ce0c421

Please sign in to comment.