templater: move Box::new() wrapping to language.wrap_() functions

Now all callers do wrap_<type>(Box::new(...)), so its responsibility can be
moved to the callee without extra boxing.
This commit is contained in:
Yuya Nishihara 2023-03-08 15:05:38 +09:00
parent 96f4d8798c
commit 6af265a388
3 changed files with 68 additions and 91 deletions

View file

@ -76,23 +76,23 @@ impl<'repo> TemplateLanguage<'repo> for CommitTemplateLanguage<'repo, '_> {
impl<'repo> CommitTemplateLanguage<'repo, '_> { impl<'repo> CommitTemplateLanguage<'repo, '_> {
fn wrap_commit_or_change_id( fn wrap_commit_or_change_id(
&self, &self,
property: Box<dyn TemplateProperty<Commit, Output = CommitOrChangeId<'repo>> + 'repo>, property: impl TemplateProperty<Commit, Output = CommitOrChangeId<'repo>> + 'repo,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::CommitOrChangeId(property) CommitTemplatePropertyKind::CommitOrChangeId(Box::new(property))
} }
fn wrap_commit_or_change_id_list( fn wrap_commit_or_change_id_list(
&self, &self,
property: Box<dyn TemplateProperty<Commit, Output = Vec<CommitOrChangeId<'repo>>> + 'repo>, property: impl TemplateProperty<Commit, Output = Vec<CommitOrChangeId<'repo>>> + 'repo,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::CommitOrChangeIdList(property) CommitTemplatePropertyKind::CommitOrChangeIdList(Box::new(property))
} }
fn wrap_shortest_id_prefix( fn wrap_shortest_id_prefix(
&self, &self,
property: Box<dyn TemplateProperty<Commit, Output = ShortestIdPrefix> + 'repo>, property: impl TemplateProperty<Commit, Output = ShortestIdPrefix> + 'repo,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::ShortestIdPrefix(property) CommitTemplatePropertyKind::ShortestIdPrefix(Box::new(property))
} }
} }
@ -145,15 +145,13 @@ fn build_commit_keyword<'repo>(
name: &str, name: &str,
span: pest::Span, span: pest::Span,
) -> TemplateParseResult<CommitTemplatePropertyKind<'repo>> { ) -> TemplateParseResult<CommitTemplatePropertyKind<'repo>> {
fn wrap_fn<'repo, O>( fn wrap_fn<O, F: Fn(&Commit) -> O>(f: F) -> TemplatePropertyFn<F> {
f: impl Fn(&Commit) -> O + 'repo, TemplatePropertyFn(f)
) -> Box<dyn TemplateProperty<Commit, Output = O> + 'repo> {
Box::new(TemplatePropertyFn(f))
} }
fn wrap_repo_fn<'repo, O>( fn wrap_repo_fn<'repo, O>(
repo: &'repo dyn Repo, repo: &'repo dyn Repo,
f: impl Fn(&dyn Repo, &Commit) -> O + 'repo, f: impl Fn(&dyn Repo, &Commit) -> O + 'repo,
) -> Box<dyn TemplateProperty<Commit, Output = O> + 'repo> { ) -> impl TemplateProperty<Commit, Output = O> + 'repo {
wrap_fn(move |commit| f(repo, commit)) wrap_fn(move |commit| f(repo, commit))
} }
@ -370,17 +368,17 @@ fn build_commit_or_change_id_method<'repo>(
let property = match function.name { let property = match function.name {
"short" => { "short" => {
let len_property = parse_optional_integer(function)?; let len_property = parse_optional_integer(function)?;
language.wrap_string(Box::new(TemplateFunction::new( language.wrap_string(TemplateFunction::new(
(self_property, len_property), (self_property, len_property),
|(id, len)| id.short(len.and_then(|l| l.try_into().ok()).unwrap_or(12)), |(id, len)| id.short(len.and_then(|l| l.try_into().ok()).unwrap_or(12)),
))) ))
} }
"shortest" => { "shortest" => {
let len_property = parse_optional_integer(function)?; let len_property = parse_optional_integer(function)?;
language.wrap_shortest_id_prefix(Box::new(TemplateFunction::new( language.wrap_shortest_id_prefix(TemplateFunction::new(
(self_property, len_property), (self_property, len_property),
|(id, len)| id.shortest(len.and_then(|l| l.try_into().ok()).unwrap_or(0)), |(id, len)| id.shortest(len.and_then(|l| l.try_into().ok()).unwrap_or(0)),
))) ))
} }
_ => { _ => {
return Err(TemplateParseError::no_such_method( return Err(TemplateParseError::no_such_method(
@ -427,25 +425,21 @@ fn build_shortest_id_prefix_method<'repo>(
let property = match function.name { let property = match function.name {
"prefix" => { "prefix" => {
template_parser::expect_no_arguments(function)?; template_parser::expect_no_arguments(function)?;
language.wrap_string(Box::new(TemplateFunction::new(self_property, |id| { language.wrap_string(TemplateFunction::new(self_property, |id| id.prefix))
id.prefix
})))
} }
"rest" => { "rest" => {
template_parser::expect_no_arguments(function)?; template_parser::expect_no_arguments(function)?;
language.wrap_string(Box::new(TemplateFunction::new(self_property, |id| id.rest))) language.wrap_string(TemplateFunction::new(self_property, |id| id.rest))
} }
"upper" => { "upper" => {
template_parser::expect_no_arguments(function)?; template_parser::expect_no_arguments(function)?;
language.wrap_shortest_id_prefix(Box::new(TemplateFunction::new(self_property, |id| { language
id.to_upper() .wrap_shortest_id_prefix(TemplateFunction::new(self_property, |id| id.to_upper()))
})))
} }
"lower" => { "lower" => {
template_parser::expect_no_arguments(function)?; template_parser::expect_no_arguments(function)?;
language.wrap_shortest_id_prefix(Box::new(TemplateFunction::new(self_property, |id| { language
id.to_lower() .wrap_shortest_id_prefix(TemplateFunction::new(self_property, |id| id.to_lower()))
})))
} }
_ => { _ => {
return Err(TemplateParseError::no_such_method( return Err(TemplateParseError::no_such_method(

View file

@ -62,9 +62,9 @@ impl TemplateLanguage<'static> for OperationTemplateLanguage<'_> {
impl OperationTemplateLanguage<'_> { impl OperationTemplateLanguage<'_> {
fn wrap_operation_id( fn wrap_operation_id(
&self, &self,
property: Box<dyn TemplateProperty<Operation, Output = OperationId>>, property: impl TemplateProperty<Operation, Output = OperationId> + 'static,
) -> OperationTemplatePropertyKind { ) -> OperationTemplatePropertyKind {
OperationTemplatePropertyKind::OperationId(property) OperationTemplatePropertyKind::OperationId(Box::new(property))
} }
} }
@ -110,14 +110,12 @@ fn build_operation_keyword(
name: &str, name: &str,
span: pest::Span, span: pest::Span,
) -> TemplateParseResult<OperationTemplatePropertyKind> { ) -> TemplateParseResult<OperationTemplatePropertyKind> {
fn wrap_fn<O>( fn wrap_fn<O, F: Fn(&Operation) -> O>(f: F) -> TemplatePropertyFn<F> {
f: impl Fn(&Operation) -> O + 'static, TemplatePropertyFn(f)
) -> Box<dyn TemplateProperty<Operation, Output = O>> {
Box::new(TemplatePropertyFn(f))
} }
fn wrap_metadata_fn<O>( fn wrap_metadata_fn<O>(
f: impl Fn(&OperationMetadata) -> O + 'static, f: impl Fn(&OperationMetadata) -> O + 'static,
) -> Box<dyn TemplateProperty<Operation, Output = O>> { ) -> impl TemplateProperty<Operation, Output = O> {
wrap_fn(move |op| f(&op.store_operation().metadata)) wrap_fn(move |op| f(&op.store_operation().metadata))
} }
@ -168,14 +166,14 @@ fn build_operation_id_method(
let len_property = len_node let len_property = len_node
.map(|node| template_parser::expect_integer_expression(language, node)) .map(|node| template_parser::expect_integer_expression(language, node))
.transpose()?; .transpose()?;
language.wrap_string(Box::new(TemplateFunction::new( language.wrap_string(TemplateFunction::new(
(self_property, len_property), (self_property, len_property),
|(id, len)| { |(id, len)| {
let mut hex = id.hex(); let mut hex = id.hex();
hex.truncate(len.and_then(|l| l.try_into().ok()).unwrap_or(12)); hex.truncate(len.and_then(|l| l.try_into().ok()).unwrap_or(12));
hex hex
}, },
))) ))
} }
_ => return Err(TemplateParseError::no_such_method("OperationId", function)), _ => return Err(TemplateParseError::no_such_method("OperationId", function)),
}; };

View file

@ -594,27 +594,27 @@ pub trait TemplateLanguage<'a> {
fn wrap_string( fn wrap_string(
&self, &self,
property: Box<dyn TemplateProperty<Self::Context, Output = String> + 'a>, property: impl TemplateProperty<Self::Context, Output = String> + 'a,
) -> Self::Property; ) -> Self::Property;
fn wrap_boolean( fn wrap_boolean(
&self, &self,
property: Box<dyn TemplateProperty<Self::Context, Output = bool> + 'a>, property: impl TemplateProperty<Self::Context, Output = bool> + 'a,
) -> Self::Property; ) -> Self::Property;
fn wrap_integer( fn wrap_integer(
&self, &self,
property: Box<dyn TemplateProperty<Self::Context, Output = i64> + 'a>, property: impl TemplateProperty<Self::Context, Output = i64> + 'a,
) -> Self::Property; ) -> Self::Property;
fn wrap_signature( fn wrap_signature(
&self, &self,
property: Box<dyn TemplateProperty<Self::Context, Output = Signature> + 'a>, property: impl TemplateProperty<Self::Context, Output = Signature> + 'a,
) -> Self::Property; ) -> Self::Property;
fn wrap_timestamp( fn wrap_timestamp(
&self, &self,
property: Box<dyn TemplateProperty<Self::Context, Output = Timestamp> + 'a>, property: impl TemplateProperty<Self::Context, Output = Timestamp> + 'a,
) -> Self::Property; ) -> Self::Property;
fn wrap_timestamp_range( fn wrap_timestamp_range(
&self, &self,
property: Box<dyn TemplateProperty<Self::Context, Output = TimestampRange> + 'a>, property: impl TemplateProperty<Self::Context, Output = TimestampRange> + 'a,
) -> Self::Property; ) -> Self::Property;
fn build_keyword(&self, name: &str, span: pest::Span) -> TemplateParseResult<Self::Property>; fn build_keyword(&self, name: &str, span: pest::Span) -> TemplateParseResult<Self::Property>;
@ -652,12 +652,11 @@ macro_rules! impl_wrap_property_fns {
$( $(
fn $func( fn $func(
&self, &self,
property: Box< property: impl $crate::templater::TemplateProperty<
dyn $crate::templater::TemplateProperty<Self::Context, Output = $ty> + $a Self::Context, Output = $ty> + $a,
>,
) -> Self::Property { ) -> Self::Property {
use $kind as Kind; // https://github.com/rust-lang/rust/issues/48067 use $kind as Kind; // https://github.com/rust-lang/rust/issues/48067
$outer(Kind::$var(property)) $outer(Kind::$var(Box::new(property)))
} }
)+ )+
}; };
@ -885,28 +884,24 @@ fn build_string_method<'a, L: TemplateLanguage<'a>>(
let [needle_node] = expect_exact_arguments(function)?; let [needle_node] = expect_exact_arguments(function)?;
// TODO: or .try_into_string() to disable implicit type cast? // TODO: or .try_into_string() to disable implicit type cast?
let needle_property = build_expression(language, needle_node)?.into_plain_text(); let needle_property = build_expression(language, needle_node)?.into_plain_text();
language.wrap_boolean(Box::new(TemplateFunction::new( language.wrap_boolean(TemplateFunction::new(
(self_property, needle_property), (self_property, needle_property),
|(haystack, needle)| haystack.contains(&needle), |(haystack, needle)| haystack.contains(&needle),
))) ))
} }
"first_line" => { "first_line" => {
expect_no_arguments(function)?; expect_no_arguments(function)?;
language.wrap_string(Box::new(TemplateFunction::new(self_property, |s| { language.wrap_string(TemplateFunction::new(self_property, |s| {
s.lines().next().unwrap_or_default().to_string() s.lines().next().unwrap_or_default().to_string()
}))) }))
} }
"upper" => { "upper" => {
expect_no_arguments(function)?; expect_no_arguments(function)?;
language.wrap_string(Box::new(TemplateFunction::new(self_property, |s| { language.wrap_string(TemplateFunction::new(self_property, |s| s.to_uppercase()))
s.to_uppercase()
})))
} }
"lower" => { "lower" => {
expect_no_arguments(function)?; expect_no_arguments(function)?;
language.wrap_string(Box::new(TemplateFunction::new(self_property, |s| { language.wrap_string(TemplateFunction::new(self_property, |s| s.to_lowercase()))
s.to_lowercase()
})))
} }
_ => return Err(TemplateParseError::no_such_method("String", function)), _ => return Err(TemplateParseError::no_such_method("String", function)),
}; };
@ -937,34 +932,28 @@ fn build_signature_method<'a, L: TemplateLanguage<'a>>(
let property = match function.name { let property = match function.name {
"name" => { "name" => {
expect_no_arguments(function)?; expect_no_arguments(function)?;
language.wrap_string(Box::new(TemplateFunction::new( language.wrap_string(TemplateFunction::new(self_property, |signature| {
self_property, signature.name
|signature| signature.name, }))
)))
} }
"email" => { "email" => {
expect_no_arguments(function)?; expect_no_arguments(function)?;
language.wrap_string(Box::new(TemplateFunction::new( language.wrap_string(TemplateFunction::new(self_property, |signature| {
self_property, signature.email
|signature| signature.email, }))
)))
} }
"username" => { "username" => {
expect_no_arguments(function)?; expect_no_arguments(function)?;
language.wrap_string(Box::new(TemplateFunction::new( language.wrap_string(TemplateFunction::new(self_property, |signature| {
self_property, let (username, _) = split_email(&signature.email);
|signature| { username.to_owned()
let (username, _) = split_email(&signature.email); }))
username.to_owned()
},
)))
} }
"timestamp" => { "timestamp" => {
expect_no_arguments(function)?; expect_no_arguments(function)?;
language.wrap_timestamp(Box::new(TemplateFunction::new( language.wrap_timestamp(TemplateFunction::new(self_property, |signature| {
self_property, signature.timestamp
|signature| signature.timestamp, }))
)))
} }
_ => return Err(TemplateParseError::no_such_method("Signature", function)), _ => return Err(TemplateParseError::no_such_method("Signature", function)),
}; };
@ -979,10 +968,9 @@ fn build_timestamp_method<'a, L: TemplateLanguage<'a>>(
let property = match function.name { let property = match function.name {
"ago" => { "ago" => {
expect_no_arguments(function)?; expect_no_arguments(function)?;
language.wrap_string(Box::new(TemplateFunction::new( language.wrap_string(TemplateFunction::new(self_property, |timestamp| {
self_property, time_util::format_timestamp_relative_to_now(&timestamp)
|timestamp| time_util::format_timestamp_relative_to_now(&timestamp), }))
)))
} }
_ => return Err(TemplateParseError::no_such_method("Timestamp", function)), _ => return Err(TemplateParseError::no_such_method("Timestamp", function)),
}; };
@ -997,24 +985,21 @@ fn build_timestamp_range_method<'a, L: TemplateLanguage<'a>>(
let property = match function.name { let property = match function.name {
"start" => { "start" => {
expect_no_arguments(function)?; expect_no_arguments(function)?;
language.wrap_timestamp(Box::new(TemplateFunction::new( language.wrap_timestamp(TemplateFunction::new(self_property, |time_range| {
self_property, time_range.start
|time_range| time_range.start, }))
)))
} }
"end" => { "end" => {
expect_no_arguments(function)?; expect_no_arguments(function)?;
language.wrap_timestamp(Box::new(TemplateFunction::new( language.wrap_timestamp(TemplateFunction::new(self_property, |time_range| {
self_property, time_range.end
|time_range| time_range.end, }))
)))
} }
"duration" => { "duration" => {
expect_no_arguments(function)?; expect_no_arguments(function)?;
language.wrap_string(Box::new(TemplateFunction::new( language.wrap_string(TemplateFunction::new(self_property, |time_range| {
self_property, time_range.duration()
|time_range| time_range.duration(), }))
)))
} }
_ => { _ => {
return Err(TemplateParseError::no_such_method( return Err(TemplateParseError::no_such_method(
@ -1108,11 +1093,11 @@ pub fn build_expression<'a, L: TemplateLanguage<'a>>(
Ok(Expression::Property(property, labels)) Ok(Expression::Property(property, labels))
} }
ExpressionKind::Integer(value) => { ExpressionKind::Integer(value) => {
let property = language.wrap_integer(Box::new(Literal(*value))); let property = language.wrap_integer(Literal(*value));
Ok(Expression::Property(property, vec![])) Ok(Expression::Property(property, vec![]))
} }
ExpressionKind::String(value) => { ExpressionKind::String(value) => {
let property = language.wrap_string(Box::new(Literal(value.clone()))); let property = language.wrap_string(Literal(value.clone()));
Ok(Expression::Property(property, vec![])) Ok(Expression::Property(property, vec![]))
} }
ExpressionKind::List(nodes) => { ExpressionKind::List(nodes) => {