Как читать атрибуты программно в Rust - PullRequest
0 голосов
/ 07 февраля 2019

Я хотел бы читать атрибуты программно.Например, у меня есть структура, атрибуты которой прикреплены к каждому полю:

#[derive(Clone, Debug, PartialEq, Message)]
pub struct Person {
    #[prost(string, tag="1")]
    pub name: String,
    /// Unique ID number for this person.
    #[prost(int32, tag="2")]
    pub id: i32,
    #[prost(string, tag="3")]
    pub email: String,
    #[prost(message, repeated, tag="4")]
    pub phones: Vec<person::PhoneNumber>,
}

( source )

Я хотел бы найти тег, связанный споле электронной почты.

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

let tag = Person::email::prost::tag;

1 Ответ

0 голосов
/ 07 февраля 2019

Поскольку атрибуты доступны только для чтения во время компиляции, вам необходимо написать процедурный макрос для решения такой проблемы.

Вы можете найти информацию со следующими обозначениями в вашем макросе.

  • Имя поля с ident
  • Атрибут содержимого с meta

После того, как вы найдете имя поля и свою мету, вы можете сопоставить строковый результат с заданным входным параметром в макросе, как показано ниже:

macro_rules! my_macro {
    (struct $name:ident {
        $(#[$field_attribute:meta] $field_name:ident: $field_type:ty,)*
    }) => {
        struct $name {
            $(#[$field_attribute] $field_name: $field_type,)*
        }

        impl $name {
            fn get_field_attribute(field_name_prm : &str) -> &'static str {
                let fields = vec![$(stringify!($field_name,$field_attribute)),*];
                let mut ret_val = "Field Not Found";

                fields.iter().for_each(|field_str| {
                    let parts : Vec<&str> = field_str.split(' ').collect();
                    if parts[0] == field_name_prm{
                        ret_val = parts[2];
                    }
                });
                ret_val
            }
        }
    }
}

my_macro! {
    struct S {
        #[serde(default)]
        field1: String,
        #[serde(default)]
        field2: String,
    }
}

Обратите внимание, что предполагается, что каждое поле вструктура имеет атрибут.И каждое объявление поля заканчивается ,, включая последнее поле.Но с некоторыми изменениями в регулярном выражении вы можете сделать его доступным и для необязательных атрибутов.

Здесь рабочее решение в Playground

Для получения дополнительной информации о обозначениях здесь ссылка

Также вы можете быстро просмотреть процедурные макросы здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...