V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
horou
V2EX  ›  Rust

简单的写了个 Rust 结构体字段验证过程宏

  •  
  •   horou · 2021-11-12 15:11:58 +08:00 · 1789 次点击
    这是一个创建于 1136 天前的主题,其中的信息可能已经有所发展或是发生改变。

    自己这两天边学边写,搞了个简单的验证器过程宏,

    用在 web 框架里面可以比较方便的验证前端传来的各个字段

    github 地址https://github.com/horou-dsk/fields-valid.git

    刚学过程宏,写的很简陋,内置的功能不多

    有大佬觉得写的不好的话,还望指点迷津

    示例:

    use fields_valid::FieldsValidate;
    
    #[derive(FieldsValidate)]
    struct User {
        // #[valid(len(5, 11), email, regex("^[\\d@\\.]+$"), "邮箱格式不正确")]
        #[valid(len(5, 17), "The length of the mailbox must be between 5-16")]
        #[valid(email, "E-mail format is incorrect")]
        email: String,
        #[valid(len(8, 17), "The minimum password length is 8 digits and the maximum is 16 digits")]
        password: String,
        #[valid(eq("#password"), "The two passwords are inconsistent")]
        password2: String,
        #[valid(len(5, 12), "The length of the phone number is incorrect")]
        #[valid(regex("\\d+"), "The phone number must be a number")]
        phone: Option<String>,
        #[valid(range(5.8, 10.1), "Incorrect amount returned")]
        amount: u32,
    }
    
    #[inline]
    fn fields_validate<T: FieldsValidate>(fields: &T) -> Result<(), &'static str> {
        fields.fields_validate()
    }
    
    fn main() {
        let user = User {
            email: "[email protected]".to_string(),
            password: "12ndd232.23".to_string(),
            password2: "1225".to_string(),
            phone: None, //Some("111111".to_string())
            amount: 7,
        };
        
        println!("{:?}", fields_validate(&user));
    }
    
    5 条回复    2021-11-17 16:15:52 +08:00
    Kilerd
        1
    Kilerd  
       2021-11-12 15:58:02 +08:00   ❤️ 1
    写得太糙了。
    1. impl fields_valid::FieldsValidate for #struct_ident {

    如果 struct 带泛型,带生命周期就生成不了了。

    2. fn fields_validate(&self) -> std::result::Result<(), &'static str> {

    错误返回一个&str 也不知道如何吐槽好。

    3. 代码里面出现了很多「期望是绝对引用」的地方,例如:
    final_tokenstream.extend(quote!(use bigdecimal::ToPrimitive;));
    return std::result::Result::Err(#msg);

    然而如果用户自己定义了一个 `mod bigdecimal` 你这里就炸了。 在宏里面「第三方库的绝对引用」应该是
    `use ::bigdecimal::ToPrimitive;` 和 `::std::result::Result::Err(#msg);`

    4. ValidateRule 的解析建议使用 darling 这个库帮忙解析参数


    5. lib 里面的
    #[inline]
    pub fn match_regex(rx: &str, v: &str) -> bool {
    regex::Regex::new(rx).unwrap().is_match(v)
    }


    每次 parse 都 new 一个 regex ,然后害 unwrap 也是挺简单粗暴的。
    horou
        2
    horou  
    OP
       2021-11-12 16:22:28 +08:00
    @Kilerd O(∩_∩)O 哈哈~, 谢谢大佬的回复,刚学过程宏,好多地方还不懂,后面根据大佬的建议再多优化优化,
    大佬有没有比较全面的过程宏教程啊,网上搜过程宏教程资料太少了。 _(:з」∠)_
    miniliuke
        3
    miniliuke  
       2021-11-12 16:48:13 +08:00 via iPhone
    1 楼大佬看得很仔细认真,还是先学好基础吧,把宏放一边吧,宏功能很强但没啥用
    horou
        4
    horou  
    OP
       2021-11-12 17:43:39 +08:00
    @miniliuke rust 断断续续学了有 1 年多了,基础差不多都了解了,主要是想学学宏用来提高编码效率。
    rahuahua
        5
    rahuahua  
       2021-11-17 16:15:52 +08:00
    @miniliuke 看别人写的代码都是大量的用宏
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   977 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 22:59 · PVG 06:59 · LAX 14:59 · JFK 17:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.