extendr_macros/extendr_options.rs
1use syn::{meta::ParseNestedMeta, Lit, LitBool};
2
3#[derive(Debug, Default)]
4pub(crate) struct ExtendrOptions {
5 /// Name of the corresponding R object
6 pub r_name: Option<String>,
7 /// `mod_name` is the name of the exported C symbol for `#[extendr]`-`fn`,
8 /// and a post-fix on exported methods for `#[extendr]`-`impl`.
9 pub mod_name: Option<String>,
10 /// Flag ensuring that R's Random Number Generator state is acquired and returned to
11 /// R. See [WRE, Section 6.3 number generation](https://cran.r-project.org/doc/manuals/R-exts.html#Random-numbers)
12 pub use_rng: bool,
13 pub invisible: Option<bool>,
14}
15
16impl ExtendrOptions {
17 /// Parse a set of attribute arguments for `#[extendr(opts...)]`
18 ///
19 /// Supported options:
20 ///
21 /// - `r_name = "name"` which specifies the name of the wrapper on the R-side.
22 /// - `use_rng = bool` ensures the RNG-state is pulled and pushed
23 ///
24 pub fn parse(&mut self, meta: ParseNestedMeta) -> syn::parse::Result<()> {
25 let path = meta
26 .path
27 .get_ident()
28 .ok_or(meta.error("Unexpected syntax"))?;
29
30 match path.to_string().as_str() {
31 "invisible" => {
32 self.invisible = Some(true);
33 Ok(())
34 }
35 _ => {
36 let value = meta.value()?;
37 match path.to_string().as_str() {
38 "r_name" => {
39 if let Ok(Lit::Str(litstr)) = value.parse() {
40 self.r_name = Some(litstr.value());
41 Ok(())
42 } else {
43 Err(value.error("`r_name` must be a string literal"))
44 }
45 }
46 "mod_name" => {
47 if let Ok(Lit::Str(litstr)) = value.parse() {
48 self.mod_name = Some(litstr.value());
49 Ok(())
50 } else {
51 Err(value.error("`mod_name` must be a string literal"))
52 }
53 }
54 "use_rng" => {
55 if let Ok(LitBool { value, .. }) = value.parse() {
56 self.use_rng = value;
57 Ok(())
58 } else {
59 Err(value.error("`use_rng` must be `true` or `false`"))
60 }
61 }
62 _ => Err(syn::Error::new_spanned(meta.path, "Unexpected key")),
63 }
64 }
65 }
66 }
67}