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

View File

@ -89,11 +89,11 @@ use crate::template_parser::TemplateDiagnostics;
use crate::template_parser::TemplateParseError; use crate::template_parser::TemplateParseError;
use crate::template_parser::TemplateParseResult; use crate::template_parser::TemplateParseResult;
use crate::templater; use crate::templater;
use crate::templater::BoxedTemplateProperty;
use crate::templater::PlainTextFormattedProperty; use crate::templater::PlainTextFormattedProperty;
use crate::templater::SizeHint; use crate::templater::SizeHint;
use crate::templater::Template; use crate::templater::Template;
use crate::templater::TemplateFormatter; use crate::templater::TemplateFormatter;
use crate::templater::TemplateProperty;
use crate::templater::TemplatePropertyError; use crate::templater::TemplatePropertyError;
use crate::templater::TemplatePropertyExt as _; use crate::templater::TemplatePropertyExt as _;
use crate::text_util; use crate::text_util;
@ -361,115 +361,115 @@ impl<'repo> CommitTemplateLanguage<'repo> {
} }
pub fn wrap_commit( pub fn wrap_commit(
property: Box<dyn TemplateProperty<Output = Commit> + 'repo>, property: BoxedTemplateProperty<'repo, Commit>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::Commit(property) CommitTemplatePropertyKind::Commit(property)
} }
pub fn wrap_commit_opt( pub fn wrap_commit_opt(
property: Box<dyn TemplateProperty<Output = Option<Commit>> + 'repo>, property: BoxedTemplateProperty<'repo, Option<Commit>>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::CommitOpt(property) CommitTemplatePropertyKind::CommitOpt(property)
} }
pub fn wrap_commit_list( pub fn wrap_commit_list(
property: Box<dyn TemplateProperty<Output = Vec<Commit>> + 'repo>, property: BoxedTemplateProperty<'repo, Vec<Commit>>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::CommitList(property) CommitTemplatePropertyKind::CommitList(property)
} }
pub fn wrap_commit_ref( pub fn wrap_commit_ref(
property: Box<dyn TemplateProperty<Output = Rc<CommitRef>> + 'repo>, property: BoxedTemplateProperty<'repo, Rc<CommitRef>>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::CommitRef(property) CommitTemplatePropertyKind::CommitRef(property)
} }
pub fn wrap_commit_ref_opt( pub fn wrap_commit_ref_opt(
property: Box<dyn TemplateProperty<Output = Option<Rc<CommitRef>>> + 'repo>, property: BoxedTemplateProperty<'repo, Option<Rc<CommitRef>>>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::CommitRefOpt(property) CommitTemplatePropertyKind::CommitRefOpt(property)
} }
pub fn wrap_commit_ref_list( pub fn wrap_commit_ref_list(
property: Box<dyn TemplateProperty<Output = Vec<Rc<CommitRef>>> + 'repo>, property: BoxedTemplateProperty<'repo, Vec<Rc<CommitRef>>>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::CommitRefList(property) CommitTemplatePropertyKind::CommitRefList(property)
} }
pub fn wrap_repo_path( pub fn wrap_repo_path(
property: Box<dyn TemplateProperty<Output = RepoPathBuf> + 'repo>, property: BoxedTemplateProperty<'repo, RepoPathBuf>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::RepoPath(property) CommitTemplatePropertyKind::RepoPath(property)
} }
pub fn wrap_repo_path_opt( pub fn wrap_repo_path_opt(
property: Box<dyn TemplateProperty<Output = Option<RepoPathBuf>> + 'repo>, property: BoxedTemplateProperty<'repo, Option<RepoPathBuf>>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::RepoPathOpt(property) CommitTemplatePropertyKind::RepoPathOpt(property)
} }
pub fn wrap_commit_or_change_id( pub fn wrap_commit_or_change_id(
property: Box<dyn TemplateProperty<Output = CommitOrChangeId> + 'repo>, property: BoxedTemplateProperty<'repo, CommitOrChangeId>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::CommitOrChangeId(property) CommitTemplatePropertyKind::CommitOrChangeId(property)
} }
pub fn wrap_shortest_id_prefix( pub fn wrap_shortest_id_prefix(
property: Box<dyn TemplateProperty<Output = ShortestIdPrefix> + 'repo>, property: BoxedTemplateProperty<'repo, ShortestIdPrefix>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::ShortestIdPrefix(property) CommitTemplatePropertyKind::ShortestIdPrefix(property)
} }
pub fn wrap_tree_diff( pub fn wrap_tree_diff(
property: Box<dyn TemplateProperty<Output = TreeDiff> + 'repo>, property: BoxedTemplateProperty<'repo, TreeDiff>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::TreeDiff(property) CommitTemplatePropertyKind::TreeDiff(property)
} }
pub fn wrap_tree_diff_entry( pub fn wrap_tree_diff_entry(
property: Box<dyn TemplateProperty<Output = TreeDiffEntry> + 'repo>, property: BoxedTemplateProperty<'repo, TreeDiffEntry>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::TreeDiffEntry(property) CommitTemplatePropertyKind::TreeDiffEntry(property)
} }
pub fn wrap_tree_diff_entry_list( pub fn wrap_tree_diff_entry_list(
property: Box<dyn TemplateProperty<Output = Vec<TreeDiffEntry>> + 'repo>, property: BoxedTemplateProperty<'repo, Vec<TreeDiffEntry>>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::TreeDiffEntryList(property) CommitTemplatePropertyKind::TreeDiffEntryList(property)
} }
pub fn wrap_tree_entry( pub fn wrap_tree_entry(
property: Box<dyn TemplateProperty<Output = TreeEntry> + 'repo>, property: BoxedTemplateProperty<'repo, TreeEntry>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::TreeEntry(property) CommitTemplatePropertyKind::TreeEntry(property)
} }
pub fn wrap_diff_stats( pub fn wrap_diff_stats(
property: Box<dyn TemplateProperty<Output = DiffStatsFormatted<'repo>> + 'repo>, property: BoxedTemplateProperty<'repo, DiffStatsFormatted<'repo>>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::DiffStats(property) CommitTemplatePropertyKind::DiffStats(property)
} }
fn wrap_cryptographic_signature_opt( fn wrap_cryptographic_signature_opt(
property: Box<dyn TemplateProperty<Output = Option<CryptographicSignature>> + 'repo>, property: BoxedTemplateProperty<'repo, Option<CryptographicSignature>>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::CryptographicSignatureOpt(property) CommitTemplatePropertyKind::CryptographicSignatureOpt(property)
} }
pub fn wrap_annotation_line( pub fn wrap_annotation_line(
property: Box<dyn TemplateProperty<Output = AnnotationLine> + 'repo>, property: BoxedTemplateProperty<'repo, AnnotationLine>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::AnnotationLine(property) CommitTemplatePropertyKind::AnnotationLine(property)
} }
pub fn wrap_trailer( pub fn wrap_trailer(
property: Box<dyn TemplateProperty<Output = Trailer> + 'repo>, property: BoxedTemplateProperty<'repo, Trailer>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::Trailer(property) CommitTemplatePropertyKind::Trailer(property)
} }
pub fn wrap_trailer_list( pub fn wrap_trailer_list(
property: Box<dyn TemplateProperty<Output = Vec<Trailer>> + 'repo>, property: BoxedTemplateProperty<'repo, Vec<Trailer>>,
) -> CommitTemplatePropertyKind<'repo> { ) -> CommitTemplatePropertyKind<'repo> {
CommitTemplatePropertyKind::TrailerList(property) CommitTemplatePropertyKind::TrailerList(property)
} }
@ -477,27 +477,25 @@ impl<'repo> CommitTemplateLanguage<'repo> {
pub enum CommitTemplatePropertyKind<'repo> { pub enum CommitTemplatePropertyKind<'repo> {
Core(CoreTemplatePropertyKind<'repo>), Core(CoreTemplatePropertyKind<'repo>),
Commit(Box<dyn TemplateProperty<Output = Commit> + 'repo>), Commit(BoxedTemplateProperty<'repo, Commit>),
CommitOpt(Box<dyn TemplateProperty<Output = Option<Commit>> + 'repo>), CommitOpt(BoxedTemplateProperty<'repo, Option<Commit>>),
CommitList(Box<dyn TemplateProperty<Output = Vec<Commit>> + 'repo>), CommitList(BoxedTemplateProperty<'repo, Vec<Commit>>),
CommitRef(Box<dyn TemplateProperty<Output = Rc<CommitRef>> + 'repo>), CommitRef(BoxedTemplateProperty<'repo, Rc<CommitRef>>),
CommitRefOpt(Box<dyn TemplateProperty<Output = Option<Rc<CommitRef>>> + 'repo>), CommitRefOpt(BoxedTemplateProperty<'repo, Option<Rc<CommitRef>>>),
CommitRefList(Box<dyn TemplateProperty<Output = Vec<Rc<CommitRef>>> + 'repo>), CommitRefList(BoxedTemplateProperty<'repo, Vec<Rc<CommitRef>>>),
RepoPath(Box<dyn TemplateProperty<Output = RepoPathBuf> + 'repo>), RepoPath(BoxedTemplateProperty<'repo, RepoPathBuf>),
RepoPathOpt(Box<dyn TemplateProperty<Output = Option<RepoPathBuf>> + 'repo>), RepoPathOpt(BoxedTemplateProperty<'repo, Option<RepoPathBuf>>),
CommitOrChangeId(Box<dyn TemplateProperty<Output = CommitOrChangeId> + 'repo>), CommitOrChangeId(BoxedTemplateProperty<'repo, CommitOrChangeId>),
ShortestIdPrefix(Box<dyn TemplateProperty<Output = ShortestIdPrefix> + 'repo>), ShortestIdPrefix(BoxedTemplateProperty<'repo, ShortestIdPrefix>),
TreeDiff(Box<dyn TemplateProperty<Output = TreeDiff> + 'repo>), TreeDiff(BoxedTemplateProperty<'repo, TreeDiff>),
TreeDiffEntry(Box<dyn TemplateProperty<Output = TreeDiffEntry> + 'repo>), TreeDiffEntry(BoxedTemplateProperty<'repo, TreeDiffEntry>),
TreeDiffEntryList(Box<dyn TemplateProperty<Output = Vec<TreeDiffEntry>> + 'repo>), TreeDiffEntryList(BoxedTemplateProperty<'repo, Vec<TreeDiffEntry>>),
TreeEntry(Box<dyn TemplateProperty<Output = TreeEntry> + 'repo>), TreeEntry(BoxedTemplateProperty<'repo, TreeEntry>),
DiffStats(Box<dyn TemplateProperty<Output = DiffStatsFormatted<'repo>> + 'repo>), DiffStats(BoxedTemplateProperty<'repo, DiffStatsFormatted<'repo>>),
CryptographicSignatureOpt( CryptographicSignatureOpt(BoxedTemplateProperty<'repo, Option<CryptographicSignature>>),
Box<dyn TemplateProperty<Output = Option<CryptographicSignature>> + 'repo>, AnnotationLine(BoxedTemplateProperty<'repo, AnnotationLine>),
), Trailer(BoxedTemplateProperty<'repo, Trailer>),
AnnotationLine(Box<dyn TemplateProperty<Output = AnnotationLine> + 'repo>), TrailerList(BoxedTemplateProperty<'repo, Vec<Trailer>>),
Trailer(Box<dyn TemplateProperty<Output = Trailer> + 'repo>),
TrailerList(Box<dyn TemplateProperty<Output = Vec<Trailer>> + 'repo>),
} }
impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> { 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 { match self {
CommitTemplatePropertyKind::Core(property) => property.try_into_boolean(), CommitTemplatePropertyKind::Core(property) => property.try_into_boolean(),
CommitTemplatePropertyKind::Commit(_) => None, 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 { match self {
CommitTemplatePropertyKind::Core(property) => property.try_into_integer(), CommitTemplatePropertyKind::Core(property) => property.try_into_integer(),
_ => None, _ => 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 { match self {
CommitTemplatePropertyKind::Core(property) => property.try_into_plain_text(), 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) { match (self, other) {
(CommitTemplatePropertyKind::Core(lhs), CommitTemplatePropertyKind::Core(rhs)) => { (CommitTemplatePropertyKind::Core(lhs), CommitTemplatePropertyKind::Core(rhs)) => {
lhs.try_into_eq(rhs) lhs.try_into_eq(rhs)
@ -645,10 +643,7 @@ impl<'repo> IntoTemplateProperty<'repo> for CommitTemplatePropertyKind<'repo> {
} }
} }
fn try_into_cmp( fn try_into_cmp(self, other: Self) -> Option<BoxedTemplateProperty<'repo, Ordering>> {
self,
other: Self,
) -> Option<Box<dyn TemplateProperty<Output = Ordering> + 'repo>> {
match (self, other) { match (self, other) {
(CommitTemplatePropertyKind::Core(lhs), CommitTemplatePropertyKind::Core(rhs)) => { (CommitTemplatePropertyKind::Core(lhs), CommitTemplatePropertyKind::Core(rhs)) => {
lhs.try_into_cmp(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::FunctionCallNode;
use crate::template_parser::TemplateDiagnostics; use crate::template_parser::TemplateDiagnostics;
use crate::template_parser::TemplateParseResult; use crate::template_parser::TemplateParseResult;
use crate::templater::BoxedTemplateProperty;
use crate::templater::Template; use crate::templater::Template;
use crate::templater::TemplateProperty;
/// General-purpose template language for basic value types. /// 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) pub fn add_keyword<F>(&mut self, name: &'static str, build: F)
where where
F: Fn( F: Fn(
Box<dyn TemplateProperty<Output = C> + 'a>, BoxedTemplateProperty<'a, C>,
) -> TemplateParseResult<GenericTemplatePropertyKind<'a, C>> ) -> TemplateParseResult<GenericTemplatePropertyKind<'a, C>>
+ 'a, + 'a,
{ {
@ -131,16 +131,14 @@ impl<'a, C> TemplateLanguage<'a> for GenericTemplateLanguage<'a, C> {
} }
impl<'a, C> GenericTemplateLanguage<'a, C> { impl<'a, C> GenericTemplateLanguage<'a, C> {
pub fn wrap_self( pub fn wrap_self(property: BoxedTemplateProperty<'a, C>) -> GenericTemplatePropertyKind<'a, C> {
property: Box<dyn TemplateProperty<Output = C> + 'a>,
) -> GenericTemplatePropertyKind<'a, C> {
GenericTemplatePropertyKind::Self_(property) GenericTemplatePropertyKind::Self_(property)
} }
} }
pub enum GenericTemplatePropertyKind<'a, C> { pub enum GenericTemplatePropertyKind<'a, C> {
Core(CoreTemplatePropertyKind<'a>), Core(CoreTemplatePropertyKind<'a>),
Self_(Box<dyn TemplateProperty<Output = C> + 'a>), Self_(BoxedTemplateProperty<'a, C>),
} }
impl<'a, C> IntoTemplateProperty<'a> for GenericTemplatePropertyKind<'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 { match self {
GenericTemplatePropertyKind::Core(property) => property.try_into_boolean(), GenericTemplatePropertyKind::Core(property) => property.try_into_boolean(),
GenericTemplatePropertyKind::Self_(_) => None, 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 { match self {
GenericTemplatePropertyKind::Core(property) => property.try_into_integer(), GenericTemplatePropertyKind::Core(property) => property.try_into_integer(),
GenericTemplatePropertyKind::Self_(_) => None, 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 { match self {
GenericTemplatePropertyKind::Core(property) => property.try_into_plain_text(), GenericTemplatePropertyKind::Core(property) => property.try_into_plain_text(),
GenericTemplatePropertyKind::Self_(_) => None, 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) { match (self, other) {
(GenericTemplatePropertyKind::Core(lhs), GenericTemplatePropertyKind::Core(rhs)) => { (GenericTemplatePropertyKind::Core(lhs), GenericTemplatePropertyKind::Core(rhs)) => {
lhs.try_into_eq(rhs) lhs.try_into_eq(rhs)
@ -189,10 +187,7 @@ impl<'a, C> IntoTemplateProperty<'a> for GenericTemplatePropertyKind<'a, C> {
} }
} }
fn try_into_cmp( fn try_into_cmp(self, other: Self) -> Option<BoxedTemplateProperty<'a, Ordering>> {
self,
other: Self,
) -> Option<Box<dyn TemplateProperty<Output = Ordering> + 'a>> {
match (self, other) { match (self, other) {
(GenericTemplatePropertyKind::Core(lhs), GenericTemplatePropertyKind::Core(rhs)) => { (GenericTemplatePropertyKind::Core(lhs), GenericTemplatePropertyKind::Core(rhs)) => {
lhs.try_into_cmp(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 /// Because the `GenericTemplateLanguage` doesn't provide a way to pass around
/// global resources, the keyword function is allowed to capture resources. /// global resources, the keyword function is allowed to capture resources.
pub type GenericTemplateBuildKeywordFn<'a, C> = Box< pub type GenericTemplateBuildKeywordFn<'a, C> = Box<
dyn Fn( dyn Fn(BoxedTemplateProperty<'a, C>) -> TemplateParseResult<GenericTemplatePropertyKind<'a, C>>
Box<dyn TemplateProperty<Output = C> + 'a>,
) -> TemplateParseResult<GenericTemplatePropertyKind<'a, C>>
+ 'a, + 'a,
>; >;

View File

@ -37,10 +37,10 @@ use crate::template_parser;
use crate::template_parser::FunctionCallNode; use crate::template_parser::FunctionCallNode;
use crate::template_parser::TemplateDiagnostics; use crate::template_parser::TemplateDiagnostics;
use crate::template_parser::TemplateParseResult; use crate::template_parser::TemplateParseResult;
use crate::templater::BoxedTemplateProperty;
use crate::templater::PlainTextFormattedProperty; use crate::templater::PlainTextFormattedProperty;
use crate::templater::Template; use crate::templater::Template;
use crate::templater::TemplateFormatter; use crate::templater::TemplateFormatter;
use crate::templater::TemplateProperty;
use crate::templater::TemplatePropertyExt as _; use crate::templater::TemplatePropertyExt as _;
use crate::templater::TimestampRange; use crate::templater::TimestampRange;
@ -137,13 +137,13 @@ impl OperationTemplateLanguage {
} }
pub fn wrap_operation( pub fn wrap_operation(
property: Box<dyn TemplateProperty<Output = Operation> + 'static>, property: BoxedTemplateProperty<'static, Operation>,
) -> OperationTemplatePropertyKind { ) -> OperationTemplatePropertyKind {
OperationTemplatePropertyKind::Operation(property) OperationTemplatePropertyKind::Operation(property)
} }
pub fn wrap_operation_id( pub fn wrap_operation_id(
property: Box<dyn TemplateProperty<Output = OperationId> + 'static>, property: BoxedTemplateProperty<'static, OperationId>,
) -> OperationTemplatePropertyKind { ) -> OperationTemplatePropertyKind {
OperationTemplatePropertyKind::OperationId(property) OperationTemplatePropertyKind::OperationId(property)
} }
@ -151,8 +151,8 @@ impl OperationTemplateLanguage {
pub enum OperationTemplatePropertyKind { pub enum OperationTemplatePropertyKind {
Core(CoreTemplatePropertyKind<'static>), Core(CoreTemplatePropertyKind<'static>),
Operation(Box<dyn TemplateProperty<Output = Operation>>), Operation(BoxedTemplateProperty<'static, Operation>),
OperationId(Box<dyn TemplateProperty<Output = OperationId>>), OperationId(BoxedTemplateProperty<'static, OperationId>),
} }
impl IntoTemplateProperty<'static> for OperationTemplatePropertyKind { 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 { match self {
OperationTemplatePropertyKind::Core(property) => property.try_into_boolean(), OperationTemplatePropertyKind::Core(property) => property.try_into_boolean(),
OperationTemplatePropertyKind::Operation(_) => None, 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 { match self {
OperationTemplatePropertyKind::Core(property) => property.try_into_integer(), OperationTemplatePropertyKind::Core(property) => property.try_into_integer(),
_ => None, _ => 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 { match self {
OperationTemplatePropertyKind::Core(property) => property.try_into_plain_text(), 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) { match (self, other) {
( (
OperationTemplatePropertyKind::Core(lhs), 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) { match (self, other) {
( (
OperationTemplatePropertyKind::Core(lhs), OperationTemplatePropertyKind::Core(lhs),

View File

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

View File

@ -394,6 +394,8 @@ tuple_impls! {
(0 T0, 1 T1, 2 T2, 3 T3) (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. /// `TemplateProperty` adapters that are useful when implementing methods.
pub trait TemplatePropertyExt: TemplateProperty { pub trait TemplatePropertyExt: TemplateProperty {
/// Translates to a property that will apply fallible `function` to an /// 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. /// 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 where
Self: Sized + 'a, Self: Sized + 'a,
{ {