extendr_macros/
extendr_options.rs

1use syn::{meta::ParseNestedMeta, Lit, LitBool};
2
3#[derive(Debug, Default)]
4pub(crate) struct ExtendrOptions {
5    pub r_name: Option<String>,
6    pub mod_name: Option<String>,
7    pub use_rng: bool,
8    pub invisible: Option<bool>,
9}
10
11impl ExtendrOptions {
12    /// Parse a set of attribute arguments for `#[extendr(opts...)]`
13    ///
14    /// Supported options:
15    ///
16    /// - `r_name = "name"` which specifies the name of the wrapper on the R-side.
17    /// - `use_rng = bool` ensures the RNG-state is pulled and pushed
18    ///
19    pub fn parse(&mut self, meta: ParseNestedMeta) -> syn::parse::Result<()> {
20        let path = meta
21            .path
22            .get_ident()
23            .ok_or(meta.error("Unexpected syntax"))?;
24
25        match path.to_string().as_str() {
26            "invisible" => {
27                self.invisible = Some(true);
28                Ok(())
29            }
30            _ => {
31                let value = meta.value()?;
32                match path.to_string().as_str() {
33                    "r_name" => {
34                        if let Ok(Lit::Str(litstr)) = value.parse() {
35                            self.r_name = Some(litstr.value());
36                            Ok(())
37                        } else {
38                            Err(value.error("`r_name` must be a string literal"))
39                        }
40                    }
41                    "mod_name" => {
42                        if let Ok(Lit::Str(litstr)) = value.parse() {
43                            self.mod_name = Some(litstr.value());
44                            Ok(())
45                        } else {
46                            Err(value.error("`mod_name` must be a string literal"))
47                        }
48                    }
49                    "use_rng" => {
50                        if let Ok(LitBool { value, .. }) = value.parse() {
51                            self.use_rng = value;
52                            Ok(())
53                        } else {
54                            Err(value.error("`use_rng` must be `true` or `false`"))
55                        }
56                    }
57                    _ => Err(syn::Error::new_spanned(meta.path, "Unexpected key")),
58                }
59            }
60        }
61    }
62}