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