1 use std::str::FromStr;
2 
3 use crate::params_style::ParamStyle;
4 use crate::rpc_attr::path_eq_str;
5 
6 const CLIENT_META_WORD: &str = "client";
7 const SERVER_META_WORD: &str = "server";
8 const PARAMS_META_KEY: &str = "params";
9 
10 #[derive(Debug)]
11 pub struct DeriveOptions {
12 	pub enable_client: bool,
13 	pub enable_server: bool,
14 	pub params_style: ParamStyle,
15 }
16 
17 impl DeriveOptions {
new(enable_client: bool, enable_server: bool, params_style: ParamStyle) -> Self18 	pub fn new(enable_client: bool, enable_server: bool, params_style: ParamStyle) -> Self {
19 		DeriveOptions {
20 			enable_client,
21 			enable_server,
22 			params_style,
23 		}
24 	}
25 
try_from(args: syn::AttributeArgs) -> Result<Self, syn::Error>26 	pub fn try_from(args: syn::AttributeArgs) -> Result<Self, syn::Error> {
27 		let mut options = DeriveOptions::new(false, false, ParamStyle::default());
28 		for arg in args {
29 			if let syn::NestedMeta::Meta(meta) = arg {
30 				match meta {
31 					syn::Meta::Path(ref p) => {
32 						match p
33 							.get_ident()
34 							.ok_or(syn::Error::new_spanned(
35 								p,
36 								format!("Expecting identifier `{}` or `{}`", CLIENT_META_WORD, SERVER_META_WORD),
37 							))?
38 							.to_string()
39 							.as_ref()
40 						{
41 							CLIENT_META_WORD => options.enable_client = true,
42 							SERVER_META_WORD => options.enable_server = true,
43 							_ => {}
44 						};
45 					}
46 					syn::Meta::NameValue(nv) => {
47 						if path_eq_str(&nv.path, PARAMS_META_KEY) {
48 							if let syn::Lit::Str(ref lit) = nv.lit {
49 								options.params_style = ParamStyle::from_str(&lit.value())
50 									.map_err(|e| syn::Error::new_spanned(nv.clone(), e))?;
51 							}
52 						} else {
53 							return Err(syn::Error::new_spanned(nv, "Unexpected RPC attribute key"));
54 						}
55 					}
56 					_ => return Err(syn::Error::new_spanned(meta, "Unexpected use of RPC attribute macro")),
57 				}
58 			}
59 		}
60 		if !options.enable_client && !options.enable_server {
61 			// if nothing provided default to both
62 			options.enable_client = true;
63 			options.enable_server = true;
64 		}
65 		if options.enable_server && options.params_style == ParamStyle::Named {
66 			// This is not allowed at this time
67 			panic!("Server code generation only supports `params = \"positional\"` (default) or `params = \"raw\" at this time.")
68 		}
69 		Ok(options)
70 	}
71 }
72