代码之家  ›  专栏  ›  技术社区  ›  Jamie

如何正确地将包含双冒号的路径传递给此宏?

  •  0
  • Jamie  · 技术社区  · 8 月前

    我在用 schemars 在我的代码库中广泛存在,我正在用以下(简化)类型填充一个相当大的向量:

    #[derive(Serialize, Deserialize, Debug, Clone)]
    pub struct CommandDescription {
        /// The name for the command/action as it would appear in the JSON.
        pub cmd: String,
        /// Parameters the command takes
        pub parameters: Option<RootSchema>,
    }
    

    结构的完整定义有更多的字段,它们是以下字段的组合 String RootSchema 类型。

    在我的代码中,我有数百种这样的定义:

    CommandDescription {
        cmd: String::from(api_schema::about::ABOUT_CMD),
        parameters: Some(schema_for!(api_schema::about::AboutCmd)),
    },
    

    我想创建一个宏,但我很难 schema_for!() 宏。

    我的宏观定义是:

    macro_rules! command_description {
        ($api_path:path, $prefix:ident, $type_name_cmd:ident) => {
            CommandDescription {
                cmd: String::from(concat!(
                    stringify!($api_path),
                    "::",
                    stringify!($prefix),
                    "_CMD"
                )),
                parameters: Some(schema_for!($api_path::$type_name_cmd)),
            }
        };
    }
    

    我援引:

        command_description!(
            api_schema::about,
            ABOUT,
            AboutCmd
        )
    

    但编译器建议我封装 $api_path schema_for!() 宏放在尖括号中,但它是一个路径,而不是一个类型:我知道这一点,因为如果我添加 <$api_path> 我听说这不是一种类型。

    error: missing angle brackets in associated item path
       --> src/bin/rudi-service.rs:674:42
        |
    674 |               parameters: Some(schema_for!($api_path::$type_name_cmd)),
        |                                            ^^^^^^^^^
        = note: this error originates in the macro `command_description` (in Nightly builds, run with -Z macro-backtrace for more info)
    help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths
        |
    674 |             parameters: Some(schema_for!(<$api_path>::$type_name_cmd)),
        |                                          +         +
    

    我是否使用了错误的片段说明符 $api_path 参数?

    1 回复  |  直到 8 月前
        1
  •  2
  •   Chayim Friedman    8 月前

    问题是,一旦某样东西被捕获为 path (或大多数其他片段说明符),它不能再被分解,也不能用更多的片段进行扩展。解决方案是单独捕获分段:

    macro_rules! command_description {
        ($($api_path:ident)::+, $prefix:ident, $type_name_cmd:ident) => {
            CommandDescription {
                cmd: String::from(concat!(
                    stringify!($($api_path)::+),
                    "::",
                    stringify!($prefix),
                    "_CMD"
                )),
                parameters: Some(schema_for!($($api_path)::+::$type_name_cmd)),
            }
        };
    }
    
    推荐文章