static_graph/parser/
annotations.rs

1use std::ops::Deref;
2
3use nom::{
4    bytes::complete::{tag, take_while},
5    character::complete::satisfy,
6    combinator::{map, opt, recognize},
7    multi::many1,
8    sequence::tuple,
9    IResult,
10};
11
12use super::{blank, list_separator, literal::Literal, Parser};
13
14#[derive(Debug, Clone)]
15pub struct Annotation {
16    pub key: String,
17    pub value: Literal,
18}
19
20impl Deref for Annotations {
21    type Target = Vec<Annotation>;
22
23    fn deref(&self) -> &Self::Target {
24        self.0.as_ref()
25    }
26}
27
28#[derive(Debug, Clone, Default)]
29pub struct Annotations(pub Vec<Annotation>);
30
31impl<'a> Parser<'a> for Annotations {
32    fn parse(input: &'a str) -> IResult<&'a str, Annotations> {
33        map(
34            tuple((
35                tag("#["),
36                many1(map(
37                    tuple((
38                        opt(blank),
39                        recognize(tuple((
40                            satisfy(|c| c.is_ascii_alphabetic() || c == '_'),
41                            take_while(|c: char| c.is_ascii_alphanumeric() || c == '_' || c == '.'),
42                        ))),
43                        opt(blank),
44                        tag("="),
45                        opt(blank),
46                        Literal::parse,
47                        opt(blank),
48                        opt(list_separator),
49                    )),
50                    |(_, p, _, _, _, lit, _, _)| Annotation {
51                        key: p.to_owned(),
52                        value: lit,
53                    },
54                )),
55                tag("]"),
56            )),
57            |(_, annotations, _)| Annotations(annotations),
58        )(input)
59    }
60}
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65
66    #[test]
67    fn test_annotations() {
68        match Annotations::parse(r#"#[foo = "bar"]"#) {
69            Ok((remain, annotations)) => {
70                assert_eq!(remain, "");
71                assert_eq!(annotations.len(), 1);
72                assert_eq!(annotations[0].key, "foo");
73                assert_eq!(annotations[0].value.0, "bar");
74            }
75            Err(e) => panic!("{e:?}"),
76        }
77    }
78}