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
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
use crate::{Error, NomRes, ParsePart};
use nom::{
    branch::alt,
    bytes::complete::{tag, take_until},
    combinator::map,
    combinator::rest,
    error::VerboseError,
    multi::{many0, many1},
    sequence::delimited,
};

impl<'a> ParsePart<'a> for Vec<StructuredData<'a>> {
    fn parse(sd: &'a str) -> Result<(&'a str, Self), Error> {
        let (rem, sdata) = alt((map(tag("-"), |_| vec![]), many1(parse_structured_data)))(sd)?;

        Ok((rem, sdata))
    }
}

#[derive(Debug, Eq, PartialEq, Clone)]
pub struct StructuredData<'a> {
    pub id: &'a str,
    pub params: Vec<SdParam<'a>>,
}

#[derive(Debug, Eq, PartialEq, Clone)]
pub struct SdParam<'a> {
    pub name: &'a str,
    pub value: &'a str,
}

impl<'a> From<(&'a str, Vec<SdParam<'a>>)> for StructuredData<'a> {
    fn from(tuple: (&'a str, Vec<SdParam<'a>>)) -> Self {
        Self {
            id: tuple.0,
            params: tuple.1,
        }
    }
}

impl<'a> From<(&'a str, &'a str)> for SdParam<'a> {
    fn from(tuple: (&'a str, &'a str)) -> Self {
        Self {
            name: tuple.0,
            value: tuple.1,
        }
    }
}

fn parse_structured_data<'a>(part: &'a str) -> NomRes<&'a str, StructuredData> {
    let (rem, data) = delimited::<_, _, _, _, VerboseError<&'a str>, _, _, _>(
        tag("["),
        take_until("]"),
        tag("]"),
    )(part)?;

    let (_, data): (&'a str, StructuredData) = parse_structured_data_inner(data)?;

    Ok((rem, data))
}

fn parse_structured_data_inner(part: &str) -> NomRes<&str, StructuredData> {
    use nom::character::complete::space0;

    let (rem, _) = space0(part)?;
    let (rem, id) = alt((take_until(" "), rest))(rem)?;

    let (rem, sd_params) = many0(parse_structured_elements)(rem)?;

    Ok((rem, (id, sd_params).into()))
}

fn parse_structured_elements<'a>(part: &'a str) -> NomRes<&'a str, SdParam> {
    use nom::character::complete::space0;

    let (rem, _) = space0(part)?;
    let (rem, key_value) = alt((take_until(" "), rest))(rem)?;
    let (key_value_rem, key) = take_until("=")(key_value)?;
    let (value, _) = tag("=")(key_value_rem)?;

    let value: &str = &value[1..value.len() - 1];

    Ok((rem, (key, value).into()))
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn simple_structured_data() {
        assert_eq!(
            <Vec<StructuredData> as ParsePart>::parse("[a]")
                .expect("parsing data")
                .1,
            vec![StructuredData {
                id: "a",
                params: vec![]
            }]
        );

        assert_eq!(
            <Vec<StructuredData> as ParsePart>::parse(
                "[exampleSDID@32473 iut=\"3\" eventSource=\"Application\" eventID=\"1011\"]"
            )
            .expect("parsing data")
            .1,
            vec![StructuredData {
                id: "exampleSDID@32473",
                params: vec![
                    SdParam {
                        name: "iut",
                        value: "3"
                    },
                    SdParam {
                        name: "eventSource",
                        value: "Application"
                    },
                    SdParam {
                        name: "eventID",
                        value: "1011"
                    },
                ]
            }]
        );
    }

    #[test]
    fn simple_structured_data_inner() {
        assert_eq!(
            parse_structured_data_inner("a"),
            Ok((
                "",
                StructuredData {
                    id: "a",
                    params: vec![]
                }
            ))
        );

        assert_eq!(
            parse_structured_data_inner(r#"a key="value" anotherkey="anothervalue""#),
            Ok((
                "",
                StructuredData {
                    id: "a",
                    params: vec![
                        SdParam {
                            name: "key",
                            value: "value"
                        },
                        SdParam {
                            name: "anotherkey",
                            value: "anothervalue"
                        }
                    ]
                }
            ))
        );

        assert_eq!(
            parse_structured_data_inner(
                "exampleSDID@32473 iut=\"3\" eventSource=\"Application\" eventID=\"1011\""
            ),
            Ok((
                "",
                StructuredData {
                    id: "exampleSDID@32473",
                    params: vec![
                        SdParam {
                            name: "iut",
                            value: "3"
                        },
                        SdParam {
                            name: "eventSource",
                            value: "Application"
                        },
                        SdParam {
                            name: "eventID",
                            value: "1011"
                        }
                    ]
                }
            ))
        );
    }
}