tramex_tools/interface/interface_file/
utils_file.rs

1//! utils functions for file interface
2
3use std::str::FromStr;
4
5use crate::errors::ErrorCode;
6use crate::interface::parser::{FileParser, parsing_error_to_tramex_error};
7use crate::tramex_error;
8// to use the FileParser trait and implementations
9use crate::{
10    data::Trace,
11    errors::TramexError,
12    interface::{
13        layer::Layer,
14        parser::{eof_error, parser_rrc::RRCParser, time_to_milliseconds},
15    },
16};
17
18/// Function that parses one log
19/// # Errors
20/// Return an error if the parsing fails
21pub fn parse_one_block(lines: &[String], ix: &mut usize) -> Result<Trace, TramexError> {
22    // no more lines to read
23    if lines.is_empty() {
24        return Err(eof_error(*ix as u64));
25    }
26    let mut start_line = 0;
27    let mut end_line = 0;
28    let mut should_stop = false;
29    for one_line in lines.iter() {
30        end_line += 1;
31        if one_line.starts_with('#') {
32            start_line += 1;
33            continue;
34        } else if one_line.starts_with(' ') || one_line.starts_with('\t') || one_line.trim().is_empty() {
35            continue;
36        } else {
37            if should_stop {
38                end_line -= 1;
39                break;
40            }
41            should_stop = true;
42        }
43    }
44    if end_line == 1 && (lines[0].starts_with(' ') || lines[0].starts_with('\t') || lines[0].trim().is_empty()) {
45        return Err(eof_error(*ix as u64));
46    }
47    let lines_to_parse = &lines[start_line..end_line];
48    let copy_ix = *ix + start_line;
49    *ix += end_line;
50    match lines_to_parse.first() {
51        Some(first_line) => {
52            let parts: Vec<&str> = first_line.split_whitespace().collect();
53            if parts.is_empty() {
54                return Err(tramex_error!(
55                    format!("Not enough parts in the line {:?} (line {})", first_line, copy_ix as u64 + 1),
56                    ErrorCode::FileParsing
57                ));
58            }
59            let date = match chrono::NaiveTime::parse_from_str(parts[0], "%H:%M:%S%.3f") {
60                Ok(rdate) => rdate,
61                Err(_) => {
62                    return Err(tramex_error!(
63                        format!(
64                            "Error while parsing date {:?} in {:?} (line {})",
65                            parts[0],
66                            first_line,
67                            copy_ix + 1
68                        ),
69                        ErrorCode::FileParsing
70                    ));
71                }
72            };
73            let res_layer = Layer::from_str(parts[1].trim_start_matches('[').trim_end_matches(']'));
74            let res_parse = match res_layer {
75                Ok(Layer::RRC) => RRCParser::parse(lines_to_parse),
76                _ => {
77                    return Err(tramex_error!(
78                        format!(
79                            "Unknown message type {:?} in {:?} (line {})",
80                            parts[1],
81                            first_line,
82                            copy_ix + 1
83                        ),
84                        ErrorCode::ParsingLayerNotImplemented
85                    ));
86                }
87            };
88            match res_parse {
89                Ok(mut trace) => {
90                    trace.timestamp = time_to_milliseconds(&date) as u64;
91                    Ok(trace)
92                }
93                Err(err) => Err(parsing_error_to_tramex_error(err, copy_ix as u64)),
94            }
95        }
96        None => Err(eof_error(copy_ix as u64)),
97    }
98}