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