Skip to content

Commit b1b0d1b

Browse files
committed
glib-macros: port attribute parsing to use deluxe crate
1 parent e73ff61 commit b1b0d1b

9 files changed

+214
-327
lines changed

glib-macros/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ proc-macro2 = "1.0"
1919
quote = "1.0"
2020
syn = { version = "1.0", features = ["full"], default-features = false }
2121
proc-macro-crate = "1.0"
22+
deluxe = "0.3.2"
2223

2324
[lib]
2425
proc-macro = true

glib-macros/src/boxed_derive.rs

+17-15
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
// Take a look at the license at the top of the repository in the LICENSE file.
22

33
use proc_macro2::{Ident, TokenStream};
4-
use proc_macro_error::abort_call_site;
54
use quote::quote;
65

7-
use crate::utils::{crate_ident_new, find_attribute_meta, find_nested_meta, parse_name};
6+
use crate::utils::crate_ident_new;
87

98
fn gen_option_to_ptr() -> TokenStream {
109
quote! {
@@ -91,21 +90,22 @@ fn gen_impl_to_value_optional(name: &Ident, crate_ident: &TokenStream) -> TokenS
9190
}
9291
}
9392

94-
pub fn impl_boxed(input: &syn::DeriveInput) -> TokenStream {
95-
let name = &input.ident;
93+
#[derive(deluxe::ExtractAttributes, Default)]
94+
#[deluxe(attributes(boxed_type))]
95+
struct BoxedType {
96+
name: String,
97+
#[deluxe(default)]
98+
nullable: bool,
99+
}
96100

97-
let gtype_name = match parse_name(input, "boxed_type") {
98-
Ok(name) => name,
99-
Err(e) => abort_call_site!(
100-
"{}: #[derive(glib::Boxed)] requires #[boxed_type(name = \"BoxedTypeName\")]",
101-
e
102-
),
103-
};
101+
pub fn impl_boxed(mut input: syn::DeriveInput) -> TokenStream {
102+
let name = &input.ident;
104103

105-
let meta = find_attribute_meta(&input.attrs, "boxed_type")
106-
.unwrap()
107-
.unwrap();
108-
let nullable = find_nested_meta(&meta, "nullable").is_some();
104+
let errors = deluxe::Errors::new();
105+
let BoxedType {
106+
name: gtype_name,
107+
nullable,
108+
} = deluxe::extract_attributes_optional(&mut input.attrs, &errors);
109109

110110
let crate_ident = crate_ident_new();
111111

@@ -121,6 +121,8 @@ pub fn impl_boxed(input: &syn::DeriveInput) -> TokenStream {
121121
};
122122

123123
quote! {
124+
#errors
125+
124126
impl #crate_ident::subclass::boxed::BoxedType for #name {
125127
const NAME: &'static str = #gtype_name;
126128
}

glib-macros/src/enum_derive.rs

+42-41
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,20 @@ use proc_macro_error::abort_call_site;
66
use quote::{quote, quote_spanned};
77
use syn::{punctuated::Punctuated, spanned::Spanned, token::Comma, Data, Ident, Variant};
88

9-
use crate::utils::{
10-
crate_ident_new, gen_enum_from_glib, parse_item_attributes, parse_name, ItemAttribute,
11-
};
9+
use crate::utils::{crate_ident_new, gen_enum_from_glib};
10+
11+
#[derive(deluxe::ExtractAttributes, Default)]
12+
#[deluxe(attributes(enum_type))]
13+
struct EnumType {
14+
name: String,
15+
}
16+
17+
#[derive(deluxe::ExtractAttributes, Default)]
18+
#[deluxe(attributes(enum_value), default)]
19+
struct EnumValue {
20+
name: Option<String>,
21+
nick: Option<String>,
22+
}
1223

1324
// Generate glib::gobject_ffi::GEnumValue structs mapping the enum such as:
1425
// glib::gobject_ffi::GEnumValue {
@@ -18,35 +29,24 @@ use crate::utils::{
1829
// },
1930
fn gen_enum_values(
2031
enum_name: &Ident,
21-
enum_variants: &Punctuated<Variant, Comma>,
32+
enum_variants: &mut Punctuated<Variant, Comma>,
33+
errors: &deluxe::Errors,
2234
) -> (TokenStream, usize) {
2335
let crate_ident = crate_ident_new();
2436

2537
// start at one as GEnumValue array is null-terminated
2638
let mut n = 1;
27-
let recurse = enum_variants.iter().map(|v| {
28-
let name = &v.ident;
29-
let mut value_name = name.to_string().to_upper_camel_case();
30-
let mut value_nick = name.to_string().to_kebab_case();
31-
32-
let attrs = parse_item_attributes("enum_value", &v.attrs);
33-
let attrs = match attrs {
34-
Ok(attrs) => attrs,
35-
Err(e) => abort_call_site!(
36-
"{}: derive(glib::Enum) enum supports only the following optional attributes: #[enum_value(name = \"The Cat\", nick = \"chat\")]",
37-
e
38-
),
39-
};
40-
41-
attrs.into_iter().for_each(|attr|
42-
match attr {
43-
ItemAttribute::Name(n) => value_name = n,
44-
ItemAttribute::Nick(n) => value_nick = n,
45-
}
46-
);
39+
let recurse = enum_variants.iter_mut().map(|v| {
40+
let EnumValue {
41+
name: value_name,
42+
nick: value_nick,
43+
} = deluxe::extract_attributes_optional(v, errors);
4744

48-
let value_name = format!("{value_name}\0");
49-
let value_nick = format!("{value_nick}\0");
45+
let name = &v.ident;
46+
let mut value_name = value_name.unwrap_or_else(|| name.to_string().to_upper_camel_case());
47+
let mut value_nick = value_nick.unwrap_or_else(|| name.to_string().to_kebab_case());
48+
value_name.push('\0');
49+
value_nick.push('\0');
5050

5151
n += 1;
5252
quote_spanned! {v.span()=>
@@ -65,28 +65,27 @@ fn gen_enum_values(
6565
)
6666
}
6767

68-
pub fn impl_enum(input: &syn::DeriveInput) -> TokenStream {
69-
let name = &input.ident;
70-
71-
let enum_variants = match input.data {
72-
Data::Enum(ref e) => &e.variants,
68+
pub fn impl_enum(mut input: syn::DeriveInput) -> TokenStream {
69+
let enum_variants = match &mut input.data {
70+
Data::Enum(e) => &mut e.variants,
7371
_ => abort_call_site!("#[derive(glib::Enum)] only supports enums"),
7472
};
7573

76-
let gtype_name = match parse_name(input, "enum_type") {
77-
Ok(name) => name,
78-
Err(e) => abort_call_site!(
79-
"{}: #[derive(glib::Enum)] requires #[enum_type(name = \"EnumTypeName\")]",
80-
e
81-
),
82-
};
74+
let errors = deluxe::Errors::new();
75+
let EnumType {
76+
name: mut gtype_name,
77+
} = deluxe::extract_attributes_optional(&mut input.attrs, &errors);
78+
gtype_name.push('\0');
8379

80+
let name = &input.ident;
8481
let from_glib = gen_enum_from_glib(name, enum_variants);
85-
let (enum_values, nb_enum_values) = gen_enum_values(name, enum_variants);
82+
let (enum_values, nb_enum_values) = gen_enum_values(name, enum_variants, &errors);
8683

8784
let crate_ident = crate_ident_new();
8885

8986
quote! {
87+
#errors
88+
9089
impl #crate_ident::translate::IntoGlib for #name {
9190
type GlibType = i32;
9291

@@ -175,9 +174,11 @@ pub fn impl_enum(input: &syn::DeriveInput) -> TokenStream {
175174
},
176175
];
177176

178-
let name = ::std::ffi::CString::new(#gtype_name).expect("CString::new failed");
179177
unsafe {
180-
let type_ = #crate_ident::gobject_ffi::g_enum_register_static(name.as_ptr(), VALUES.as_ptr());
178+
let type_ = #crate_ident::gobject_ffi::g_enum_register_static(
179+
#gtype_name.as_ptr() as *const _,
180+
VALUES.as_ptr(),
181+
);
181182
let type_: #crate_ident::Type = #crate_ident::translate::from_glib(type_);
182183
assert!(type_.is_valid());
183184
TYPE = type_;

glib-macros/src/error_domain_derive.rs

+18-12
Original file line numberDiff line numberDiff line change
@@ -5,37 +5,43 @@ use proc_macro_error::abort_call_site;
55
use quote::quote;
66
use syn::Data;
77

8-
use crate::utils::{crate_ident_new, gen_enum_from_glib, parse_name};
8+
use crate::utils::{crate_ident_new, gen_enum_from_glib};
99

10-
pub fn impl_error_domain(input: &syn::DeriveInput) -> TokenStream {
10+
#[derive(deluxe::ExtractAttributes, Default)]
11+
#[deluxe(attributes(error_domain))]
12+
struct ErrorDomainType {
13+
name: String,
14+
}
15+
16+
pub fn impl_error_domain(mut input: syn::DeriveInput) -> TokenStream {
1117
let name = &input.ident;
1218

13-
let enum_variants = match input.data {
14-
Data::Enum(ref e) => &e.variants,
19+
let enum_variants = match &mut input.data {
20+
Data::Enum(e) => &mut e.variants,
1521
_ => abort_call_site!("#[derive(glib::ErrorDomain)] only supports enums"),
1622
};
1723

18-
let domain_name = match parse_name(input, "error_domain") {
19-
Ok(name) => name,
20-
Err(e) => abort_call_site!(
21-
"{}: #[derive(glib::ErrorDomain)] requires #[error_domain(name = \"domain-name\")]",
22-
e
23-
),
24-
};
24+
let errors = deluxe::Errors::new();
25+
let ErrorDomainType {
26+
name: mut domain_name,
27+
} = deluxe::extract_attributes_optional(&mut input.attrs, &errors);
28+
domain_name.push('\0');
2529

2630
let crate_ident = crate_ident_new();
2731

2832
let from_glib = gen_enum_from_glib(name, enum_variants);
2933

3034
quote! {
35+
#errors
36+
3137
impl #crate_ident::error::ErrorDomain for #name {
3238
#[inline]
3339
fn domain() -> #crate_ident::Quark {
3440
use #crate_ident::translate::from_glib;
3541

3642
static QUARK: #crate_ident::once_cell::sync::Lazy<#crate_ident::Quark> =
3743
#crate_ident::once_cell::sync::Lazy::new(|| unsafe {
38-
from_glib(#crate_ident::ffi::g_quark_from_static_string(concat!(#domain_name, "\0") as *const str as *const _))
44+
from_glib(#crate_ident::ffi::g_quark_from_static_string(#domain_name.as_ptr() as *const _))
3945
});
4046
*QUARK
4147
}

0 commit comments

Comments
 (0)