1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use proc_macro2::TokenStream; |
4 | use quote::quote; |
5 | use syn::Data; |
6 | |
7 | use crate::utils::{crate_ident_new, gen_enum_from_glib, parse_nested_meta_items, NestedMetaItem}; |
8 | |
9 | pub fn impl_error_domain(input: &syn::DeriveInput) -> syn::Result<TokenStream> { |
10 | let name = &input.ident; |
11 | |
12 | let enum_variants = match input.data { |
13 | Data::Enum(ref e) => &e.variants, |
14 | _ => { |
15 | return Err(syn::Error::new_spanned( |
16 | input, |
17 | "#[derive(glib::ErrorDomain)] only supports enums" , |
18 | )) |
19 | } |
20 | }; |
21 | |
22 | let mut domain_name = NestedMetaItem::<syn::LitStr>::new("name" ) |
23 | .required() |
24 | .value_required(); |
25 | let found = parse_nested_meta_items(&input.attrs, "error_domain" , &mut [&mut domain_name])?; |
26 | |
27 | if found.is_none() { |
28 | return Err(syn::Error::new_spanned( |
29 | input, |
30 | "#[derive(glib::ErrorDomain)] requires #[error_domain(name = \"domain-name \")]" , |
31 | )); |
32 | }; |
33 | let domain_name = domain_name.value.unwrap(); |
34 | let crate_ident = crate_ident_new(); |
35 | |
36 | let from_glib = gen_enum_from_glib(name, enum_variants); |
37 | |
38 | Ok(quote! { |
39 | impl #crate_ident::error::ErrorDomain for #name { |
40 | #[inline] |
41 | fn domain() -> #crate_ident::Quark { |
42 | use #crate_ident::translate::from_glib; |
43 | |
44 | static QUARK: ::std::sync::OnceLock<#crate_ident::Quark> = ::std::sync::OnceLock::new(); |
45 | *QUARK.get_or_init(|| unsafe { |
46 | from_glib(#crate_ident::ffi::g_quark_from_static_string(concat!(#domain_name, " \0" ) as *const ::core::primitive::str as *const _)) |
47 | }) |
48 | } |
49 | |
50 | #[inline] |
51 | fn code(self) -> i32 { |
52 | self as i32 |
53 | } |
54 | |
55 | #[inline] |
56 | fn from(value: i32) -> ::core::option::Option<Self> |
57 | where |
58 | Self: ::std::marker::Sized |
59 | { |
60 | #from_glib |
61 | } |
62 | } |
63 | }) |
64 | } |
65 | |