despatma_lib/
options_attribute.rs

1use crate::key_value::KeyValue;
2use syn::parse::{Parse, ParseStream, Result};
3use syn::punctuated::Punctuated;
4use syn::{bracketed, token, Token};
5
6/// Holds an outer attribute filled with key-value options.
7///
8/// Streams in the following form will be parsed successfully:
9/// ```text
10/// #[key1 = value1, bool_key2, key3 = value]
11/// ```
12///
13/// The value part of an option is optional.
14/// Thus, `bool_key2` will have the value `default`.
15#[cfg_attr(any(test, feature = "extra-traits"), derive(Eq, PartialEq, Debug))]
16#[derive(Default)]
17pub struct OptionsAttribute {
18    pub pound_token: Token![#],
19    pub bracket_token: token::Bracket,
20    pub options: Punctuated<KeyValue, Token![,]>,
21}
22
23/// Make OptionsAttribute parsable from a token stream
24impl Parse for OptionsAttribute {
25    fn parse(input: ParseStream) -> Result<Self> {
26        // Used to hold the stream inside square brackets
27        let content;
28
29        Ok(OptionsAttribute {
30            pound_token: input.parse()?,
31            bracket_token: bracketed!(content in input), // Use `syn` to extract the stream inside the square bracket group
32            options: content.parse_terminated(KeyValue::parse, Token![,])?,
33        })
34    }
35}
36
37#[cfg(test)]
38mod tests {
39    use super::*;
40    use pretty_assertions::assert_eq;
41    use syn::parse_str;
42
43    type Result = std::result::Result<(), Box<dyn std::error::Error>>;
44
45    #[test]
46    fn parse() -> Result {
47        let actual: OptionsAttribute =
48            parse_str("#[tmpl = {trait To {};}, no_default, other = Top]")?;
49        let mut expected = OptionsAttribute {
50            pound_token: Default::default(),
51            bracket_token: Default::default(),
52            options: Punctuated::new(),
53        };
54
55        expected.options.push(parse_str("tmpl = {trait To {};}")?);
56        expected.options.push(parse_str("no_default")?);
57        expected.options.push(parse_str("other = Top")?);
58
59        assert_eq!(actual, expected);
60        Ok(())
61    }
62}