sylvia_derive/parser/attributes/
custom.rs

1use proc_macro_error::emit_error;
2use syn::parse::{Parse, ParseStream, Parser};
3use syn::{parse_quote, Error, Ident, MetaList, Result, Token, Type};
4
5use crate::crate_module;
6
7/// Type wrapping data parsed from `sv::custom` attribute.
8#[derive(Debug, Default)]
9pub struct Custom {
10    pub msg: Option<Type>,
11    pub query: Option<Type>,
12}
13
14impl Custom {
15    pub fn new(attr: &MetaList) -> Result<Self> {
16        Custom::parse.parse2(attr.tokens.clone()).map_err(|err| {
17            emit_error!(err.span(), err);
18            err
19        })
20    }
21
22    pub fn msg_or_default(&self) -> Type {
23        self.msg.clone().unwrap_or_else(Self::default_type)
24    }
25
26    pub fn query_or_default(&self) -> Type {
27        self.query.clone().unwrap_or_else(Self::default_type)
28    }
29
30    pub fn default_type() -> Type {
31        let sylvia = crate_module();
32        parse_quote! { #sylvia ::cw_std::Empty }
33    }
34}
35
36impl Parse for Custom {
37    fn parse(input: ParseStream) -> Result<Self> {
38        let mut custom = Self::default();
39
40        while !input.is_empty() {
41            let ty: Ident = input.parse()?;
42            let _: Token![=] = input.parse()?;
43            match ty.to_string().as_str() {
44                "msg" => custom.msg = Some(input.parse()?),
45                "query" => custom.query = Some(input.parse()?),
46                _ => {
47                    return Err(Error::new(
48                        ty.span(),
49                        "Invalid custom type.\n
50  = note: Expected `#[sv::custom(msg=SomeMsg, query=SomeQuery)]`.\n",
51                    ))
52                }
53            }
54            if !input.peek(Token![,]) {
55                break;
56            }
57            let _: Token![,] = input.parse()?;
58        }
59
60        Ok(custom)
61    }
62}