Как я могу извлечь тип из атрибута процедурного макроса с помощью darling?

#rust #rust-proc-macros

Вопрос:

Мне нужно иметь возможность извлекать дизель-манипулятор типа, в идеале таким образом, чтобы можно было воспроизводить атрибуты data_loader для преобразования в несколько типов.

 #[derive(Loadable)]
#[data_loader(handler = DieselHandler<FooLoader>)]
 

Если я использую handler: syn::Type , возникает ошибка:

граница признака syn::Type: FromMeta не удовлетворена признак FromMeta не реализован для syn::Type

Как я могу передать тип здесь и, возможно, даже проверить структуру оболочки?

 #[derive(Debug, FromDeriveInput)]
#[darling(attributes(data_loader))]
struct LoadByArgs {
  #[darling(default)]
  internal: bool,
  handler: ????,
}

#[proc_macro_derive(Loadable, attributes(data_loader))]
pub fn load_by(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
  let input = parse_macro_input!(input as DeriveInput);

  let LoadByArgs {
    internal, handler
  } = FromDeriveInput::from_derive_input(amp;input).expect("can't parse attribute");

  let expanded = quote! {
      ...
  };

  proc_macro::TokenStream::from(expanded)
}
 

Комментарии:

1. Я не добился большого успеха в этом, не выражая типы в виде строк. т. #[data_loader(handler = "DieselHandler<FooLoader>")] е.. handler затем может быть a syn::Path в вашем коде.

2. Я думаю, это потому, что darling уже некоторое время не обновлялся, и раньше это было синтаксическим ограничением.

3. Я надеялся сделать это без кавычек и в идеале с таким синтаксисом, как #[data_loader(DieselHandler<FooLoader>)] . Знаете ли вы о милой альтернативе, которая помогла бы здесь? Я никогда раньше не пытался написать процедурный макрос, поэтому я все еще собираю вещи

4. Нет, я ничего не видел. Но дорогая действительно делает жизнь намного проще, когда у тебя есть атрибуты. Это спасло меня от 100 строк очень грязного кода.

5. Да, я определенно вижу ценность и действительно не хочу писать ничего из этого от руки. Надеюсь, дорогая добавит поддержку или, возможно, примеры, если это уже возможно

Ответ №1:

darling требует кавычек при написании #[attr(foo = "bar")] , потому syn что не считает форму без кавычек допустимой Meta , и Meta это основа darling всего API.

Это согласуется с serde тем , что я по-прежнему рассматриваю как наиболее близкое к стандарту для API-интерфейсов proc-macro в Rust.

Вы можете использовать darling::util::PathList , если хотите написать что-то подобное #[data_loader(DieselHandler)] . Технически параметры типа являются частью пути, поэтому DieselHandler<FooLoader> должны работать на бумаге.