1use std::str::Chars;
2
3#[derive(Debug, PartialEq, Clone)]
4pub enum Data {
5    Single(String),
6    Vector(Vec<(usize, Data)>),
7}
8
9impl Data {
10    pub fn to_str(&self) -> String {
11        match self {
12            Data::Single(s) => String::from(&s[..]),
13            _ => String::new(),
14        }
15    }
16
17    pub fn to_vec(&self) -> Vec<(usize, Data)> {
18        match self {
19            Data::Vector(v) => (*v).to_vec(),
20            _ => Vec::new(),
21        }
22    }
23}
24
25pub(crate) fn parse(code: &str, max: usize) -> Vec<(usize, Data)> {
26    let mut chars = code.chars();
27    (0usize..=max)
28        .filter_map(|_| parse_code(&mut chars))
29        .map(|code| match code.0 {
30            26..=51 | 80..=98 => (code.0, Data::Vector(inner_parse(&code.1, 99))),
31            62 => (code.0, Data::Vector(inner_parse(&code.1, 25))),
32            _ => (code.0, Data::Single(code.1)),
33        })
34        .collect()
35}
36
37pub(crate) fn inner_parse(code: &str, max: usize) -> Vec<(usize, Data)> {
38    let mut chars = code.chars();
39    (0usize..=max)
40        .filter_map(|_| parse_code(&mut chars))
41        .map(|code| (code.0, Data::Single(code.1)))
42        .collect()
43}
44
45fn parse_code(chars: &mut Chars) -> Option<(usize, String)> {
46    match (
47        chars.take(2).collect::<String>().parse(),
48        chars.take(2).collect::<String>().parse(),
49    ) {
50        (Ok(id), Ok(len)) => {
51            let value: String = chars.take(len).collect();
52            Some((id, value))
53        }
54        _ => None,
55    }
56}
57
58#[cfg(test)]
59mod test {
60    use super::{parse, Data};
61
62    #[test]
63    fn helloworld_in_tag_00() {
64        let code = "0011hello-world";
65        let expected = vec![(0usize, Data::Single(String::from("hello-world")))];
66
67        assert_eq!(parse(code, 99), expected);
68    }
69
70    #[test]
71    fn code_with_inner_values() {
72        let code = "00020104141234567890123426580014BR.GOV.BCB.PIX0136123e4567-e12b-12d1-a456-426655440000";
73        let expected = vec![
74            (0usize, Data::Single("01".to_string())),
75            (4usize, Data::Single("12345678901234".to_string())),
76            (
77                26,
78                Data::Vector(vec![
79                    (0usize, Data::Single("BR.GOV.BCB.PIX".to_string())),
80                    (
81                        1usize,
82                        Data::Single("123e4567-e12b-12d1-a456-426655440000".to_string()),
83                    ),
84                ]),
85            ),
86        ];
87
88        assert_eq!(parse(code, 99), expected);
89    }
90}