Skip to content

Commit

Permalink
review macros to use static dispatch instead of dynamic dispatch
Browse files Browse the repository at this point in the history
Signed-off-by: fbrouille <[email protected]>
  • Loading branch information
fbrouille committed Oct 18, 2023
1 parent 22ab846 commit 0fe707d
Show file tree
Hide file tree
Showing 9 changed files with 257 additions and 234 deletions.
114 changes: 72 additions & 42 deletions glib-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -650,32 +650,43 @@ pub fn object_subclass(_attr: TokenStream, item: TokenStream) -> TokenStream {
///
/// A dynamic type must be explicitly registered when the system loads the
/// implementation (see [`TypePlugin`] and [`TypeModule`].
/// Therefore, unlike for static types a dynamic type can be registered
/// several times.
/// Therefore, whereas an object subclass can be registered only once as a
/// static type, it can be registered several times as a dynamic type.
///
/// A dynamic type is never unregistered. The system calls
/// [`TypePluginExt::unuse`] to unload the type's implementation. If the
/// plugin's implementation is a module, the dynamic type is marked as unloaded
/// and must be registered again, when the module is reloaded.
/// [`TypePluginExt::unuse`] to unload implementation of the dynamic type. If
/// the [`TypePlugin`] subclass is a [`TypeModule`], the dynamic type is
/// marked as unloaded and the object subclass must be registered again as a
/// dynamic type when the module is reloaded.
///
/// This macro provides two behaviors when registering a dynamic type:
/// This macro provides two behaviors when registering an object subclass as a
/// dynamic type:
///
/// By default the dynamic type is registered when the system loads the
/// implementation (e.g. when the module is loaded)
/// By default an object subclass is registered as a dynamic type when the
/// system loads its implementation (e.g. when the module is loaded):
/// ```ignore
/// #[glib::dynamic_object_subclass]
/// impl ObjectSubclass for MyType { ... }
/// ```
///
/// Optionally setting the macro attribute to `lazy_registration = true`
/// postpones the registration of the dynamic type on first use (when `type_()`
/// is called for the first time), similarly to the [`macro@object_subclass`]
/// macro.
/// Optionally setting the macro attribute `lazy_registration` to `true`
/// postpones registration on the first use (when `type_()` is called for the
/// first time), similarly to the [`macro@object_subclass`]
/// macro:
/// ```ignore
/// #[glib::dynamic_object_subclass(lazy_registration = true)]
/// impl ObjectSubclass for MyType { ... }
/// ```
///
/// By default an object subclass is considered to be registered as a dynamic
/// type within a [`TypeModule`] subclass. Optionally setting the macro
/// attribute `plugin_type` allows to register an object subclass as a dynamic
/// type within a given [`TypePlugin`] subclass:
/// ```ignore
/// #[glib::dynamic_object_subclass(plugin_type = MyPlugin)]
/// impl ObjectSubclass for MyType { ... }
/// ```
///
/// [`ObjectSubclass`]: ../glib/subclass/types/trait.ObjectSubclass.html
/// [`TypePlugin`]: ../glib/gobject/type_plugin/struct.TypePlugin.html
/// [`TypeModule`]: ../glib/gobject/type_module/struct.TypeModule.html
Expand All @@ -684,18 +695,21 @@ pub fn object_subclass(_attr: TokenStream, item: TokenStream) -> TokenStream {
#[proc_macro_error]
pub fn dynamic_object_subclass(attr: TokenStream, item: TokenStream) -> TokenStream {
use proc_macro_error::abort_call_site;
let attr = if attr.is_empty() {
None
} else {
match syn::parse::<syn::Expr>(attr) {
Ok(expr) => Some(expr),
Err(_) => abort_call_site!(object_subclass_attribute::WRONG_EXPRESSION_MSG),
let attrs = match syn::parse::Parser::parse(
syn::punctuated::Punctuated::<syn::Expr, syn::Token![,]>::parse_terminated,
attr,
) {
Ok(attrs)
if attrs
.iter()
.all(|attr| matches!(attr, syn::Expr::Assign(_))) =>
{
attrs
}
_ => abort_call_site!(object_subclass_attribute::WRONG_EXPRESSION_MSG),
};
match syn::parse::<syn::ItemImpl>(item) {
Ok(input) => {
object_subclass_attribute::impl_dynamic_object_subclass(attr.as_ref(), &input).into()
}
Ok(input) => object_subclass_attribute::impl_dynamic_object_subclass(&attrs, &input).into(),
Err(_) => abort_call_site!(object_subclass_attribute::WRONG_PLACE_MSG),
}
}
Expand Down Expand Up @@ -726,36 +740,47 @@ pub fn object_interface(_attr: TokenStream, item: TokenStream) -> TokenStream {
}

/// Macro for boilerplate of [`ObjectInterface`] implementations specific to
/// dynamic interfaces.
/// dynamic types.
///
/// A dynamic interface must be explicitly registered when the system loads the
/// A dynamic type must be explicitly registered when the system loads the
/// implementation (see [`TypePlugin`] and [`TypeModule`].
/// Therefore, unlike for static interfaces a dynamic interface can be
/// registered several times.
/// Therefore, whereas an object interface can be registered only once as a
/// static type, it can be registered several times as a dynamic type.
///
/// A dynamic interface is never unregistered. The system calls
/// [`TypePluginExt::unuse`] to unload the type's implementation. If the
/// plugin's implementation is a module, the dynamic interface is marked as
/// unloaded and must be registered again, when the module is reloaded.
/// A dynamic type is never unregistered. The system calls
/// [`TypePluginExt::unuse`] to unload implementation of the dynamic type. If
/// the [`TypePlugin`] subclass is a [`TypeModule`], the dynamic type is
/// marked as unloaded and the object interface must be registered again as a
/// dynamic type when the module is reloaded.
///
/// This macro provides two behaviors when registering a dynamic interface:
/// This macro provides two behaviors when registering an object interface as a
/// dynamic type:
///
/// By default the dynamic interface is registered when the system loads the
/// implementation (e.g. when the module is loaded)
/// By default an object interface is registered as a dynamic type when the
/// system loads its implementation (e.g. when the module is loaded):
/// ```ignore
/// #[glib::dynamic_object_interface]
/// unsafe impl ObjectInterface for MyInterface { ... }
/// ```
///
/// Optionally setting the macro attribute to `lazy_registration = true`
/// postpones the registration of the dynamic interface on first use (when
/// `type_()` is called for the first time), similarly to the
/// Optionally setting the macro attribute `lazy_registration` to `true`
/// postpones registration on the first use (when `type_()` is called for the
/// first time), similarly to the [`macro@object_subclass`]
/// [`macro@object_interface`] macro.
/// ```ignore
/// #[glib::dynamic_object_interface(lazy_registration = true)]
/// unsafe impl ObjectInterface for MyInterface { ... }
/// ```
///
/// By default an object interface is considered to be registered as a dynamic
/// type within a [`TypeModule`] subclass. Optionally setting the macro
/// attribute `plugin_type` allows to register an object interface as a dynamic
/// type within a given [`TypePlugin`] subclass:
/// ```ignore
/// #[glib::dynamic_object_interface(plugin_type = MyPlugin)]
/// unsafe impl ObjectInterface for MyInterface { ... }
/// ```
///
/// [`ObjectInterface`]: ../glib/subclass/interface/trait.ObjectInterface.html
/// [`TypePlugin`]: ../glib/gobject/type_plugin/struct.TypePlugin.html
/// [`TypeModule`]: ../glib/gobject/type_module/struct.TypeModule.html
Expand All @@ -764,17 +789,22 @@ pub fn object_interface(_attr: TokenStream, item: TokenStream) -> TokenStream {
#[proc_macro_error]
pub fn dynamic_object_interface(attr: TokenStream, item: TokenStream) -> TokenStream {
use proc_macro_error::abort_call_site;
let attr = if attr.is_empty() {
None
} else {
match syn::parse::<syn::Expr>(attr) {
Ok(expr) => Some(expr),
Err(_) => abort_call_site!(object_interface_attribute::WRONG_EXPRESSION_MSG),
let attrs = match syn::parse::Parser::parse(
syn::punctuated::Punctuated::<syn::Expr, syn::Token![,]>::parse_terminated,
attr,
) {
Ok(attrs)
if attrs
.iter()
.all(|attr| matches!(attr, syn::Expr::Assign(_))) =>
{
attrs
}
_ => abort_call_site!(object_interface_attribute::WRONG_EXPRESSION_MSG),
};
match syn::parse::<syn::ItemImpl>(item) {
Ok(input) => {
object_interface_attribute::impl_dynamic_object_interface(attr.as_ref(), &input).into()
object_interface_attribute::impl_dynamic_object_interface(&attrs, &input).into()
}
Err(_) => abort_call_site!(object_interface_attribute::WRONG_PLACE_MSG),
}
Expand Down
Loading

0 comments on commit 0fe707d

Please sign in to comment.