sdp_rs/tokenizers/
key_optvalue.rs

1use crate::TResult;
2
3#[derive(Debug, PartialEq, Eq, Clone)]
4pub struct Tokenizer<'a, const C: char> {
5    pub key: &'a str,
6    pub value: Option<&'a str>,
7}
8
9impl<'a, const C: char> Tokenizer<'a, C> {
10    pub fn tokenize(part: &'a str) -> TResult<'a, Self> {
11        use crate::parser_utils::*;
12        use nom::{branch::alt, bytes::complete::tag, combinator::rest, sequence::preceded};
13
14        let (rem, key_with_value) = preceded(tag(Self::prefix().as_str()), until_newline)(part)?;
15        let (value, key) = alt((until_stopbreak_of(":"), rest))(key_with_value)?;
16        let value = match value.is_empty() {
17            true => None,
18            false => Some(value),
19        };
20
21        Ok((rem, (key, value).into()))
22    }
23
24    //TODO: this should be generated by a concat-related macro, but atm at stable this is not
25    //possible, will come back once const generics expands on stable
26    fn prefix() -> String {
27        format!("{}=", C)
28    }
29}
30
31impl<'a, const C: char> From<(&'a str, Option<&'a str>)> for Tokenizer<'a, C> {
32    fn from((key, value): (&'a str, Option<&'a str>)) -> Self {
33        Self { key, value }
34    }
35}
36
37impl<'a, const C: char> From<(&'a str, &'a str)> for Tokenizer<'a, C> {
38    fn from((key, value): (&'a str, &'a str)) -> Self {
39        Self {
40            key,
41            value: Some(value),
42        }
43    }
44}
45
46impl<'a, const C: char> From<&'a str> for Tokenizer<'a, C> {
47    fn from(key: &'a str) -> Self {
48        Self { key, value: None }
49    }
50}
51
52#[cfg(test)]
53mod tests {
54    use super::*;
55
56    #[test]
57    fn tokenizer1() {
58        let key_optvalue = concat!("a=recvonly\r\nsomething");
59
60        assert_eq!(
61            Tokenizer::<'a'>::tokenize(key_optvalue),
62            Ok((
63                "something",
64                Tokenizer {
65                    key: "recvonly",
66                    value: None,
67                }
68            )),
69        );
70    }
71
72    #[test]
73    fn tokenizer2() {
74        let key_optvalue = concat!("a=rtpmap:99 h263-1998/90000\r\nsomething");
75
76        assert_eq!(
77            Tokenizer::<'a'>::tokenize(key_optvalue),
78            Ok((
79                "something",
80                Tokenizer {
81                    key: "rtpmap",
82                    value: Some("99 h263-1998/90000"),
83                }
84            )),
85        );
86    }
87}