cairo_lang_starknet/inline_macros/
selector.rs

1use cairo_lang_defs::extract_macro_single_unnamed_arg;
2use cairo_lang_defs::plugin::{
3    InlineMacroExprPlugin, InlinePluginResult, MacroPluginMetadata, NamedPlugin, PluginDiagnostic,
4    PluginGeneratedFile,
5};
6use cairo_lang_defs::plugin_utils::{PluginResultTrait, not_legacy_macro_diagnostic};
7use cairo_lang_parser::macro_helpers::AsLegacyInlineMacro;
8use cairo_lang_starknet_classes::keccak::starknet_keccak;
9use cairo_lang_syntax::node::{TypedStablePtr, TypedSyntaxNode, ast};
10use salsa::Database;
11
12/// Macro for expanding a selector to a string literal.
13#[derive(Debug, Default)]
14pub struct SelectorMacro;
15impl NamedPlugin for SelectorMacro {
16    const NAME: &'static str = "selector";
17}
18impl InlineMacroExprPlugin for SelectorMacro {
19    fn generate_code<'db>(
20        &self,
21        db: &'db dyn Database,
22        syntax: &ast::ExprInlineMacro<'db>,
23        _metadata: &MacroPluginMetadata<'_>,
24    ) -> InlinePluginResult<'db> {
25        let Some(legacy_inline_macro) = syntax.as_legacy_inline_macro(db) else {
26            return InlinePluginResult::diagnostic_only(not_legacy_macro_diagnostic(
27                syntax.as_syntax_node().stable_ptr(db),
28            ));
29        };
30        let arg = extract_macro_single_unnamed_arg!(
31            db,
32            &legacy_inline_macro,
33            ast::WrappedArgList::ParenthesizedArgList(_),
34            syntax.stable_ptr(db)
35        );
36
37        let ast::Expr::String(input_string) = arg else {
38            let diagnostics = vec![PluginDiagnostic::error(
39                syntax.stable_ptr(db).untyped(),
40                format!("`{}` macro argument must be a string", SelectorMacro::NAME),
41            )];
42            return InlinePluginResult { code: None, diagnostics };
43        };
44        let selector_string = input_string.string_value(db).unwrap();
45
46        let selector = starknet_keccak(selector_string.as_bytes());
47        InlinePluginResult {
48            code: Some(PluginGeneratedFile {
49                name: "selector_inline_macro".into(),
50                content: format!("0x{}", selector.to_str_radix(16)),
51                code_mappings: vec![],
52                aux_data: None,
53                diagnostics_note: Default::default(),
54                is_unhygienic: false,
55            }),
56            diagnostics: vec![],
57        }
58    }
59}