sylvia_derive/parser/attributes/
data.rs

1use proc_macro_error::emit_error;
2use syn::parse::{Parse, ParseStream, Parser};
3use syn::spanned::Spanned;
4use syn::{Error, Ident, MetaList, Result, Token};
5
6/// Type wrapping data parsed from `sv::data` attribute.
7#[derive(Default, Debug)]
8pub struct DataFieldParams {
9    pub raw: bool,
10    pub opt: bool,
11    pub instantiate: bool,
12}
13
14impl DataFieldParams {
15    pub fn new(attr: &MetaList) -> Result<Self> {
16        let data = DataFieldParams::parse
17            .parse2(attr.tokens.clone())
18            .map_err(|err| {
19                emit_error!(err.span(), err);
20                err
21            })?;
22
23        if data.instantiate && data.raw {
24            emit_error!(
25                attr.tokens.span(),
26                "The `instantiate` cannot be used in pair with `raw` parameter.";
27                note = "Use any combination of [`raw`, `opt`] or [`instantiate`, `opt`] pairs."
28            );
29        }
30
31        Ok(data)
32    }
33}
34
35impl Parse for DataFieldParams {
36    fn parse(input: ParseStream) -> Result<Self> {
37        let mut data = Self::default();
38
39        while !input.is_empty() {
40            let option: Ident = input.parse()?;
41            match option.to_string().as_str() {
42                "raw" => data.raw = true,
43                "opt" => data.opt = true,
44                "instantiate" => data.instantiate = true,
45                _ => {
46                    return Err(Error::new(
47                        option.span(),
48                        "Invalid data parameter.\n
49  = note: Expected one of [`raw`, `opt`, `instantiate`] comma separated.\n",
50                    ))
51                }
52            }
53            if !input.peek(Token![,]) {
54                break;
55            }
56            let _: Token![,] = input.parse()?;
57        }
58
59        Ok(data)
60    }
61}