sylvia_derive/parser/attributes/
attr.rs

1use proc_macro2::{Span, TokenStream};
2use proc_macro_error::emit_error;
3use syn::parse::{Error, Parse, ParseStream, Parser};
4use syn::spanned::Spanned;
5use syn::{Ident, MetaList, Result, Token};
6
7use super::MsgType;
8
9/// Type wrapping data parsed from `sv::msg_attr` attribute.
10#[derive(Clone, Debug)]
11pub struct VariantAttrForwarding {
12    pub attrs: TokenStream,
13    pub span: Span,
14}
15
16impl VariantAttrForwarding {
17    pub fn new(attr: &MetaList) -> Self {
18        VariantAttrForwarding {
19            attrs: attr.tokens.clone(),
20            span: attr.span(),
21        }
22    }
23}
24
25/// Type wrapping data parsed from `sv::attr` attribute.
26#[derive(Clone, Debug)]
27pub struct MsgAttrForwarding {
28    pub msg_type: MsgType,
29    pub attrs: TokenStream,
30}
31
32impl MsgAttrForwarding {
33    pub fn new(attr: &MetaList) -> Result<Self> {
34        MsgAttrForwarding::parse
35            .parse2(attr.tokens.clone())
36            .map_err(|err| {
37                emit_error!(attr.tokens.span(), err);
38                err
39            })
40    }
41}
42
43impl Parse for MsgAttrForwarding {
44    fn parse(input: ParseStream) -> Result<Self> {
45        let error_msg =
46            "Expected attribute of the form: `#[sv::msg_attr(msg_type, attribute_to_forward)]`";
47        let msg_type: Ident = input
48            .parse()
49            .map_err(|err| Error::new(err.span(), error_msg))?;
50        let _: Token![,] = input
51            .parse()
52            .map_err(|err| Error::new(err.span(), error_msg))?;
53        let attrs: TokenStream = input
54            .parse()
55            .map_err(|err| Error::new(err.span(), error_msg))?;
56        if attrs.is_empty() {
57            return Err(Error::new(attrs.span(), error_msg));
58        }
59        let msg_type = match msg_type.to_string().as_str() {
60            "exec" => MsgType::Exec,
61            "query" => MsgType::Query,
62            "instantiate" => MsgType::Instantiate,
63            "migrate" => MsgType::Migrate,
64            "reply" => MsgType::Reply,
65            "sudo" => MsgType::Sudo,
66            _ => return Err(Error::new(
67                msg_type.span(),
68                "Invalid message type, expected one of: `exec`, `query`, `instantiate`, `migrate`, `reply` or `sudo`.",
69            ))
70        };
71        Ok(Self { msg_type, attrs })
72    }
73}