tramex_tools/interface/parser/
parser_rrc.rs

1//! Parser for RRC traces
2use super::ParsingError;
3use crate::data::{AdditionalInfos, Trace};
4use std::str::FromStr;
5
6use crate::interface::{functions::extract_hexe, layer::Layer, types::Direction};
7
8use super::FileParser;
9
10#[derive(Debug, Clone)]
11/// Data structure to store the message type (from the amarisoft API)
12pub struct RRCInfos {
13    /// Direction of the message.
14    pub direction: Direction,
15
16    /// canal of the message.
17    pub canal: String,
18
19    /// Message of the canal.
20    pub canal_msg: String,
21}
22
23/// RRC Parser
24pub struct RRCParser;
25
26impl RRCParser {
27    /// Function that parses the hexadecimal part of a log
28    /// # Errors
29    /// Returns a ParsingError if the hexadecimal part could not be parsed
30    fn parse_lines(lines: &[String]) -> Result<(Vec<u8>, Vec<String>), ParsingError> {
31        let lines_len = lines.len();
32        let mut ix = 0;
33        let mut hex_str: Vec<&str> = vec![];
34        while ix < lines_len {
35            match lines[ix].trim_start().chars().next() {
36                Some(c) => {
37                    if c == '{' {
38                        break;
39                    }
40                }
41                None => {
42                    break;
43                }
44            }
45            hex_str.push(&lines[ix]);
46            ix += 1;
47        }
48        if ix >= lines_len {
49            return Err(ParsingError::new(
50                "Could not find the end of the hexadecimal".to_string(),
51                ix as u64,
52            ));
53        }
54        let hex = match extract_hexe(&hex_str) {
55            Ok(h) => h,
56            Err(e) => return Err(ParsingError::new(e.message, ix as u64)),
57        };
58
59        let mut end = false;
60        let mut brackets: i16 = 0;
61        let start_block = ix;
62        while (ix < lines_len) && !end {
63            brackets += count_brackets(&lines[ix]);
64            ix += 1;
65            if brackets == 0 {
66                end = true;
67            }
68        }
69        if ix >= lines_len && !end {
70            return Err(ParsingError::new(
71                "Could not parse the JSON like part, missing closing }".to_string(),
72                ix as u64,
73            ));
74        }
75        let text = lines[start_block..ix].iter().map(|s| s.to_string()).collect();
76        Ok((hex, text))
77    }
78}
79
80impl FileParser for RRCParser {
81    fn parse_additional_infos(lines: &[String]) -> Result<AdditionalInfos, ParsingError> {
82        let line = &lines[0];
83        let parts: Vec<&str> = line.split_whitespace().collect();
84        if parts.len() < 5 {
85            return Err(ParsingError::new("Could not find enough (5) parameters".to_string(), 1));
86        }
87        let direction_result = Direction::from_str(parts[2]);
88        let binding: String = parts[5..].join(" ");
89        let concatenated: Vec<&str> = binding.split(':').collect();
90        let direction = match direction_result {
91            Ok(d) => d,
92            Err(_) => {
93                return Err(ParsingError::new(
94                    format!("The direction could not be parsed in the part {:?} of {}", parts[2], line),
95                    1,
96                ));
97            }
98        };
99        if concatenated.len() < 2 || concatenated[0].is_empty() || concatenated[1].is_empty() {
100            return Err(ParsingError::new(
101                "The canal and/or canal message could not be parsed".to_string(),
102                1,
103            ));
104        }
105        Ok(AdditionalInfos::RRCInfos(RRCInfos {
106            direction,
107            canal: concatenated[0].to_owned(),
108            canal_msg: concatenated[1].trim_start().to_owned(),
109        }))
110    }
111
112    fn parse(lines: &[String]) -> Result<Trace, ParsingError> {
113        let mtype = match Self::parse_additional_infos(lines) {
114            Ok(m) => m,
115            Err(e) => {
116                return Err(e);
117            }
118        };
119        let (hexa, text) = match Self::parse_lines(&lines[1..]) {
120            Ok((h, t)) => (h, t),
121            Err(e) => {
122                return Err(e);
123            }
124        };
125        let trace = Trace {
126            timestamp: 0,
127            layer: Layer::RRC,
128            additional_infos: mtype,
129            hexa,
130            text: Some(text),
131        };
132        Ok(trace)
133    }
134}
135
136/// Counting Brackets
137#[inline]
138pub fn count_brackets(hay: &str) -> i16 {
139    let mut count: i16 = 0;
140    for ch in hay.chars() {
141        match ch {
142            '{' => count += 1,
143            '}' => count -= 1,
144            _ => (),
145        }
146    }
147    count
148}