summaryrefslogtreecommitdiff
path: root/crates/typst-macros
diff options
context:
space:
mode:
authorSébastien d'Herbais de Thun <sebastien.d.herbais@gmail.com>2023-11-27 11:37:30 +0100
committerGitHub <noreply@github.com>2023-11-27 11:37:30 +0100
commit0fbb1aaaaa04d93ae478df6dc268ab8fb13e2bf2 (patch)
tree81fca9a9e811fefba4763989766ddfc600302470 /crates/typst-macros
parente36a18b99135a96bbddbaea33a2116977d04e318 (diff)
Optimize `Content::has`, `Introspector::query_label`, and `MetaElem` (#2759)
Diffstat (limited to 'crates/typst-macros')
-rw-r--r--crates/typst-macros/src/elem.rs37
1 files changed, 37 insertions, 0 deletions
diff --git a/crates/typst-macros/src/elem.rs b/crates/typst-macros/src/elem.rs
index acb73ba5..e0306b70 100644
--- a/crates/typst-macros/src/elem.rs
+++ b/crates/typst-macros/src/elem.rs
@@ -738,6 +738,27 @@ fn create_native_elem_impl(element: &Elem) -> TokenStream {
}
});
+ // Fields that can be checked using the `has` method.
+ let field_has_matches = element.visible_fields().map(|field| {
+ let elem = &element.ident;
+ let name = &field.enum_ident;
+ let field_ident = &field.ident;
+
+ if field.ghost {
+ quote! {
+ <#elem as #foundations::ElementFields>::Fields::#name => false,
+ }
+ } else if field.inherent() {
+ quote! {
+ <#elem as #foundations::ElementFields>::Fields::#name => true,
+ }
+ } else {
+ quote! {
+ <#elem as #foundations::ElementFields>::Fields::#name => self.#field_ident.is_some(),
+ }
+ }
+ });
+
// Fields that can be set using the `set_field` method.
let field_set_matches = element
.visible_fields()
@@ -888,6 +909,10 @@ fn create_native_elem_impl(element: &Elem) -> TokenStream {
})
.unwrap_or_else(|| quote! { None });
+ let label_has_field = element
+ .unless_capability("Unlabellable", || quote! { self.label().is_some() })
+ .unwrap_or_else(|| quote! { false });
+
let mark_prepared = element
.unless_capability("Unlabellable", || quote! { self.prepared = true; })
.unwrap_or_else(|| quote! {});
@@ -1026,6 +1051,18 @@ fn create_native_elem_impl(element: &Elem) -> TokenStream {
}
}
+ fn has(&self, id: u8) -> bool {
+ let Ok(id) = <#ident as #foundations::ElementFields>::Fields::try_from(id) else {
+ return false;
+ };
+
+ match id {
+ <#ident as #foundations::ElementFields>::Fields::Label => #label_has_field,
+ #(#field_has_matches)*
+ _ => false,
+ }
+ }
+
fn fields(&self) -> #foundations::Dict {
let mut fields = #foundations::Dict::new();
#(#field_dict)*