Rust proc_macro_derive (с синхронизацией), генерирующий вариант перечисления для сопоставления - PullRequest
0 голосов
/ 19 апреля 2020

Я ржавый новичок ie, я начал одну неделю go, но этот язык уже очень увлекателен. Я переписываю nodejs проект в ржавчине, чтобы получить лучшую производительность, и на данный момент просто безумие, насколько он быстрее.

На самом деле я пишу proc_derive_macro (используя "syn" ящик) для генерации метод по некоторой спецификации c struct. Я почти закончил, но я не нашел, как генерировать enum-вариант. Я попытаюсь объяснить себя.

Это моя генерация кода (с использованием цитаты!)

quote! {
        // The generated impl.
        impl #name /*#ty_generics #where_clause*/ {
            pub fn from_config(config: &IndicatorConfig) -> Result<Self, Error> {
                let mut #name_lower = #name::default()?;
                for (k, v) in config.opts.iter() {
                    println!("{:?} {:?}", k, v);
                    match (k.as_str(), v) {
                        ("label", Values::String(val)) => {
                            #name_lower.label = val.clone();
                        }
                        ("agg_time", Values::String(val)) => {
                            #name_lower.agg_time = Some(val.clone());
                        }
                        #(
                            (#fields_name_str, Values::Unteger(val)) => {
                                #name_lower.#fields_name = val.clone();
                            }
                        )*
                        (&_, _) => {}
                    }
                }
                #name_lower.init()?;
                Ok(#name_lower)
            }
        }
    };

Как мы видим, я генерирую большую часть своего кода здесь

(#fields_name_str, Values::Unteger(val)) => {
   #name_lower.#fields_name = val.clone();
}

Но я не нашел способа сгенерировать «enum-вариант для сопоставления» (я не знаю, как мы это называем, надеюсь, вы поймете):

Values::String(val)
OR
Values::Unteger(val)
...

I ' m пишу функцию, которая создаст сопоставление вариантов в соответствии с типом параметра, найденным внутри структуры:

fn create_variant_match(ty: &str) -> PatTupleStruct {
    let variant = match ty {
        "u32" => Ident::new("Unteger", Span::call_site()),
        ...
        _ => unimplemented!(),
    };
}

На самом деле я создаю Ident, но я хочу создать "enum option match" -> Значения: : Unteger (val).

Я наблюдал за работой c синхронизации, часами пытался найти способ, но это немного сложно для моего фактического уровня, поэтому я надеюсь, что кто-то объяснит мне, как сделать это.

1 Ответ

0 голосов
/ 20 апреля 2020

Я нашел простой способ сделать это. Просто нужно проанализировать строку (которую я могу форматировать раньше) с помощью синтаксического анализатора. Я не думал об этом, прежде чем пытался построить Expr вручную (немного глупо ^^)

syn::parse_str::<Expr>("Values::Unteger(val)")

, что сгенерирует необходимый Expr

...