Skip to content

Commit 7400c0b

Browse files
committed
replace derive macro 'DynamicEnum' by the derive macro helper attribute 'enum_dynamic' for derive macro 'Enum'
Signed-off-by: fbrouille <[email protected]>
1 parent c173103 commit 7400c0b

File tree

5 files changed

+243
-219
lines changed

5 files changed

+243
-219
lines changed

glib-macros/src/enum_derive.rs

Lines changed: 161 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ use syn::{
99
Variant,
1010
};
1111

12-
use crate::utils::{crate_ident_new, gen_enum_from_glib, parse_nested_meta_items, NestedMetaItem};
12+
use crate::utils::{
13+
crate_ident_new, gen_enum_from_glib, parse_nested_meta_items, parse_optional_nested_meta_items,
14+
NestedMetaItem,
15+
};
1316

1417
// generates glib::gobject_ffi::GEnumValue structs mapping the enum such as:
1518
// glib::gobject_ffi::GEnumValue {
@@ -70,6 +73,7 @@ pub fn impl_enum(input: &syn::DeriveInput) -> TokenStream {
7073
Data::Enum(ref e) => &e.variants,
7174
_ => abort_call_site!("#[derive(glib::Enum)] only supports enums"),
7275
};
76+
let (g_enum_values, nb_enum_values) = gen_enum_values(name, enum_variants);
7377

7478
let mut gtype_name = NestedMetaItem::<syn::LitStr>::new("name")
7579
.required()
@@ -84,13 +88,152 @@ pub fn impl_enum(input: &syn::DeriveInput) -> TokenStream {
8488
Ok(attr) => attr,
8589
};
8690
let gtype_name = gtype_name.value.unwrap();
87-
let from_glib = gen_enum_from_glib(name, enum_variants);
88-
let (enum_values, nb_enum_values) = gen_enum_values(name, enum_variants);
91+
92+
let mut plugin_type = NestedMetaItem::<syn::Path>::new("plugin_type").value_required();
93+
let mut lazy_registration =
94+
NestedMetaItem::<syn::LitBool>::new("lazy_registration").value_required();
95+
96+
let found = parse_optional_nested_meta_items(
97+
&input.attrs,
98+
"enum_dynamic",
99+
&mut [&mut plugin_type, &mut lazy_registration],
100+
);
89101

90102
let crate_ident = crate_ident_new();
91103

