syn_args/
syn_args.rs

1use proc_macro2::Group;
2use syn::{
3    parse::{Parse, ParseStream},
4    token::{Brace, Bracket, Paren},
5    Expr, Ident, Lit, Token,
6};
7
8use crate::utils::{recursive_lit, recursive_parsing};
9use crate::{def, Value};
10
11/// A very important core type used to convert types related to syn::parse into Value, and then you can call the `.arguments` method to get the specific type (this type must be derived using the `ArgsParse` macro)
12/// Example:
13/// ```rust
14/// use syn_args::def;
15/// use syn_args::derive::ArgsParse;
16/// use syn_args::SynArgs;
17///
18/// #[derive(Debug, ArgsParse)]
19/// enum FArgs {
20///    F1(def::Int),
21///    F2(def::String),
22/// }
23///
24/// fn main() {
25///    let args = syn::parse_str::<SynArgs>("F(1)").unwrap();
26///    let args = args.arguments::<FArgs>().unwrap();
27///    println!("{:?}", args);
28/// }
29#[derive(Debug)]
30pub struct SynArgs {
31    pub value: Value,
32}
33
34impl SynArgs {
35    pub fn arguments<T: TryFrom<Value, Error = syn::Error>>(self) -> Result<T, syn::Error> {
36        T::try_from(self.value)
37    }
38}
39
40impl Parse for SynArgs {
41    fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
42        let mut res: Vec<Value> = vec![];
43
44        if input.peek(Ident) && input.peek2(Paren) {
45            input.parse::<Ident>()?;
46        }
47
48        if input.peek(Paren) {
49            let group = input.parse::<Group>()?;
50            let stream = group.stream();
51            return syn::parse2(stream);
52        }
53
54        let content = input;
55
56        while !content.is_empty() {
57            if content.peek(Lit) {
58                let lit = content.parse::<Lit>()?;
59                res.push(recursive_lit(&lit));
60            } else if content.peek(Brace) {
61                let group: ObjectArgs = content.parse()?;
62                res.push(Value::Object(def::Object(group.value)));
63            } else if content.peek(Bracket) {
64                let group: ArrayArgs = content.parse()?;
65                res.push(Value::Array(def::Array(group.value)));
66            } else if let Ok(v) = content.parse::<syn::Expr>() {
67                res.push(recursive_parsing(&v));
68            } else {
69                println!("Failed to parse: {:?}", content);
70            }
71
72            if content.is_empty() {
73                break;
74            }
75            let _ = content.parse::<Token![,]>()?;
76        }
77
78        Ok(SynArgs { value: Value::Array(def::Array(res)) })
79    }
80}
81
82pub(crate) struct ObjectArgs {
83    pub value: std::collections::HashMap<String, Value>,
84}
85
86impl Parse for ObjectArgs {
87    fn parse(input: ParseStream) -> syn::Result<Self> {
88        let content;
89        let _ = syn::braced!(content in input);
90
91        let mut value = std::collections::HashMap::new();
92
93        while !content.is_empty() {
94            let key: Ident = content.parse()?;
95            let _: Token![:] = content.parse()?;
96            if content.peek(Brace) {
97                let group: ObjectArgs = content.parse()?;
98                value.insert(key.to_string(), Value::Object(def::Object(group.value)));
99            } else {
100                let expr = content.parse::<Expr>()?;
101                value.insert(key.to_string(), recursive_parsing(&expr));
102            }
103            if content.is_empty() {
104                break;
105            }
106            let _: Token![,] = content.parse()?;
107        }
108
109        Ok(ObjectArgs { value })
110    }
111}
112
113pub(crate) struct ArrayArgs {
114    pub value: Vec<Value>,
115}
116
117impl Parse for ArrayArgs {
118    fn parse(input: ParseStream) -> syn::Result<Self> {
119        let content;
120        let _ = syn::bracketed!(content in input);
121
122        let mut value = vec![];
123
124        while !content.is_empty() {
125            let p = content.parse::<SynArgs>()?;
126
127            if let Value::Array(def::Array(v)) = p.value {
128                value.extend(v);
129            }
130
131            if content.is_empty() {
132                break;
133            }
134            let _: Token![,] = content.parse()?;
135        }
136
137        Ok(ArrayArgs { value })
138    }
139}
140
141#[cfg(test)]
142mod tests {
143    use super::*;
144
145    #[test]
146    fn test_syn_args() {
147        let args = syn::parse_str::<SynArgs>("(1, 20, { a: 12 })").unwrap();
148        assert_eq!(format!("{:?}", args.value), "Array(Array([Int(Int(1)), Int(Int(20)), Object(Object({\"a\": Int(Int(12))}))]))");
149    }
150
151    #[test]
152    fn test_syn_args2() {
153        let args = syn::parse_str::<SynArgs>("(Test, MY::TEST)").unwrap();
154        assert_eq!(format!("{:?}", args.value), "Array(Array([Expr(Expr(\"Test\")), Expr(Expr(\"MY :: TEST\"))]))");
155    }
156
157    #[test]
158    fn test_syn_args3() {
159        let args = syn::parse_str::<SynArgs>("([Test, MY::TEST])").unwrap();
160        assert_eq!(format!("{:?}", args.value), "Array(Array([Array(Array([Expr(Expr(\"Test\")), Expr(Expr(\"MY :: TEST\"))]))]))");
161    }
162
163    #[test]
164    fn test_syn_args3_no_parenthesized() {
165        let args = syn::parse_str::<SynArgs>("[Test, MY::TEST]").unwrap();
166        assert_eq!(format!("{:?}", args.value), "Array(Array([Array(Array([Expr(Expr(\"Test\")), Expr(Expr(\"MY :: TEST\"))]))]))");
167    }
168}