首页 > 其他 > 详细

Rust 使用声明宏替类(struct)添加反射信息

时间:2021-04-09 16:26:17      阅读:186      评论:0      收藏:0      [点我收藏+]
使用声明宏替类(struct)添加反射信息

按网上的说法,Rust语言由于没有runtime,因此不支持运行时反射。
我捣鼓了半天发现可以使用声明宏替类添加反射信息,
可以实现类似反射的效果。

贴在这儿供大家参考。

(代码在最底下,只是示意,不完整,请理解原理后自行完善)

简单说明

简单说明一下这段代码在做什么:

首先代码最后几行就是这个reflect_info!宏的用法:

#[macro_use]
reflect_info! {
    struct Test{
        uuu:u32,
        bbb:bool
    }
}

使用cargo expand可以看到这段代码的宏展开结果:

技术分享图片

可以看到,Test类经过宏的处理,添加了get_fields(),get_xxx_value(), set_xxx_value() 等方法;
只要用get_fields()获得字段及类型,我们就可以使用基于字段名称透过 getter, setter 来获取类的值或设置类的值。

虽然这个例子只实现了很简单的示意,但大抵还是完成了反射的基本功能;

代码

#[macro_export]
macro_rules! get_u32_value {
    ($name:expr, $condition:expr, $field:expr, u32) => {
        if $name == $condition  {
            return $field;
        }
    };
    ($($else:tt)*) => {};
}

#[macro_export]
macro_rules! get_bool_value {
    ($name:expr, $condition:expr, $field:expr, bool) => {
        if $name == $condition  {
            return $field;
        }
    };
    ($($else:tt)*) => {};
}

#[macro_export]
macro_rules! set_u32_value {
    ($name:expr, $condition:expr, $field:expr, $value:expr, u32) => {
        if $name == $condition  {
            $field = $value;
        }
    };
    ($($else:tt)*) => {};
}

#[macro_export]
macro_rules! set_bool_value {
    ($name:expr, $condition:expr, $field:expr, $value:expr, bool) => {
        if $name == $condition  {
            $field = $value;
        }
    };
    ($($else:tt)*) => {};
}

#[macro_export]
macro_rules! reflect_info {
    (
        $vis1:vis struct $name:ident {
            $(
                $vis2:vis $item:ident: $t:tt$(,)*
            ),+
        }
    ) => {
        $vis1 struct $name {
            $(
                $vis2 $item: $t,
            )+
        }

        impl $name {

            fn get_fields() -> HashMap<&‘static str,&‘static str> {
                let mut fields = HashMap::new();
                $(
                    fields.insert(stringify!($item),stringify!($t));
                )+
                return fields;
            }

            fn get_u32_value(&mut self, name: &str) -> u32{
                $(
                    get_u32_value!(name, stringify!($item), self.$item, $t);
                )+
            }

            fn get_bool_value(&mut self, name: &str) -> u32{
                $(
                    get_bool_value!(name, stringify!($item), self.$item, $t);
                )+
            }

             pub fn set_u32_value(&mut self, name: &str, value: u32){
                $(
                    set_u32_value!(name, stringify!($item), self.$item, value, $t);
                )*
            }

            pub fn set_bool_value(&mut self, name: &str, value: bool){
                $(
                    set_bool_value!(name, stringify!($item), self.$item, value, $t);
                )*
            }

        }
    };
}

#[macro_use]
reflect_info! {
    struct Test{
        uuu:u32,
        bbb:bool
    }
}

其他参考:

https://github.com/zkonge/husk/blob/2a75692de441a662af3c1d3dc7dfa2b0c93d73eb/src/tls_item.rs#L52

Rust 使用声明宏替类(struct)添加反射信息

原文:https://blog.51cto.com/oldycat/2694365

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!