Skip to content

Commit

Permalink
prost-build: optimise derived prost::Name (#956)
Browse files Browse the repository at this point in the history
When deriving prost::Name, prost-bulid generates the following code
for full_name and type_url methods:

    fn full_name() -> ::prost::alloc::string::String {
        ::prost::alloc::format!(
            "some.package.{0}", Self::NAME
        )
    }
    fn type_url() -> ::prost::alloc::string::String {
        ::prost::alloc::format!(
            "example.com/{0}", Self::full_name()
        )
    }

With those definitions, type_url:
- allocates a new temporary string,
- formats text into that string,
- allocates another string,
- and once again formats text into that string.

Most of those operations can be done at build time with only a single
string allocation being necessary in type_url method.

Change the generated code such that no formatting happens at run time
and no temporary strings are allocated in type_url, specifically:

    fn full_name() -> ::prost::alloc::string::String {
        "some.package.MessageName".into()
    }
    fn type_url() -> ::prost::alloc::string::String {
        "example.com/some.package.MessageName"
    }

Furthermore, unconditionally derive type_url even if no domain is
specified such that default definition (which uses temporary strings
and formatting) isn’t used.

Co-authored-by: Lucio Franco <luciofranco14@gmail.com>
  • Loading branch information
mina86 and LucioFranco committed Feb 20, 2024
1 parent 54838c6 commit 0a64a09
Showing 1 changed file with 15 additions and 13 deletions.
28 changes: 15 additions & 13 deletions prost-build/src/code_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -293,26 +293,28 @@ impl<'a> CodeGenerator<'a> {
));

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);
let string_path = format!("{prost_path}::alloc::string::String");

self.buf.push_str(&format!(
r#"fn full_name() -> {string_path} {{
{format_path}!("{}{}{}{}{{}}", Self::NAME)
}}"#,
let full_name = format!(
"{}{}{}{}{message_name}",
self.package.trim_matches('.'),
if self.package.is_empty() { "" } else { "." },
self.type_path.join("."),
if self.type_path.is_empty() { "" } else { "." },
);
let domain_name = self
.config
.type_name_domains
.get_first(fq_message_name)
.map_or("", |name| name.as_str());

self.buf.push_str(&format!(
r#"fn full_name() -> {string_path} {{ "{full_name}".into() }}"#,
));

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.buf.push_str(&format!(
r#"fn type_url() -> {string_path} {{ "{domain_name}/{full_name}".into() }}"#,
));

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

0 comments on commit 0a64a09

Please sign in to comment.