1use syn::parse::discouraged::Speculative;
2use syn::parse::*;
3use syn::parse_macro_input;
4
5enum Value {
6 Null,
7 Object(Vec<KeyValuePair>),
8 Array(Vec<Value>),
9 Expr(syn::Expr),
10}
11
12struct Object(Vec<KeyValuePair>);
13
14impl Parse for Object {
15 fn parse(input: ParseStream) -> Result<Self> {
16 let content;
17 syn::braced!(content in input);
18 let tokens = content.parse_terminated(KeyValuePair::parse, syn::Token![,])?;
19 let pairs = tokens.into_iter().collect();
20 Ok(Object(pairs))
21 }
22}
23
24struct Array(Vec<Value>);
25
26impl Parse for Array {
27 fn parse(input: ParseStream) -> Result<Self> {
28 let content;
29 syn::bracketed!(content in input);
30 let tokens = content.parse_terminated(Value::parse, syn::Token![,])?;
31 let values = tokens.into_iter().collect();
32 Ok(Array(values))
33 }
34}
35
36struct Null;
37
38impl Parse for Null {
39 fn parse(input: ParseStream) -> Result<Self> {
40 let fork = input.fork();
41 if let Ok(kw) = fork.parse::<syn::Ident>() {
42 if kw == "null" {
43 input.advance_to(&fork);
44 return Ok(Null);
45 }
46 }
47 Err(syn::Error::new(input.span(), "expected `null`"))
48 }
49}
50
51impl Parse for Value {
52 fn parse(input: ParseStream) -> syn::Result<Self> {
53 if let Ok(_) = input.parse::<Null>() {
54 Ok(Value::Null)
55 } else if let Ok(Array(array)) = input.parse::<Array>() {
56 Ok(Value::Array(array))
57 } else if let Ok(Object(object)) = input.parse::<Object>() {
58 Ok(Value::Object(object))
59 } else if let Ok(expr) = input.parse::<syn::Expr>() {
60 Ok(Value::Expr(expr))
61 } else {
62 Err(syn::Error::new(input.span(), "Unexpected token."))
63 }
64 }
65}
66
67struct KeyValuePair {
68 key: syn::Expr,
69 value: Value,
70}
71
72impl Parse for KeyValuePair {
73 fn parse(input: ParseStream) -> Result<Self> {
74 let key = input.parse::<syn::Expr>()?;
75 input.parse::<syn::Token![:]>()?;
76 let value = input.parse::<Value>()?;
77 Ok(KeyValuePair { key, value })
78 }
79}
80
81impl Value {
82 fn to_tokenstream(self) -> proc_macro2::TokenStream {
83 use quote::quote;
84 match self {
85 Value::Null => quote!(bourne::Value::Null),
86 Value::Object(object) => {
87 let capacity = object.len();
88 let inserts = object.into_iter().map(|KeyValuePair { key, value }| {
89 let value = value.to_tokenstream();
90 quote! { map.insert((#key).to_owned(), #value); }
91 }).collect::<Vec<_>>();
92 quote! {
93 {
94 let mut map = bourne::ValueMap::with_capacity(#capacity);
95 #(#inserts)*
96 bourne::Value::Object(map)
97 }
98 }
99 },
100 Value::Array(array) => {
101 let capacity = array.len();
102 let lines = array.into_iter().map(|value| {
103 let value = value.to_tokenstream();
104 quote!{ array.push(#value); }
105 }).collect::<Vec<_>>();
106 quote! {
107 {
108 let mut array = Vec::<bourne::Value>::with_capacity(#capacity);
109 #(#lines)*
110 bourne::Value::Array(array)
111 }
112 }
113 },
114 Value::Expr(expr) => {
115 quote!{ bourne::Value::from(#expr) }
116 },
117 }
118 }
119}
120
121#[proc_macro]
132pub fn json(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
133 if input.is_empty() {
134 quote::quote!{ bourne::Value::Null }.into()
135 } else {
136 let value = parse_macro_input!(input as Value);
137 value.to_tokenstream().into()
138 }
139}