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
//! Parser for RRC traces
use super::ParsingError;
use crate::data::{AdditionalInfos, Trace};
use std::str::FromStr;

use crate::interface::{functions::extract_hexe, layer::Layer, types::Direction};

use super::FileParser;

#[derive(Debug, Clone)]
/// Data structure to store the message type (from the amarisoft API)
pub struct RRCInfos {
    /// Direction of the message.
    pub direction: Direction,

    /// canal of the message.
    pub canal: String,

    /// Message of the canal.
    pub canal_msg: String,
}

/// RRC Parser
pub struct RRCParser;

impl RRCParser {
    /// Function that parses the hexadecimal part of a log
    fn parse_lines(lines: &[String]) -> Result<(Vec<u8>, Vec<String>), ParsingError> {
        let lines_len = lines.len();
        let mut ix = 0;
        let mut hex_str: Vec<&str> = vec![];
        while ix < lines_len {
            match lines[ix].trim_start().chars().next() {
                Some(c) => {
                    if c == '{' {
                        break;
                    }
                }
                None => {
                    break;
                }
            }
            hex_str.push(&lines[ix]);
            ix += 1;
        }
        if ix >= lines_len {
            return Err(ParsingError::new(
                "Could not find the end of the hexadecimal".to_string(),
                ix as u64,
            ));
        }
        let hex = match extract_hexe(&hex_str) {
            Ok(h) => h,
            Err(e) => return Err(ParsingError::new(e.message, ix as u64)),
        };

        let mut end = false;
        let mut brackets: i16 = 0;
        let start_block = ix;
        while (ix < lines_len) && !end {
            brackets += count_brackets(&lines[ix]);
            ix += 1;
            if brackets == 0 {
                end = true;
            }
        }
        if ix >= lines_len && !end {
            return Err(ParsingError::new(
                "Could not parse the JSON like part, missing closing }".to_string(),
                ix as u64,
            ));
        }
        let text = lines[start_block..ix].iter().map(|s| s.to_string()).collect();
        Ok((hex, text))
    }
}

impl FileParser for RRCParser {
    fn parse_additional_infos(lines: &[String]) -> Result<AdditionalInfos, ParsingError> {
        let line = &lines[0];
        let parts: Vec<&str> = line.split_whitespace().collect();
        if parts.len() < 5 {
            return Err(ParsingError::new("Could not find enough (5) parameters".to_string(), 1));
        }
        let direction_result = Direction::from_str(parts[2]);
        let binding: String = parts[5..].join(" ");
        let concatenated: Vec<&str> = binding.split(':').collect();
        let direction = match direction_result {
            Ok(d) => d,
            Err(_) => {
                return Err(ParsingError::new(
                    format!("The direction could not be parsed in the part {:?} of {}", parts[2], line),
                    1,
                ))
            }
        };
        if concatenated.len() < 2 || concatenated[0].is_empty() || concatenated[1].is_empty() {
            return Err(ParsingError::new(
                "The canal and/or canal message could not be parsed".to_string(),
                1,
            ));
        }
        return Ok(AdditionalInfos::RRCInfos(RRCInfos {
            direction,
            canal: concatenated[0].to_owned(),
            canal_msg: concatenated[1].trim_start().to_owned(),
        }));
    }

    fn parse(lines: &[String]) -> Result<Trace, ParsingError> {
        let mtype = match Self::parse_additional_infos(lines) {
            Ok(m) => m,
            Err(e) => {
                return Err(e);
            }
        };
        let (hexa, text) = match Self::parse_lines(&lines[1..]) {
            Ok((h, t)) => (h, t),
            Err(e) => {
                return Err(e);
            }
        };
        let trace = Trace {
            timestamp: 0,
            layer: Layer::RRC,
            additional_infos: mtype,
            hexa,
            text: Some(text),
        };
        Ok(trace)
    }
}

/// Counting Brackets
#[inline]
pub fn count_brackets(hay: &str) -> i16 {
    let mut count: i16 = 0;
    for ch in hay.chars() {
        match ch {
            '{' => count += 1,
            '}' => count -= 1,
            _ => (),
        }
    }
    count
}