| 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 | |