sylvia_derive/parser/attributes/
override_entry_point.rs

1use proc_macro2::TokenStream;
2use proc_macro_error::emit_error;
3use quote::quote;
4use syn::parse::{Error, Parse, ParseStream, Parser};
5use syn::{parenthesized, Ident, MetaList, Path, Result, Token, Type};
6
7use crate::crate_module;
8use crate::parser::MsgType;
9
10/// Type wrapping data parsed from `sv::override_entry_points` attribute.
11#[derive(Debug, Clone)]
12pub struct OverrideEntryPoint {
13    entry_point: Path,
14    msg_name: Type,
15    msg_type: MsgType,
16}
17
18impl OverrideEntryPoint {
19    pub fn new(attr: &MetaList) -> Result<Self> {
20        OverrideEntryPoint::parse
21            .parse2(attr.tokens.clone())
22            .map_err(|err| {
23                emit_error!(err.span(), err);
24                err
25            })
26    }
27
28    pub fn emit_multitest_dispatch(&self) -> TokenStream {
29        let Self {
30            entry_point,
31            msg_name,
32            msg_type,
33            ..
34        } = self;
35
36        let sylvia = crate_module();
37        let values = msg_type.emit_ctx_values();
38
39        quote! {
40            #entry_point ( #values .into(), #sylvia ::cw_std::from_json::< #msg_name >(&msg)?)
41                .map_err(Into::into)
42        }
43    }
44}
45
46pub trait FilteredOverrideEntryPoints {
47    fn get_entry_point(&self, ty: MsgType) -> Option<&OverrideEntryPoint>;
48}
49
50impl FilteredOverrideEntryPoints for &[OverrideEntryPoint] {
51    fn get_entry_point(&self, ty: MsgType) -> Option<&OverrideEntryPoint> {
52        self.iter().find(|entry_point| entry_point.msg_type == ty)
53    }
54}
55
56impl FilteredOverrideEntryPoints for &Vec<OverrideEntryPoint> {
57    fn get_entry_point(&self, ty: MsgType) -> Option<&OverrideEntryPoint> {
58        self.iter().find(|entry_point| entry_point.msg_type == ty)
59    }
60}
61
62impl Parse for OverrideEntryPoint {
63    fn parse(input: ParseStream) -> Result<Self> {
64        let ty: Ident = input.parse()?;
65        let _: Token![=] = input.parse()?;
66        let entry_point = input.parse()?;
67
68        let msg_content;
69        parenthesized!(msg_content in input);
70
71        let msg_name = msg_content.parse()?;
72
73        let msg_type = match ty.to_string().as_str() {
74            "exec" =>  MsgType::Exec,
75            "instantiate" =>  MsgType::Instantiate,
76            "query" =>  MsgType::Instantiate,
77            "migrate" => MsgType::Migrate,
78            "reply" => MsgType::Reply,
79            "sudo" =>  MsgType::Sudo,
80            &_ => {
81                return Err(Error::new(
82                    ty.span(),
83                    "Invalid entry point. Expected exec, instantiate, query, migrate, reply or sudo. Found {ty}",
84                ))
85            }
86        };
87
88        Ok(Self {
89            entry_point,
90            msg_name,
91            msg_type,
92        })
93    }
94}