Skip to content

Commit ceb9ac2

Browse files
committed
Use Enums for faster property retrieval
1 parent f8fd537 commit ceb9ac2

File tree

1 file changed

+74
-13
lines changed

1 file changed

+74
-13
lines changed

glib-macros/src/properties.rs

Lines changed: 74 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -364,19 +364,20 @@ fn expand_property_fn(props: &[PropDesc]) -> TokenStream2 {
364364
..
365365
} = p;
366366

367+
let enum_ident = name_to_enum_ident(name.value());
367368
let span = p.attrs_span;
368369
get.as_ref().map(|get| {
369370
let body = match (member, get) {
370371
(_, MaybeCustomFn::Custom(expr)) => quote!(
371-
#name => Ok((#expr)(&self).to_value())
372+
DerivedPropertiesEnum::#enum_ident => Ok((#expr)(&self).to_value())
372373
),
373374
(None, MaybeCustomFn::Default) => quote!(
374-
#name => Ok(
375+
DerivedPropertiesEnum::#enum_ident => Ok(
375376
#crate_ident::PropertyGet::get(&self.#field_ident, |v| v.to_value())
376377
)
377378
),
378379
(Some(member), MaybeCustomFn::Default) => quote!(
379-
#name => Ok(
380+
DerivedPropertiesEnum::#enum_ident => Ok(
380381
#crate_ident::PropertyGet::get(&self.#field_ident, |v| v.#member.to_value())
381382
)
382383
),
@@ -385,10 +386,12 @@ fn expand_property_fn(props: &[PropDesc]) -> TokenStream2 {
385386
})
386387
});
387388
quote!(
388-
fn derived_property<'a>(&self, _obj: &Self::Type, _id: usize, pspec: &'a #crate_ident::ParamSpec) -> Result<#crate_ident::Value, #crate_ident::subclass::object::MissingPropertyHandler<'a>> {
389-
match pspec.name() {
389+
fn derived_property<'a>(&self, _obj: &Self::Type, id: usize, pspec: &'a #crate_ident::ParamSpec) -> Result<#crate_ident::Value, #crate_ident::subclass::object::MissingPropertyHandler<'a>> {
390+
let prop = DerivedPropertiesEnum::try_from(id-1)
391+
.map_err(|_| #crate_ident::subclass::object::MissingPropertyHandler::<'a>::from(pspec))?;
392+
match prop {
390393
#(#match_branch_get,)*
391-
p => Err(pspec.into())
394+
_ => Err(pspec.into())
392395
}
393396
}
394397
)
@@ -405,18 +408,19 @@ fn expand_set_property_fn(props: &[PropDesc]) -> TokenStream2 {
405408
} = p;
406409

407410
let crate_ident = crate_ident_new();
411+
let enum_ident = name_to_enum_ident(name.value());
408412
let span = p.attrs_span;
409413
let expect = quote!(.expect("Can't convert glib::value to property type"));
410414
set.as_ref().map(|set| {
411415
let body = match (member, set) {
412416
(_, MaybeCustomFn::Custom(expr)) => quote!(
413-
#name => {
417+
DerivedPropertiesEnum::#enum_ident => {
414418
(#expr)(&self, #crate_ident::Value::get(value)#expect);
415419
Ok(())
416420
}
417421
),
418422
(None, MaybeCustomFn::Default) => quote!(
419-
#name => {
423+
DerivedPropertiesEnum::#enum_ident => {
420424
#crate_ident::PropertySet::set(
421425
&self.#field_ident,
422426
#crate_ident::Value::get(value)#expect
@@ -425,7 +429,7 @@ fn expand_set_property_fn(props: &[PropDesc]) -> TokenStream2 {
425429
}
426430
),
427431
(Some(member), MaybeCustomFn::Default) => quote!(
428-
#name => {
432+
DerivedPropertiesEnum::#enum_ident => {
429433
#crate_ident::PropertySetNested::set_nested(
430434
&self.#field_ident,
431435
move |v| v.#member = #crate_ident::Value::get(value)#expect
@@ -438,10 +442,12 @@ fn expand_set_property_fn(props: &[PropDesc]) -> TokenStream2 {
438442
})
439443
});
440444
quote!(
441-
fn derived_set_property<'a>(&self, _obj: &Self::Type, _id: usize, value: &#crate_ident::Value, pspec: &'a #crate_ident::ParamSpec) -> Result<(), #crate_ident::subclass::object::MissingPropertyHandler<'a>> {
442-
match pspec.name() {
445+
fn derived_set_property<'a>(&self, _obj: &Self::Type, id: usize, value: &#crate_ident::Value, pspec: &'a #crate_ident::ParamSpec) -> Result<(), #crate_ident::subclass::object::MissingPropertyHandler<'a>> {
446+
let prop = DerivedPropertiesEnum::try_from(id-1)
447+
.map_err(|_| #crate_ident::subclass::object::MissingPropertyHandler::<'a>::from(pspec))?;
448+
match prop {
443449
#(#match_branch_set,)*
444-
p => Err(pspec.into())
450+
_ => Err(pspec.into())
445451
}
446452
}
447453
)
@@ -527,20 +533,71 @@ fn expand_connect_prop_notify_impl(props: &[PropDesc]) -> TokenStream2 {
527533
}
528534

529535
fn expand_emit_impl(props: &[PropDesc]) -> TokenStream2 {
536+
let crate_ident = crate_ident_new();
530537
let emit_fns = props.iter().map(|p| {
531538
let name = &p.name;
532539
let fn_prototype = {
533540
let fn_ident = format_ident!("emit_{}", name_to_ident(name));
534541
quote!(pub fn #fn_ident(&self))
535542
};
536543
let span = p.attrs_span;
544+
let enum_ident = name_to_enum_ident(name.value());
537545
quote_spanned!(span=> #fn_prototype {
538-
self.notify(#name);
546+
self.notify_by_pspec(
547+
&<<Self as #crate_ident::object::ObjectSubclassIs>::Subclass
548+
as #crate_ident::subclass::object::DerivedObjectProperties>::derived_properties()
549+
[DerivedPropertiesEnum::#enum_ident as usize]
550+
);
539551
})
540552
});
541553
quote!(#(#emit_fns)*)
542554
}
543555

556+
fn name_to_enum_ident(mut name: String) -> syn::Ident {
557+
let mut slice = name.as_mut_str();
558+
while let Some(i) = slice.find('-') {
559+
let (head, tail) = slice.split_at_mut(i);
560+
if let Some(c) = head.get_mut(0..1) {
561+
c.make_ascii_uppercase();
562+
}
563+
slice = &mut tail[1..];
564+
}
565+
if let Some(c) = slice.get_mut(0..1) {
566+
c.make_ascii_uppercase();
567+
}
568+
let enum_member: String = name.split('-').collect();
569+
format_ident!("{}", enum_member)
570+
}
571+
572+
fn expand_properties_enum(props: &[PropDesc]) -> TokenStream2 {
573+
let properties: Vec<syn::Ident> = props
574+
.iter()
575+
.map(|p| {
576+
let name: String = p.name.value();
577+
name_to_enum_ident(name)
578+
})
579+
.collect();
580+
let props = properties.iter();
581+
let indices = 0..properties.len();
582+
quote! {
583+
#[repr(usize)]
584+
#[derive(Debug, Copy, Clone)]
585+
enum DerivedPropertiesEnum {
586+
#(#props,)*
587+
}
588+
impl std::convert::TryFrom<usize> for DerivedPropertiesEnum {
589+
type Error = usize;
590+
591+
fn try_from(item: usize) -> Result<Self, Self::Error> {
592+
match item {
593+
#(#indices => Ok(Self::#properties),)*
594+
_ => Err(item)
595+
}
596+
}
597+
}
598+
}
599+
}
600+
544601
pub fn impl_derive_props(input: PropsMacroInput) -> TokenStream {
545602
let struct_ident = &input.ident;
546603
let crate_ident = crate_ident_new();
@@ -551,9 +608,13 @@ pub fn impl_derive_props(input: PropsMacroInput) -> TokenStream {
551608
let getset_properties_impl = expand_getset_properties_impl(&input.props);
552609
let connect_prop_notify_impl = expand_connect_prop_notify_impl(&input.props);
553610
let emit_impl = expand_emit_impl(&input.props);
611+
let properties_enum = expand_properties_enum(&input.props);
612+
554613
let expanded = quote! {
555614
use #crate_ident::{PropertyGet, PropertySet, ToValue};
556615

616+
#properties_enum
617+
557618
impl #crate_ident::subclass::object::DerivedObjectProperties for #struct_ident {
558619
#fn_properties
559620
#fn_property

0 commit comments

Comments
 (0)