From 0a64a09158eee89f04700b5761c474d9feb11a16 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Tue, 20 Feb 2024 20:15:36 +0100 Subject: [PATCH] prost-build: optimise derived prost::Name (#956) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- prost-build/src/code_generator.rs | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/prost-build/src/code_generator.rs b/prost-build/src/code_generator.rs index a6a06d484..4f348baaf 100644 --- a/prost-build/src/code_generator.rs +++ b/prost-build/src/code_generator.rs @@ -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");