104+
let register_enum = match found {
105+
Err(e) => return e.to_compile_error(),
106+
Ok(None) => register_enum_as_static(
107+
&crate_ident,
108+
name,
109+
gtype_name,
110+
g_enum_values,
111+
nb_enum_values,
112+
),
113+
Ok(Some(_)) => {
114+
let plugin_ty = plugin_type
115+
.value
116+
.map(|p| p.into_token_stream())
117+
.unwrap_or(quote!(#crate_ident::TypeModule));
118+
let lazy_registration = lazy_registration.value.map(|b| b.value).unwrap_or_default();
119+
register_enum_as_dynamic(
120+
&crate_ident,
121+
plugin_ty,
122+
lazy_registration,
123+
name,
124+
gtype_name,
125+
g_enum_values,
126+
nb_enum_values,
127+
)
128+
}
129+
};
130+
131+
let from_glib = gen_enum_from_glib(name, enum_variants);
132+
133+
quote! {
134+
impl #crate_ident::translate::IntoGlib for #name {
135+
type GlibType = i32;
136+
137+
#[inline]
138+
fn into_glib(self) -> i32 {
139+
self as i32
140+
}
141+
}
142+
143+
impl #crate_ident::translate::TryFromGlib<i32> for #name {
144+
type Error = i32;
145+
146+
#[inline]
147+
unsafe fn try_from_glib(value: i32) -> ::core::result::Result<Self, i32> {
148+
let from_glib = || {
149+
#from_glib
150+
};
151+
152+
from_glib().ok_or(value)
153+
}
154+
}
155+
156+
impl #crate_ident::translate::FromGlib<i32> for #name {
157+
#[inline]
158+
unsafe fn from_glib(value: i32) -> Self {
159+
use #crate_ident::translate::TryFromGlib;
160+
161+
Self::try_from_glib(value).unwrap()
162+
}
163+
}
164+
165+
impl #crate_ident::value::ValueType for #name {
166+
type Type = Self;
167+
}
168+
169+
unsafe impl<'a> #crate_ident::value::FromValue<'a> for #name {
170+
type Checker = #crate_ident::value::GenericValueTypeChecker<Self>;
171+
172+
#[inline]
173+
unsafe fn from_value(value: &'a #crate_ident::value::Value) -> Self {
174+
#crate_ident::translate::from_glib(#crate_ident::gobject_ffi::g_value_get_enum(
175+
#crate_ident::translate::ToGlibPtr::to_glib_none(value).0
176+
))
177+
}
178+
}
179+
180+
impl #crate_ident::value::ToValue for #name {
181+
#[inline]
182+
fn to_value(&self) -> #crate_ident::value::Value {
183+
let mut value = #crate_ident::value::Value::for_value_type::<Self>();
184+
unsafe {
185+
#crate_ident::gobject_ffi::g_value_set_enum(
186+
#crate_ident::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
187+
#crate_ident::translate::IntoGlib::into_glib(*self)
188+
)
189+
}
190+
value
191+
}
192+
193+
#[inline]
194+
fn value_type(&self) -> #crate_ident::Type {
195+
<Self as #crate_ident::StaticType>::static_type()
196+
}
197+
}
198+
199+
impl ::std::convert::From<#name> for #crate_ident::Value {
200+
#[inline]
201+
fn from(v: #name) -> Self {
202+
#crate_ident::value::ToValue::to_value(&v)
203+
}
204+
}
205+
206+
impl #crate_ident::StaticType for #name {
207+
#[inline]
208+
fn static_type() -> #crate_ident::Type {
209+
Self::register_enum()
210+
}
211+
}
212+
213+
#register_enum
214+
215+
impl #crate_ident::HasParamSpec for #name {
216+
type ParamSpec = #crate_ident::ParamSpecEnum;
217+
type SetValue = Self;
218+
type BuilderFn = fn(&::core::primitive::str, Self) -> #crate_ident::ParamSpecEnumBuilder<Self>;
219+
220+
fn param_spec_builder() -> Self::BuilderFn {
221+
|name, default_value| Self::ParamSpec::builder_with_default(name, default_value)
222+
}
223+
}
224+
}
225+
}
226+
227+
// Registers the enum as a static type.
228+
fn register_enum_as_static(
229+
crate_ident: &TokenStream,
230+
name: &Ident,
231+
gtype_name: syn::LitStr,
232+
g_enum_values: TokenStream,
233+
nb_enum_values: usize,
234+
) -> TokenStream {
92235
// registers the enum on first use (lazy registration).
93-
let register_enum = quote! {
236+
quote! {
94237
impl #name {
95238
/// Registers the enum only once.
96239
#[inline]
@@ -100,7 +243,7 @@ pub fn impl_enum(input: &syn::DeriveInput) -> TokenStream {
100243

101244
ONCE.call_once(|| {
102245
static mut VALUES: [#crate_ident::gobject_ffi::GEnumValue; #nb_enum_values] = [
103-
#enum_values
246+
#g_enum_values
104247
#crate_ident::gobject_ffi::GEnumValue {
105248
value: 0,
106249
value_name: ::std::ptr::null(),
@@ -121,51 +264,20 @@ pub fn impl_enum(input: &syn::DeriveInput) -> TokenStream {
121264
}
122265
}
123266
}
124-
};
125-
126-
impl_enum_(name, from_glib, register_enum)
267+
}
127268
}
128269

129-
pub fn impl_dynamic_enum(input: &syn::DeriveInput) -> TokenStream {
130-
let name = &input.ident;
131-
132-
let enum_variants = match input.data {
133-
Data::Enum(ref e) => &e.variants,
134-
_ => abort_call_site!("#[derive(glib::Enum)] only supports enums"),
135-
};
136-
137-
let mut gtype_name = NestedMetaItem::<syn::LitStr>::new("name")
138-
.required()
139-
.value_required();
140-
let mut plugin_type = NestedMetaItem::<syn::Path>::new("plugin_type").value_required();
141-
let mut lazy_registration =
142-
NestedMetaItem::<syn::LitBool>::new("lazy_registration").value_required();
143-
let found = parse_nested_meta_items(
144-
&input.attrs,
145-
"enum_type",
146-
&mut [&mut gtype_name, &mut plugin_type, &mut lazy_registration],
147-
);
148-
149-
match found {
150-
Ok(None) => {
151-
abort_call_site!("#[derive(glib::DynamicEnum)] requires #[enum_type(name = \"EnumTypeName\"[, plugin_type = <subclass_of_glib::TypePlugin>][, lazy_registration = true|false])]")
152-
}
153-
Err(e) => return e.to_compile_error(),
154-
Ok(attr) => attr,
155-
};
156-
157-
let crate_ident = crate_ident_new();
158-
159-
let gtype_name = gtype_name.value.unwrap();
160-
let plugin_ty = plugin_type
161-
.value
162-
.map(|p| p.into_token_stream())
163-
.unwrap_or(quote!(#crate_ident::TypeModule));
164-
let lazy_registration = lazy_registration.value.map(|b| b.value).unwrap_or_default();
165-
166-
let from_glib = gen_enum_from_glib(name, enum_variants);
167-
let (g_enum_values, nb_enum_values) = gen_enum_values(name, enum_variants);
168-
270+
// The following implementations follows the lifecycle of plugins and of dynamic types (see [`TypePluginExt`] and [`TypeModuleExt`]).
271+
// An enum can be reregistered as a dynamic type.
272+
fn register_enum_as_dynamic(
273+
crate_ident: &TokenStream,
274+
plugin_ty: TokenStream,
275+
lazy_registration: bool,
276+
name: &Ident,
277+
gtype_name: syn::LitStr,
278+
g_enum_values: TokenStream,
279+
nb_enum_values: usize,
280+
) -> TokenStream {
169281
// Wrap each GEnumValue to EnumValue
170282
let g_enum_values_expr: ExprArray = parse_quote! { [#g_enum_values] };
171283
let enum_values_iter = g_enum_values_expr.elems.iter().map(|v| {
@@ -184,7 +296,7 @@ pub fn impl_dynamic_enum(input: &syn::DeriveInput) -> TokenStream {
184296

185297
// The following implementations follows the lifecycle of plugins and of dynamic types (see [`TypePluginExt`] and [`TypeModuleExt`]).
186298
// An enum can be reregistered as a dynamic type.
187-
let register_enum_impl = if lazy_registration {
299+
if lazy_registration {
188300
// registers the enum as a dynamic type on the first use (lazy registration).
189301
// a weak reference on the plugin is stored and will be used later on the first use of the enum.
190302
// this implementation relies on a static storage of a weak reference on the plugin and of the GLib type to know if the enum has been registered.
@@ -309,108 +421,5 @@ pub fn impl_dynamic_enum(input: &syn::DeriveInput) -> TokenStream {
309421
}
310422
}
311423
}
312-
};
313-
314-
impl_enum_(name, from_glib, register_enum_impl)
315-
}
316-
317-
pub fn impl_enum_(
318-
name: &syn::Ident,
319-
from_glib: TokenStream,
320-
register_enum: TokenStream,
321-
) -> TokenStream {
322-
let crate_ident = crate_ident_new();
323-
324-
quote! {
325-
impl #crate_ident::translate::IntoGlib for #name {
326-
type GlibType = i32;
327-
328-
#[inline]
329-
fn into_glib(self) -> i32 {
330-
self as i32
331-
}
332-
}
333-
334-
impl #crate_ident::translate::TryFromGlib<i32> for #name {
335-
type Error = i32;
336-
337-
#[inline]
338-
unsafe fn try_from_glib(value: i32) -> ::core::result::Result<Self, i32> {
339-
let from_glib = || {
340-
#from_glib
341-
};
342-
343-
from_glib().ok_or(value)
344-
}
345-
}
346-
347-
impl #crate_ident::translate::FromGlib<i32> for #name {
348-
#[inline]
349-
unsafe fn from_glib(value: i32) -> Self {
350-
use #crate_ident::translate::TryFromGlib;
351-
352-
Self::try_from_glib(value).unwrap()
353-
}
354-
}
355-
356-
impl #crate_ident::value::ValueType for #name {
357-
type Type = Self;
358-
}
359-
360-
unsafe impl<'a> #crate_ident::value::FromValue<'a> for #name {
361-
type Checker = #crate_ident::value::GenericValueTypeChecker<Self>;
362-
363-
#[inline]
364-
unsafe fn from_value(value: &'a #crate_ident::value::Value) -> Self {
365-
#crate_ident::translate::from_glib(#crate_ident::gobject_ffi::g_value_get_enum(
366-
#crate_ident::translate::ToGlibPtr::to_glib_none(value).0
367-
))
368-
}
369-
}
370-
371-
impl #crate_ident::value::ToValue for #name {
372-
#[inline]
373-
fn to_value(&self) -> #crate_ident::value::Value {
374-
let mut value = #crate_ident::value::Value::for_value_type::<Self>();
375-
unsafe {
376-
#crate_ident::gobject_ffi::g_value_set_enum(
377-
#crate_ident::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
378-
#crate_ident::translate::IntoGlib::into_glib(*self)
379-
)
380-
}
381-
value
382-
}
383-
384-
#[inline]
385-
fn value_type(&self) -> #crate_ident::Type {
386-
<Self as #crate_ident::StaticType>::static_type()
387-
}
388-
}
389-
390-
impl ::std::convert::From<#name> for #crate_ident::Value {
391-
#[inline]
392-
fn from(v: #name) -> Self {
393-
#crate_ident::value::ToValue::to_value(&v)
394-
}
395-
}
396-
397-
impl #crate_ident::StaticType for #name {
398-
#[inline]
399-
fn static_type() -> #crate_ident::Type {
400-
Self::register_enum()
401-
}
402-
}
403-
404-
#register_enum
405-
406-
impl #crate_ident::HasParamSpec for #name {
407-
type ParamSpec = #crate_ident::ParamSpecEnum;
408-
type SetValue = Self;
409-
type BuilderFn = fn(&::core::primitive::str, Self) -> #crate_ident::ParamSpecEnumBuilder<Self>;
410-
411-
fn param_spec_builder() -> Self::BuilderFn {
412-
|name, default_value| Self::ParamSpec::builder_with_default(name, default_value)
413-
}
414-
}
415424
}
416425
}

0 commit comments

Comments
 (0)