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
use syn::{meta::ParseNestedMeta, Lit, LitBool};
#[derive(Debug, Default)]
pub(crate) struct ExtendrOptions {
/// Name of the corresponding R object
pub r_name: Option<String>,
/// `mod_name` is the name of the exported C symbol for `#[extendr]`-`fn`,
/// and a post-fix on exported methods for `#[extendr]`-`impl`.
pub mod_name: Option<String>,
/// Flag ensuring that R's Random Number Generator state is acquired and returned to
/// R. See [WRE, Section 6.3 number generation](https://cran.r-project.org/doc/manuals/R-exts.html#Random-numbers)
pub use_rng: bool,
pub invisible: Option<bool>,
}
impl ExtendrOptions {
/// Parse a set of attribute arguments for `#[extendr(opts...)]`
///
/// Supported options:
///
/// - `r_name = "name"` which specifies the name of the wrapper on the R-side.
/// - `use_rng = bool` ensures the RNG-state is pulled and pushed
///
pub fn parse(&mut self, meta: ParseNestedMeta) -> syn::parse::Result<()> {
let path = meta
.path
.get_ident()
.ok_or(meta.error("Unexpected syntax"))?;
match path.to_string().as_str() {
"invisible" => {
self.invisible = Some(true);
Ok(())
}
_ => {
let value = meta.value()?;
match path.to_string().as_str() {
"r_name" => {
if let Ok(Lit::Str(litstr)) = value.parse() {
self.r_name = Some(litstr.value());
Ok(())
} else {
Err(value.error("`r_name` must be a string literal"))
}
}
"mod_name" => {
if let Ok(Lit::Str(litstr)) = value.parse() {
self.mod_name = Some(litstr.value());
Ok(())
} else {
Err(value.error("`mod_name` must be a string literal"))
}
}
"use_rng" => {
if let Ok(LitBool { value, .. }) = value.parse() {
self.use_rng = value;
Ok(())
} else {
Err(value.error("`use_rng` must be `true` or `false`"))
}
}
_ => Err(syn::Error::new_spanned(meta.path, "Unexpected key")),
}
}
}
}
}