templater: add type alias for Box<dyn TemplateProperty<..>>

It's verbose to type.
This commit is contained in:
Yuya Nishihara 2025-04-30 12:22:59 +09:00
parent b96924d17f
commit 1b300fefa2
6 changed files with 130 additions and 160 deletions

View File

@ -177,7 +177,7 @@ use crate::template_builder;
use crate::template_builder::TemplateLanguage;
use crate::template_parser::TemplateAliasesMap;
use crate::template_parser::TemplateDiagnostics;
use crate::templater::TemplateProperty;
use crate::templater::BoxedTemplateProperty;
use crate::templater::TemplateRenderer;
use crate::text_util;
use crate::ui::ColorChoice;
@ -386,7 +386,7 @@ impl CommandHelper {
ui: &Ui,
language: &L,
template_text: &str,
wrap_self: impl Fn(Box<dyn TemplateProperty<Output = C> + 'a>) -> L::Property,
wrap_self: impl Fn(BoxedTemplateProperty<'a, C>) -> L::Property,
) -> Result<TemplateRenderer<'a, C>, CommandError> {
let mut diagnostics = TemplateDiagnostics::new();
let aliases = load_template_aliases(ui, self.settings().config())?;
@ -974,7 +974,7 @@ impl WorkspaceCommandEnvironment {
ui: &Ui,
language: &L,
template_text: &str,
wrap_self: impl Fn(Box<dyn TemplateProperty<Output = C> + 'a>) -> L::Property,
wrap_self: impl Fn(BoxedTemplateProperty<'a, C>) -> L::Property,
) -> Result<TemplateRenderer<'a, C>, CommandError> {
let mut diagnostics = TemplateDiagnostics::new();
let template = template_builder::parse(
@ -1704,7 +1704,7 @@ to the current parents may contain changes from multiple commits.
ui: &Ui,
language: &L,
template_text: &str,
wrap_self: impl Fn(Box<dyn TemplateProperty<Output = C> + 'a>) -> L::Property,
wrap_self: impl Fn(BoxedTemplateProperty<'a, C>) -> L::Property,
) -> Result<TemplateRenderer<'a, C>, CommandError> {
self.env
.parse_template(ui, language, template_text, wrap_self)
@ -1715,7 +1715,7 @@ to the current parents may contain changes from multiple commits.
&self,
language: &L,
template_text: &str,
wrap_self: impl Fn(Box<dyn TemplateProperty<Output = C> + 'a>) -> L::Property,
wrap_self: impl Fn(BoxedTemplateProperty<'a, C>) -> L::Property,
) -> TemplateRenderer<'a, C> {
template_builder::parse(
language,

View File

@ -89,11 +89,11 @@ use crate::template_parser::TemplateDiagnostics;
use crate::template_parser::TemplateParseError;
use crate::template_parser::TemplateParseResult;
use crate::templater;
use crate::templater::BoxedTemplateProperty;
use crate::templater::PlainTextFormattedProperty;
use crate::templater::SizeHint;
use crate::templater::Template;
use crate::templater::TemplateFormatter;
use crate::templater::TemplateProperty;
use crate::templater::TemplatePropertyError;
use crate::templater::TemplatePropertyExt as _;
use crate::text_util;
@ -361,115 +361,115 @@ impl<'repo> CommitTemplateLanguage<'repo> {
}
pub fn wrap_commit(
property: Box<dyn TemplateProperty<Output = Commit> + 'repo>,
property: BoxedTemplateProperty<'repo, Commit>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::Commit(property)
}
pub fn wrap_commit_opt(
property: Box<dyn TemplateProperty<Output = Option<Commit>> + 'repo>,
property: BoxedTemplateProperty<'repo, Option<Commit>>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::CommitOpt(property)
}
pub fn wrap_commit_list(
property: Box<dyn TemplateProperty<Output = Vec<Commit>> + 'repo>,
property: BoxedTemplateProperty<'repo, Vec<Commit>>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::CommitList(property)
}
pub fn wrap_commit_ref(
property: Box<dyn TemplateProperty<Output = Rc<CommitRef>> + 'repo>,
property: BoxedTemplateProperty<'repo, Rc<CommitRef>>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::CommitRef(property)
}
pub fn wrap_commit_ref_opt(
property: Box<dyn TemplateProperty<Output = Option<Rc<CommitRef>>> + 'repo>,
property: BoxedTemplateProperty<'repo, Option<Rc<CommitRef>>>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::CommitRefOpt(property)
}
pub fn wrap_commit_ref_list(
property: Box<dyn TemplateProperty<Output = Vec<Rc<CommitRef>>> + 'repo>,
property: BoxedTemplateProperty<'repo, Vec<Rc<CommitRef>>>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::CommitRefList(property)
}
pub fn wrap_repo_path(
property: Box<dyn TemplateProperty<Output = RepoPathBuf> + 'repo>,
property: BoxedTemplateProperty<'repo, RepoPathBuf>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::RepoPath(property)
}
pub fn wrap_repo_path_opt(
property: Box<dyn TemplateProperty<Output = Option<RepoPathBuf>> + 'repo>,
property: BoxedTemplateProperty<'repo, Option<RepoPathBuf>>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::RepoPathOpt(property)
}
pub fn wrap_commit_or_change_id(
property: Box<dyn TemplateProperty<Output = CommitOrChangeId> + 'repo>,
property: BoxedTemplateProperty<'repo, CommitOrChangeId>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::CommitOrChangeId(property)
}
pub fn wrap_shortest_id_prefix(
property: Box<dyn TemplateProperty<Output = ShortestIdPrefix> + 'repo>,
property: BoxedTemplateProperty<'repo, ShortestIdPrefix>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::ShortestIdPrefix(property)
}
pub fn wrap_tree_diff(
property: Box<dyn TemplateProperty<Output = TreeDiff> + 'repo>,
property: BoxedTemplateProperty<'repo, TreeDiff>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::TreeDiff(property)
}
pub fn wrap_tree_diff_entry(
property: Box<dyn TemplateProperty<Output = TreeDiffEntry> + 'repo>,
property: BoxedTemplateProperty<'repo, TreeDiffEntry>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::TreeDiffEntry(property)
}
pub fn wrap_tree_diff_entry_list(
property: Box<dyn TemplateProperty<Output = Vec<TreeDiffEntry>> + 'repo>,
property: BoxedTemplateProperty<'repo, Vec<TreeDiffEntry>>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::TreeDiffEntryList(property)
}
pub fn wrap_tree_entry(
property: Box<dyn TemplateProperty<Output = TreeEntry> + 'repo>,
property: BoxedTemplateProperty<'repo, TreeEntry>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::TreeEntry(property)
}
pub fn wrap_diff_stats(
property: Box<dyn TemplateProperty<Output = DiffStatsFormatted<'repo>> + 'repo>,
property: BoxedTemplateProperty<'repo, DiffStatsFormatted<'repo>>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::DiffStats(property)
}
fn wrap_cryptographic_signature_opt(
property: Box<dyn TemplateProperty<Output = Option<CryptographicSignature>> + 'repo>,
property: BoxedTemplateProperty<'repo, Option<CryptographicSignature>>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::CryptographicSignatureOpt(property)
}
pub fn wrap_annotation_line(
property: Box<dyn TemplateProperty<Output = AnnotationLine> + 'repo>,
property: BoxedTemplateProperty<'repo, AnnotationLine>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::AnnotationLine(property)
}
pub fn wrap_trailer(
property: Box<dyn TemplateProperty<Output = Trailer> + 'repo>,
property: BoxedTemplateProperty<'repo, Trailer>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::Trailer(property)
}
pub fn wrap_trailer_list(
property: Box<dyn TemplateProperty<Output = Vec<Trailer>> + 'repo>,
property: BoxedTemplateProperty<'repo, Vec<Trailer>>,
) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::TrailerList(property)
}
@ -477,27 +477,25 @@ impl<'repo> CommitTemplateLanguage<'repo> {
pub enum CommitTemplatePropertyKind<'repo> {
Core(CoreTemplatePropertyKind<'repo>),
Commit(Box<dyn TemplateProperty<Output = Commit> + 'repo>),
CommitOpt(Box<dyn TemplateProperty<Output = Option<Commit>> + 'repo>),
CommitList(Box<dyn TemplateProperty<Output = Vec<Commit>> + 'repo>),
CommitRef(Box<dyn TemplateProperty<Output = Rc<CommitRef>> + 'repo>),
CommitRefOpt(Box<dyn TemplateProperty<Output = Option<Rc<CommitRef>>> + 'repo>),
CommitRefList(Box<dyn TemplateProperty<Output = Vec<Rc<CommitRef>>> + 'repo>),
RepoPath(Box<dyn TemplateProperty<Output = RepoPathBuf> + 'repo>),
RepoPathOpt(Box<dyn TemplateProperty<Output = Option<RepoPathBuf>> + 'repo>),
CommitOrChangeId(Box<dyn TemplateProperty<Output = CommitOrChangeId> + 'repo>),
ShortestIdPrefix(Box<dyn TemplateProperty<Output = ShortestIdPrefix> + 'repo>),
TreeDiff(Box<dyn TemplateProperty<Output = TreeDiff> + 'repo>),
TreeDiffEntry(Box<dyn TemplateProperty<Output = TreeDiffEntry> + 'repo>),
TreeDiffEntryList(Box<dyn TemplateProperty<Output = Vec<TreeDiffEntry>> + 'repo>),
TreeEntry(Box<dyn TemplateProperty<Output = TreeEntry> + 'repo>),
DiffStats(Box<dyn TemplateProperty<Output = DiffStatsFormatted<'repo>> + 'repo>),
CryptographicSignatureOpt(
Box<dyn TemplateProperty<Output = Option<CryptographicSignature>> + 'repo>,
),
AnnotationLine(Box<dyn TemplateProperty<Output = AnnotationLine> + 'repo>),
Trailer(Box<dyn TemplateProperty<Output = Trailer> + 'repo>),
TrailerList(Box<dyn TemplateProperty<Output = Vec<Trailer>> + 'repo>),
Commit(BoxedTemplateProperty<'repo, Commit>),
CommitOpt(BoxedTemplateProperty<'repo, Option<Commit>>),
CommitList(BoxedTemplateProperty<'repo, Vec<Commit>>),
CommitRef(BoxedTemplateProperty<'repo, Rc<CommitRef>>),
CommitRefOpt(BoxedTemplateProperty<'repo, Option<Rc<CommitRef>>>),
CommitRefList(BoxedTemplateProperty<'repo, Vec<Rc<CommitRef>>>),
RepoPath(BoxedTemplateProperty<'repo, RepoPathBuf>),
RepoPathOpt(BoxedTemplateProperty<'repo, Option<RepoPathBuf>>),
CommitOrChangeId(BoxedTemplateProperty<'repo, CommitOrChangeId>),
ShortestIdPrefix(BoxedTemplateProperty<'repo, ShortestIdPrefix>),
TreeDiff(BoxedTemplateProperty<'repo, TreeDiff>),
TreeDiffEntry(BoxedTemplateProperty<'repo, TreeDiffEntry>),
TreeDiffEntryList(BoxedTemplateProperty<'repo, Vec<TreeDiffEntry>>),
TreeEntry(BoxedTemplateProperty<'repo, TreeEntry>),
DiffStats(BoxedTemplateProperty<'repo, DiffStatsFormatted<'repo>>),
CryptographicSignatureOpt(BoxedTemplateProperty<'repo, Option<CryptographicSignature>>),
AnnotationLine(BoxedTemplateProperty<'repo, AnnotationLine>),
Trailer(BoxedTemplateProperty<'repo, Trailer>),
TrailerList(BoxedTemplateProperty<'repo, Vec<Trailer>>),
}
impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> {
@ -528,7 +526,7 @@ impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> {
}
}
fn try_into_boolean(self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'repo>> {
fn try_into_boolean(self) -> Option<BoxedTemplateProperty<'repo, bool>> {
match self {
CommitTemplatePropertyKind::Core(property) => property.try_into_boolean(),
CommitTemplatePropertyKind::Commit(_) => None,
@ -571,14 +569,14 @@ impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> {
}
}
fn try_into_integer(self) -> Option<Box<dyn TemplateProperty<Output = i64> + 'repo>> {
fn try_into_integer(self) -> Option<BoxedTemplateProperty<'repo, i64>> {
match self {
CommitTemplatePropertyKind::Core(property) => property.try_into_integer(),
_ => None,
}
}
fn try_into_plain_text(self) -> Option<Box<dyn TemplateProperty<Output = String> + 'repo>> {
fn try_into_plain_text(self) -> Option<BoxedTemplateProperty<'repo, String>> {
match self {
CommitTemplatePropertyKind::Core(property) => property.try_into_plain_text(),
_ => {
@ -617,7 +615,7 @@ impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> {
}
}
fn try_into_eq(self, other: Self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'repo>> {
fn try_into_eq(self, other: Self) -> Option<BoxedTemplateProperty<'repo, bool>> {
match (self, other) {
(CommitTemplatePropertyKind::Core(lhs), CommitTemplatePropertyKind::Core(rhs)) => {
lhs.try_into_eq(rhs)
@ -645,10 +643,7 @@ impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> {
}
}
fn try_into_cmp(
self,
other: Self,
) -> Option<Box<dyn TemplateProperty<Output = Ordering> + 'repo>> {
fn try_into_cmp(self, other: Self) -> Option<BoxedTemplateProperty<'repo, Ordering>> {
match (self, other) {
(CommitTemplatePropertyKind::Core(lhs), CommitTemplatePropertyKind::Core(rhs)) => {
lhs.try_into_cmp(rhs)

View File

@ -27,8 +27,8 @@ use crate::template_parser;
use crate::template_parser::FunctionCallNode;
use crate::template_parser::TemplateDiagnostics;
use crate::template_parser::TemplateParseResult;
use crate::templater::BoxedTemplateProperty;
use crate::templater::Template;
use crate::templater::TemplateProperty;
/// General-purpose template language for basic value types.
///
@ -79,7 +79,7 @@ impl<'a, C> GenericTemplateLanguage<'a, C> {
pub fn add_keyword<F>(&mut self, name: &'static str, build: F)
where
F: Fn(
Box<dyn TemplateProperty<Output = C> + 'a>,
BoxedTemplateProperty<'a, C>,
) -> TemplateParseResult<GenericTemplatePropertyKind<'a, C>>
+ 'a,
{
@ -131,16 +131,14 @@ impl<'a, C> TemplateLanguage<'a> for GenericTemplateLanguage<'a, C> {
}
impl<'a, C> GenericTemplateLanguage<'a, C> {
pub fn wrap_self(
property: Box<dyn TemplateProperty<Output = C> + 'a>,
) -> GenericTemplatePropertyKind<'a, C> {
pub fn wrap_self(property: BoxedTemplateProperty<'a, C>) -> GenericTemplatePropertyKind<'a, C> {
GenericTemplatePropertyKind::Self_(property)
}
}
pub enum GenericTemplatePropertyKind<'a, C> {
Core(CoreTemplatePropertyKind<'a>),
Self_(Box<dyn TemplateProperty<Output = C> + 'a>),
Self_(BoxedTemplateProperty<'a, C>),
}
impl<'a, C> IntoTemplateProperty<'a> for GenericTemplatePropertyKind<'a, C> {
@ -151,21 +149,21 @@ impl<'a, C> IntoTemplateProperty<'a> for GenericTemplatePropertyKind<'a, C> {
}
}
fn try_into_boolean(self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'a>> {
fn try_into_boolean(self) -> Option<BoxedTemplateProperty<'a, bool>> {
match self {
GenericTemplatePropertyKind::Core(property) => property.try_into_boolean(),
GenericTemplatePropertyKind::Self_(_) => None,
}
}
fn try_into_integer(self) -> Option<Box<dyn TemplateProperty<Output = i64> + 'a>> {
fn try_into_integer(self) -> Option<BoxedTemplateProperty<'a, i64>> {
match self {
GenericTemplatePropertyKind::Core(property) => property.try_into_integer(),
GenericTemplatePropertyKind::Self_(_) => None,
}
}
fn try_into_plain_text(self) -> Option<Box<dyn TemplateProperty<Output = String> + 'a>> {
fn try_into_plain_text(self) -> Option<BoxedTemplateProperty<'a, String>> {
match self {
GenericTemplatePropertyKind::Core(property) => property.try_into_plain_text(),
GenericTemplatePropertyKind::Self_(_) => None,
@ -179,7 +177,7 @@ impl<'a, C> IntoTemplateProperty<'a> for GenericTemplatePropertyKind<'a, C> {
}
}
fn try_into_eq(self, other: Self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'a>> {
fn try_into_eq(self, other: Self) -> Option<BoxedTemplateProperty<'a, bool>> {
match (self, other) {
(GenericTemplatePropertyKind::Core(lhs), GenericTemplatePropertyKind::Core(rhs)) => {
lhs.try_into_eq(rhs)
@ -189,10 +187,7 @@ impl<'a, C> IntoTemplateProperty<'a> for GenericTemplatePropertyKind<'a, C> {
}
}
fn try_into_cmp(
self,
other: Self,
) -> Option<Box<dyn TemplateProperty<Output = Ordering> + 'a>> {
fn try_into_cmp(self, other: Self) -> Option<BoxedTemplateProperty<'a, Ordering>> {
match (self, other) {
(GenericTemplatePropertyKind::Core(lhs), GenericTemplatePropertyKind::Core(rhs)) => {
lhs.try_into_cmp(rhs)
@ -209,9 +204,7 @@ impl<'a, C> IntoTemplateProperty<'a> for GenericTemplatePropertyKind<'a, C> {
/// Because the `GenericTemplateLanguage` doesn't provide a way to pass around
/// global resources, the keyword function is allowed to capture resources.
pub type GenericTemplateBuildKeywordFn<'a, C> = Box<
dyn Fn(
Box<dyn TemplateProperty<Output = C> + 'a>,
) -> TemplateParseResult<GenericTemplatePropertyKind<'a, C>>
dyn Fn(BoxedTemplateProperty<'a, C>) -> TemplateParseResult<GenericTemplatePropertyKind<'a, C>>
+ 'a,
>;

View File

@ -37,10 +37,10 @@ use crate::template_parser;
use crate::template_parser::FunctionCallNode;
use crate::template_parser::TemplateDiagnostics;
use crate::template_parser::TemplateParseResult;
use crate::templater::BoxedTemplateProperty;
use crate::templater::PlainTextFormattedProperty;
use crate::templater::Template;
use crate::templater::TemplateFormatter;
use crate::templater::TemplateProperty;
use crate::templater::TemplatePropertyExt as _;
use crate::templater::TimestampRange;
@ -137,13 +137,13 @@ impl OperationTemplateLanguage {
}
pub fn wrap_operation(
property: Box<dyn TemplateProperty<Output = Operation> + 'static>,
property: BoxedTemplateProperty<'static, Operation>,
) -> OperationTemplatePropertyKind {
OperationTemplatePropertyKind::Operation(property)
}
pub fn wrap_operation_id(
property: Box<dyn TemplateProperty<Output = OperationId> + 'static>,
property: BoxedTemplateProperty<'static, OperationId>,
) -> OperationTemplatePropertyKind {
OperationTemplatePropertyKind::OperationId(property)
}
@ -151,8 +151,8 @@ impl OperationTemplateLanguage {
pub enum OperationTemplatePropertyKind {
Core(CoreTemplatePropertyKind<'static>),
Operation(Box<dyn TemplateProperty<Output = Operation>>),
OperationId(Box<dyn TemplateProperty<Output = OperationId>>),
Operation(BoxedTemplateProperty<'static, Operation>),
OperationId(BoxedTemplateProperty<'static, OperationId>),
}
impl IntoTemplateProperty<'static> for OperationTemplatePropertyKind {
@ -164,7 +164,7 @@ impl IntoTemplateProperty<'static> for OperationTemplatePropertyKind {
}
}
fn try_into_boolean(self) -> Option<Box<dyn TemplateProperty<Output = bool>>> {
fn try_into_boolean(self) -> Option<BoxedTemplateProperty<'static, bool>> {
match self {
OperationTemplatePropertyKind::Core(property) => property.try_into_boolean(),
OperationTemplatePropertyKind::Operation(_) => None,
@ -172,14 +172,14 @@ impl IntoTemplateProperty<'static> for OperationTemplatePropertyKind {
}
}
fn try_into_integer(self) -> Option<Box<dyn TemplateProperty<Output = i64>>> {
fn try_into_integer(self) -> Option<BoxedTemplateProperty<'static, i64>> {
match self {
OperationTemplatePropertyKind::Core(property) => property.try_into_integer(),
_ => None,
}
}
fn try_into_plain_text(self) -> Option<Box<dyn TemplateProperty<Output = String>>> {
fn try_into_plain_text(self) -> Option<BoxedTemplateProperty<'static, String>> {
match self {
OperationTemplatePropertyKind::Core(property) => property.try_into_plain_text(),
_ => {
@ -197,7 +197,7 @@ impl IntoTemplateProperty<'static> for OperationTemplatePropertyKind {
}
}
fn try_into_eq(self, other: Self) -> Option<Box<dyn TemplateProperty<Output = bool>>> {
fn try_into_eq(self, other: Self) -> Option<BoxedTemplateProperty<'static, bool>> {
match (self, other) {
(
OperationTemplatePropertyKind::Core(lhs),
@ -209,7 +209,7 @@ impl IntoTemplateProperty<'static> for OperationTemplatePropertyKind {
}
}
fn try_into_cmp(self, other: Self) -> Option<Box<dyn TemplateProperty<Output = Ordering>>> {
fn try_into_cmp(self, other: Self) -> Option<BoxedTemplateProperty<'static, Ordering>> {
match (self, other) {
(
OperationTemplatePropertyKind::Core(lhs),

View File

@ -42,6 +42,7 @@ use crate::template_parser::TemplateParseError;
use crate::template_parser::TemplateParseErrorKind;
use crate::template_parser::TemplateParseResult;
use crate::template_parser::UnaryOp;
use crate::templater::BoxedTemplateProperty;
use crate::templater::CoalesceTemplate;
use crate::templater::ConcatTemplate;
use crate::templater::ConditionalTemplate;
@ -69,31 +70,17 @@ use crate::time_util;
pub trait TemplateLanguage<'a> {
type Property: IntoTemplateProperty<'a>;
fn wrap_string(property: Box<dyn TemplateProperty<Output = String> + 'a>) -> Self::Property;
fn wrap_string_list(
property: Box<dyn TemplateProperty<Output = Vec<String>> + 'a>,
) -> Self::Property;
fn wrap_boolean(property: Box<dyn TemplateProperty<Output = bool> + 'a>) -> Self::Property;
fn wrap_integer(property: Box<dyn TemplateProperty<Output = i64> + 'a>) -> Self::Property;
fn wrap_integer_opt(
property: Box<dyn TemplateProperty<Output = Option<i64>> + 'a>,
) -> Self::Property;
fn wrap_config_value(
property: Box<dyn TemplateProperty<Output = ConfigValue> + 'a>,
) -> Self::Property;
fn wrap_signature(
property: Box<dyn TemplateProperty<Output = Signature> + 'a>,
) -> Self::Property;
fn wrap_email(property: Box<dyn TemplateProperty<Output = Email> + 'a>) -> Self::Property;
fn wrap_size_hint(
property: Box<dyn TemplateProperty<Output = SizeHint> + 'a>,
) -> Self::Property;
fn wrap_timestamp(
property: Box<dyn TemplateProperty<Output = Timestamp> + 'a>,
) -> Self::Property;
fn wrap_timestamp_range(
property: Box<dyn TemplateProperty<Output = TimestampRange> + 'a>,
) -> Self::Property;
fn wrap_string(property: BoxedTemplateProperty<'a, String>) -> Self::Property;
fn wrap_string_list(property: BoxedTemplateProperty<'a, Vec<String>>) -> Self::Property;
fn wrap_boolean(property: BoxedTemplateProperty<'a, bool>) -> Self::Property;
fn wrap_integer(property: BoxedTemplateProperty<'a, i64>) -> Self::Property;
fn wrap_integer_opt(property: BoxedTemplateProperty<'a, Option<i64>>) -> Self::Property;
fn wrap_config_value(property: BoxedTemplateProperty<'a, ConfigValue>) -> Self::Property;
fn wrap_signature(property: BoxedTemplateProperty<'a, Signature>) -> Self::Property;
fn wrap_email(property: BoxedTemplateProperty<'a, Email>) -> Self::Property;
fn wrap_size_hint(property: BoxedTemplateProperty<'a, SizeHint>) -> Self::Property;
fn wrap_timestamp(property: BoxedTemplateProperty<'a, Timestamp>) -> Self::Property;
fn wrap_timestamp_range(property: BoxedTemplateProperty<'a, TimestampRange>) -> Self::Property;
fn wrap_template(template: Box<dyn Template + 'a>) -> Self::Property;
fn wrap_list_template(template: Box<dyn ListTemplate + 'a>) -> Self::Property;
@ -163,7 +150,7 @@ macro_rules! impl_wrap_property_fns {
($a:lifetime, $kind:path, $outer:path, { $( $func:ident($ty:ty) => $var:ident, )+ }) => {
$(
fn $func(
property: Box<dyn $crate::templater::TemplateProperty<Output = $ty> + $a>,
property: $crate::templater::BoxedTemplateProperty<$a, $ty>,
) -> Self::Property {
use $kind as Kind; // https://github.com/rust-lang/rust/issues/48067
$outer(Kind::$var(property))
@ -180,32 +167,31 @@ pub trait IntoTemplateProperty<'a> {
/// Type name of the property output.
fn type_name(&self) -> &'static str;
fn try_into_boolean(self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'a>>;
fn try_into_integer(self) -> Option<Box<dyn TemplateProperty<Output = i64> + 'a>>;
fn try_into_boolean(self) -> Option<BoxedTemplateProperty<'a, bool>>;
fn try_into_integer(self) -> Option<BoxedTemplateProperty<'a, i64>>;
fn try_into_plain_text(self) -> Option<Box<dyn TemplateProperty<Output = String> + 'a>>;
fn try_into_plain_text(self) -> Option<BoxedTemplateProperty<'a, String>>;
fn try_into_template(self) -> Option<Box<dyn Template + 'a>>;
/// Transforms into a property that will evaluate to `self == other`.
fn try_into_eq(self, other: Self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'a>>;
fn try_into_eq(self, other: Self) -> Option<BoxedTemplateProperty<'a, bool>>;
/// Transforms into a property that will evaluate to an [`Ordering`].
fn try_into_cmp(self, other: Self)
-> Option<Box<dyn TemplateProperty<Output = Ordering> + 'a>>;
fn try_into_cmp(self, other: Self) -> Option<BoxedTemplateProperty<'a, Ordering>>;
}
pub enum CoreTemplatePropertyKind<'a> {
String(Box<dyn TemplateProperty<Output = String> + 'a>),
StringList(Box<dyn TemplateProperty<Output = Vec<String>> + 'a>),
Boolean(Box<dyn TemplateProperty<Output = bool> + 'a>),
Integer(Box<dyn TemplateProperty<Output = i64> + 'a>),
IntegerOpt(Box<dyn TemplateProperty<Output = Option<i64>> + 'a>),
ConfigValue(Box<dyn TemplateProperty<Output = ConfigValue> + 'a>),
Signature(Box<dyn TemplateProperty<Output = Signature> + 'a>),
Email(Box<dyn TemplateProperty<Output = Email> + 'a>),
SizeHint(Box<dyn TemplateProperty<Output = SizeHint> + 'a>),
Timestamp(Box<dyn TemplateProperty<Output = Timestamp> + 'a>),
TimestampRange(Box<dyn TemplateProperty<Output = TimestampRange> + 'a>),
String(BoxedTemplateProperty<'a, String>),
StringList(BoxedTemplateProperty<'a, Vec<String>>),
Boolean(BoxedTemplateProperty<'a, bool>),
Integer(BoxedTemplateProperty<'a, i64>),
IntegerOpt(BoxedTemplateProperty<'a, Option<i64>>),
ConfigValue(BoxedTemplateProperty<'a, ConfigValue>),
Signature(BoxedTemplateProperty<'a, Signature>),
Email(BoxedTemplateProperty<'a, Email>),
SizeHint(BoxedTemplateProperty<'a, SizeHint>),
Timestamp(BoxedTemplateProperty<'a, Timestamp>),
TimestampRange(BoxedTemplateProperty<'a, TimestampRange>),
// Both TemplateProperty and Template can represent a value to be evaluated
// dynamically, which suggests that `Box<dyn Template + 'a>` could be
@ -240,7 +226,7 @@ impl<'a> IntoTemplateProperty<'a> for CoreTemplatePropertyKind<'a> {
}
}
fn try_into_boolean(self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'a>> {
fn try_into_boolean(self) -> Option<BoxedTemplateProperty<'a, bool>> {
match self {
CoreTemplatePropertyKind::String(property) => {
Some(property.map(|s| !s.is_empty()).into_dyn())
@ -269,7 +255,7 @@ impl<'a> IntoTemplateProperty<'a> for CoreTemplatePropertyKind<'a> {
}
}
fn try_into_integer(self) -> Option<Box<dyn TemplateProperty<Output = i64> + 'a>> {
fn try_into_integer(self) -> Option<BoxedTemplateProperty<'a, i64>> {
match self {
CoreTemplatePropertyKind::Integer(property) => Some(property),
CoreTemplatePropertyKind::IntegerOpt(property) => {
@ -279,7 +265,7 @@ impl<'a> IntoTemplateProperty<'a> for CoreTemplatePropertyKind<'a> {
}
}
fn try_into_plain_text(self) -> Option<Box<dyn TemplateProperty<Output = String> + 'a>> {
fn try_into_plain_text(self) -> Option<BoxedTemplateProperty<'a, String>> {
match self {
CoreTemplatePropertyKind::String(property) => Some(property),
_ => {
@ -307,7 +293,7 @@ impl<'a> IntoTemplateProperty<'a> for CoreTemplatePropertyKind<'a> {
}
}
fn try_into_eq(self, other: Self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'a>> {
fn try_into_eq(self, other: Self) -> Option<BoxedTemplateProperty<'a, bool>> {
match (self, other) {
(CoreTemplatePropertyKind::String(lhs), CoreTemplatePropertyKind::String(rhs)) => {
Some((lhs, rhs).map(|(l, r)| l == r).into_dyn())
@ -343,10 +329,7 @@ impl<'a> IntoTemplateProperty<'a> for CoreTemplatePropertyKind<'a> {
}
}
fn try_into_cmp(
self,
other: Self,
) -> Option<Box<dyn TemplateProperty<Output = Ordering> + 'a>> {
fn try_into_cmp(self, other: Self) -> Option<BoxedTemplateProperty<'a, Ordering>> {
match (self, other) {
(CoreTemplatePropertyKind::Integer(lhs), CoreTemplatePropertyKind::Integer(rhs)) => {
Some((lhs, rhs).map(|(l, r)| l.cmp(&r)).into_dyn())
@ -388,7 +371,7 @@ pub type TemplateBuildMethodFn<'a, L, T> =
&L,
&mut TemplateDiagnostics,
&BuildContext<<L as TemplateLanguage<'a>>::Property>,
Box<dyn TemplateProperty<Output = T> + 'a>,
BoxedTemplateProperty<'a, T>,
&FunctionCallNode,
) -> TemplateParseResult<<L as TemplateLanguage<'a>>::Property>;
@ -603,15 +586,15 @@ impl<'a, P: IntoTemplateProperty<'a>> Expression<P> {
self.property.type_name()
}
pub fn try_into_boolean(self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'a>> {
pub fn try_into_boolean(self) -> Option<BoxedTemplateProperty<'a, bool>> {
self.property.try_into_boolean()
}
pub fn try_into_integer(self) -> Option<Box<dyn TemplateProperty<Output = i64> + 'a>> {
pub fn try_into_integer(self) -> Option<BoxedTemplateProperty<'a, i64>> {
self.property.try_into_integer()
}
pub fn try_into_plain_text(self) -> Option<Box<dyn TemplateProperty<Output = String> + 'a>> {
pub fn try_into_plain_text(self) -> Option<BoxedTemplateProperty<'a, String>> {
self.property.try_into_plain_text()
}
@ -624,14 +607,11 @@ impl<'a, P: IntoTemplateProperty<'a>> Expression<P> {
}
}
pub fn try_into_eq(self, other: Self) -> Option<Box<dyn TemplateProperty<Output = bool> + 'a>> {
pub fn try_into_eq(self, other: Self) -> Option<BoxedTemplateProperty<'a, bool>> {
self.property.try_into_eq(other.property)
}
pub fn try_into_cmp(
self,
other: Self,
) -> Option<Box<dyn TemplateProperty<Output = Ordering> + 'a>> {
pub fn try_into_cmp(self, other: Self) -> Option<BoxedTemplateProperty<'a, Ordering>> {
self.property.try_into_cmp(other.property)
}
}
@ -1267,8 +1247,8 @@ pub fn build_formattable_list_method<'a, L, O>(
function: &FunctionCallNode,
// TODO: Generic L: WrapProperty<O> trait might be needed to support more
// list operations such as first()/slice().
wrap_item: impl Fn(Box<dyn TemplateProperty<Output = O> + 'a>) -> L::Property,
wrap_list: impl Fn(Box<dyn TemplateProperty<Output = Vec<O>> + 'a>) -> L::Property,
wrap_item: impl Fn(BoxedTemplateProperty<'a, O>) -> L::Property,
wrap_list: impl Fn(BoxedTemplateProperty<'a, Vec<O>>) -> L::Property,
) -> TemplateParseResult<L::Property>
where
L: TemplateLanguage<'a> + ?Sized,
@ -1318,8 +1298,8 @@ pub fn build_unformattable_list_method<'a, L, O>(
build_ctx: &BuildContext<L::Property>,
self_property: impl TemplateProperty<Output = Vec<O>> + 'a,
function: &FunctionCallNode,
wrap_item: impl Fn(Box<dyn TemplateProperty<Output = O> + 'a>) -> L::Property,
wrap_list: impl Fn(Box<dyn TemplateProperty<Output = Vec<O>> + 'a>) -> L::Property,
wrap_item: impl Fn(BoxedTemplateProperty<'a, O>) -> L::Property,
wrap_list: impl Fn(BoxedTemplateProperty<'a, Vec<O>>) -> L::Property,
) -> TemplateParseResult<L::Property>
where
L: TemplateLanguage<'a> + ?Sized,
@ -1364,8 +1344,8 @@ fn build_filter_operation<'a, L, O, P, B>(
build_ctx: &BuildContext<L::Property>,
self_property: P,
function: &FunctionCallNode,
wrap_item: impl Fn(Box<dyn TemplateProperty<Output = O> + 'a>) -> L::Property,
wrap_list: impl Fn(Box<dyn TemplateProperty<Output = B> + 'a>) -> L::Property,
wrap_item: impl Fn(BoxedTemplateProperty<'a, O>) -> L::Property,
wrap_list: impl Fn(BoxedTemplateProperty<'a, B>) -> L::Property,
) -> TemplateParseResult<L::Property>
where
L: TemplateLanguage<'a> + ?Sized,
@ -1409,7 +1389,7 @@ fn build_map_operation<'a, L, O, P>(
build_ctx: &BuildContext<L::Property>,
self_property: P,
function: &FunctionCallNode,
wrap_item: impl Fn(Box<dyn TemplateProperty<Output = O> + 'a>) -> L::Property,
wrap_item: impl Fn(BoxedTemplateProperty<'a, O>) -> L::Property,
) -> TemplateParseResult<L::Property>
where
L: TemplateLanguage<'a> + ?Sized,
@ -1666,7 +1646,7 @@ fn builtin_functions<'a, L: TemplateLanguage<'a> + ?Sized>() -> TemplateBuildFun
fn new_pad_template<'a, W>(
content: Box<dyn Template + 'a>,
fill_char: Option<Box<dyn Template + 'a>>,
width: Box<dyn TemplateProperty<Output = usize> + 'a>,
width: BoxedTemplateProperty<'a, usize>,
write_padded: W,
) -> Box<dyn Template + 'a>
where
@ -1695,7 +1675,7 @@ where
fn new_truncate_template<'a, W>(
content: Box<dyn Template + 'a>,
ellipsis: Option<Box<dyn Template + 'a>>,
width: Box<dyn TemplateProperty<Output = usize> + 'a>,
width: BoxedTemplateProperty<'a, usize>,
write_truncated: W,
) -> Box<dyn Template + 'a>
where
@ -1827,7 +1807,7 @@ pub fn build<'a, C: Clone + 'a, L: TemplateLanguage<'a> + ?Sized>(
node: &ExpressionNode,
// TODO: Generic L: WrapProperty<C> trait might be better. See the
// comment in build_formattable_list_method().
wrap_self: impl Fn(Box<dyn TemplateProperty<Output = C> + 'a>) -> L::Property,
wrap_self: impl Fn(BoxedTemplateProperty<'a, C>) -> L::Property,
) -> TemplateParseResult<TemplateRenderer<'a, C>> {
let self_placeholder = PropertyPlaceholder::new();
let build_ctx = BuildContext {
@ -1844,7 +1824,7 @@ pub fn parse<'a, C: Clone + 'a, L: TemplateLanguage<'a> + ?Sized>(
diagnostics: &mut TemplateDiagnostics,
template_text: &str,
aliases_map: &TemplateAliasesMap,
wrap_self: impl Fn(Box<dyn TemplateProperty<Output = C> + 'a>) -> L::Property,
wrap_self: impl Fn(BoxedTemplateProperty<'a, C>) -> L::Property,
) -> TemplateParseResult<TemplateRenderer<'a, C>> {
let node = template_parser::parse(template_text, aliases_map)?;
build(language, diagnostics, &node, wrap_self)
@ -1856,7 +1836,7 @@ pub fn expect_boolean_expression<'a, L: TemplateLanguage<'a> + ?Sized>(
diagnostics: &mut TemplateDiagnostics,
build_ctx: &BuildContext<L::Property>,
node: &ExpressionNode,
) -> TemplateParseResult<Box<dyn TemplateProperty<Output = bool> + 'a>> {
) -> TemplateParseResult<BoxedTemplateProperty<'a, bool>> {
expect_expression_of_type(
language,
diagnostics,
@ -1872,7 +1852,7 @@ pub fn expect_integer_expression<'a, L: TemplateLanguage<'a> + ?Sized>(
diagnostics: &mut TemplateDiagnostics,
build_ctx: &BuildContext<L::Property>,
node: &ExpressionNode,
) -> TemplateParseResult<Box<dyn TemplateProperty<Output = i64> + 'a>> {
) -> TemplateParseResult<BoxedTemplateProperty<'a, i64>> {
expect_expression_of_type(
language,
diagnostics,
@ -1889,7 +1869,7 @@ pub fn expect_isize_expression<'a, L: TemplateLanguage<'a> + ?Sized>(
diagnostics: &mut TemplateDiagnostics,
build_ctx: &BuildContext<L::Property>,
node: &ExpressionNode,
) -> TemplateParseResult<Box<dyn TemplateProperty<Output = isize> + 'a>> {
) -> TemplateParseResult<BoxedTemplateProperty<'a, isize>> {
let i64_property = expect_integer_expression(language, diagnostics, build_ctx, node)?;
let isize_property = i64_property.and_then(|v| Ok(isize::try_from(v)?));
Ok(isize_property.into_dyn())
@ -1901,7 +1881,7 @@ pub fn expect_usize_expression<'a, L: TemplateLanguage<'a> + ?Sized>(
diagnostics: &mut TemplateDiagnostics,
build_ctx: &BuildContext<L::Property>,
node: &ExpressionNode,
) -> TemplateParseResult<Box<dyn TemplateProperty<Output = usize> + 'a>> {
) -> TemplateParseResult<BoxedTemplateProperty<'a, usize>> {
let i64_property = expect_integer_expression(language, diagnostics, build_ctx, node)?;
let usize_property = i64_property.and_then(|v| Ok(usize::try_from(v)?));
Ok(usize_property.into_dyn())
@ -1912,7 +1892,7 @@ pub fn expect_plain_text_expression<'a, L: TemplateLanguage<'a> + ?Sized>(
diagnostics: &mut TemplateDiagnostics,
build_ctx: &BuildContext<L::Property>,
node: &ExpressionNode,
) -> TemplateParseResult<Box<dyn TemplateProperty<Output = String> + 'a>> {
) -> TemplateParseResult<BoxedTemplateProperty<'a, String>> {
// Since any formattable type can be converted to a string property,
// the expected type is not a String, but a Template.
expect_expression_of_type(
@ -2056,11 +2036,11 @@ mod tests {
}
}
fn literal<'a, O: Clone + 'a>(value: O) -> Box<dyn TemplateProperty<Output = O> + 'a> {
fn literal<'a, O: Clone + 'a>(value: O) -> BoxedTemplateProperty<'a, O> {
Literal(value).into_dyn()
}
fn new_error_property<O>(message: &str) -> Box<dyn TemplateProperty<Output = O> + '_> {
fn new_error_property<O>(message: &str) -> BoxedTemplateProperty<'_, O> {
Literal(())
.and_then(|()| Err(TemplatePropertyError(message.into())))
.into_dyn()

View File

@ -394,6 +394,8 @@ tuple_impls! {
(0 T0, 1 T1, 2 T2, 3 T3)
}
pub type BoxedTemplateProperty<'a, O> = Box<dyn TemplateProperty<Output = O> + 'a>;
/// `TemplateProperty` adapters that are useful when implementing methods.
pub trait TemplatePropertyExt: TemplateProperty {
/// Translates to a property that will apply fallible `function` to an
@ -437,7 +439,7 @@ pub trait TemplatePropertyExt: TemplateProperty {
}
/// Converts this property into boxed trait object.
fn into_dyn<'a>(self) -> Box<dyn TemplateProperty<Output = Self::Output> + 'a>
fn into_dyn<'a>(self) -> BoxedTemplateProperty<'a, Self::Output>
where
Self: Sized + 'a,
{