tramex_tools/interface/parser/
mod.rs

1//! Parser for file interface
2
3pub mod hex_extractor;
4pub mod parser_basic;
5pub mod parser_gtpu;
6pub mod parser_nas;
7pub mod parser_ngap;
8pub mod parser_phy;
9pub mod parser_rrc;
10
11use crate::data::AdditionalInfos;
12use crate::data::Trace;
13
14use crate::errors::ErrorCode;
15use crate::errors::TramexError;
16use crate::tramex_error;
17use chrono::NaiveTime;
18use chrono::Timelike;
19
20/// Parsing error
21#[derive(Debug)]
22pub struct ParsingError {
23    /// Error message
24    pub message: String,
25
26    /// Line index
27    pub line_idx: u64,
28}
29
30impl ParsingError {
31    /// Create a new parsing error
32    pub fn new(message: String, line_idx: u64) -> Self {
33        Self { message, line_idx }
34    }
35}
36
37/// Convert a parsing error to a tramex error
38#[inline]
39pub fn parsing_error_to_tramex_error(error: ParsingError, idx: u64) -> TramexError {
40    let index = idx + error.line_idx;
41    tramex_error!(format!("{} (line {})", error.message, index), ErrorCode::FileParsing)
42}
43
44/// Trait for file parser
45pub trait FileParser {
46    /// Function that parses the first line of a log
47    /// # Errors
48    /// Return an error if the parsing fails
49    fn parse_additional_infos(line: &[String]) -> Result<AdditionalInfos, ParsingError>;
50
51    /// Parse the lines of a file
52    /// # Errors
53    /// Return an error if the parsing fails
54    fn parse(lines: &[String]) -> Result<Trace, ParsingError>;
55}
56
57/// Convert a time to milliseconds.
58#[inline]
59pub fn time_to_milliseconds(time: &NaiveTime) -> i64 {
60    let hours_in_ms = time.hour() as i64 * 3_600_000;
61    let minutes_in_ms = time.minute() as i64 * 60_000;
62    let seconds_in_ms = time.second() as i64 * 1000;
63    let milliseconds = time.nanosecond() as i64 / 1_000_000; // convert nanoseconds to milliseconds
64
65    hours_in_ms + minutes_in_ms + seconds_in_ms + milliseconds
66}
67
68/// Parse timestamp from the first line of a trace
69/// Expected format: "HH:MM:SS.mmm [LAYER] ..."
70/// # Errors
71/// Returns ParsingError if timestamp cannot be parsed
72pub fn parse_timestamp(first_line: &str) -> Result<i64, ParsingError> {
73    let parts: Vec<&str> = first_line.split_whitespace().collect();
74    if parts.is_empty() {
75        return Err(ParsingError::new("Empty line, cannot parse timestamp".to_string(), 0));
76    }
77
78    let date = chrono::NaiveTime::parse_from_str(parts[0], "%H:%M:%S%.3f")
79        .map_err(|_| ParsingError::new(format!("Error parsing timestamp '{}' in line: {}", parts[0], first_line), 0))?;
80
81    Ok(time_to_milliseconds(&date))
82}
83
84/// Build a eof_error
85#[inline]
86pub fn eof_error(line_idx: u64) -> TramexError {
87    tramex_error!(
88        format!("End of file (line {})", line_idx),
89        crate::errors::ErrorCode::EndOfFile
90    )
91}