diff options
| author | Laurenz <laurmaedje@gmail.com> | 2022-12-14 10:09:44 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2022-12-14 10:09:44 +0100 |
| commit | 9ba4d2c134479aad876a0e2ac4cd1622a353109e (patch) | |
| tree | a94e0e6ae53a1ba440e869fca26cc2ea0b179057 /macros/src/capability.rs | |
| parent | 4c73456fc1f5df8ebb3a89d9db657c3c54624d66 (diff) | |
New macro setup
Diffstat (limited to 'macros/src/capability.rs')
| -rw-r--r-- | macros/src/capability.rs | 44 |
1 files changed, 41 insertions, 3 deletions
diff --git a/macros/src/capability.rs b/macros/src/capability.rs index 7dd4c42a..aa98f584 100644 --- a/macros/src/capability.rs +++ b/macros/src/capability.rs @@ -1,10 +1,48 @@ use super::*; +use syn::parse::Parser; +use syn::punctuated::Punctuated; +use syn::Token; + /// Expand the `#[capability]` macro. -pub fn expand(body: syn::ItemTrait) -> Result<TokenStream> { - let ident = &body.ident; +pub fn capability(item: syn::ItemTrait) -> Result<TokenStream> { + let ident = &item.ident; Ok(quote! { - #body + #item impl ::typst::model::Capability for dyn #ident {} }) } + +/// Expand the `#[capable(..)]` macro. +pub fn capable(attr: TokenStream, item: syn::Item) -> Result<TokenStream> { + let (ident, generics) = match &item { + syn::Item::Struct(s) => (&s.ident, &s.generics), + syn::Item::Enum(s) => (&s.ident, &s.generics), + _ => bail!(item, "only structs and enums are supported"), + }; + + let (params, args, clause) = generics.split_for_impl(); + let checks = Punctuated::<Ident, Token![,]>::parse_terminated + .parse2(attr)? + .into_iter() + .map(|capability| { + quote! { + if id == ::std::any::TypeId::of::<dyn #capability>() { + return Some(unsafe { + ::typst::util::fat::vtable(self as &dyn #capability) + }); + } + } + }); + + Ok(quote! { + #item + + unsafe impl #params ::typst::model::Capable for #ident #args #clause { + fn vtable(&self, id: ::std::any::TypeId) -> ::std::option::Option<*const ()> { + #(#checks)* + None + } + } + }) +} |
