tramex_tools/interface/parser/
parser_nas.rs1use super::ParsingError;
3use super::hex_extractor::extract_binary_from_lines;
4use crate::data::{AdditionalInfos, Trace};
5use crate::interface::association::TraceRelation;
6use std::str::FromStr;
7
8use crate::interface::{layer::Layer, types::Direction};
9
10use super::FileParser;
11
12#[derive(Debug, Clone)]
13pub struct NASInfos {
15 pub direction: Direction,
17
18 pub message_type: String,
20}
21
22pub struct NASParser;
24
25impl NASParser {
26 fn parse_lines(lines: &[String]) -> Vec<String> {
28 lines.to_vec()
29 }
30}
31
32impl FileParser for NASParser {
33 fn parse_additional_infos(lines: &[String]) -> Result<AdditionalInfos, ParsingError> {
34 let line = &lines[0];
35 let parts: Vec<&str> = line.split_whitespace().collect();
36
37 if parts.len() < 5 {
40 return Err(ParsingError::new(
41 "Could not find enough (5) parameters for NAS".to_string(),
42 1,
43 ));
44 }
45
46 let direction_result = Direction::from_str(parts[2]);
47 let direction = match direction_result {
48 Ok(d) => d,
49 Err(_) => {
50 return Err(ParsingError::new(
51 format!("The direction could not be parsed in the part {:?} of {}", parts[2], line),
52 1,
53 ));
54 }
55 };
56
57 let message_type = if parts.len() > 5 {
59 parts[5..].join(" ")
60 } else {
61 parts.get(4).unwrap_or(&"Unknown").trim_end_matches(':').to_string()
62 };
63
64 Ok(AdditionalInfos::NASInfos(NASInfos { direction, message_type }))
65 }
66
67 fn parse(lines: &[String]) -> Result<Trace, ParsingError> {
68 let additional_infos = match Self::parse_additional_infos(lines) {
69 Ok(m) => m,
70 Err(e) => {
71 return Err(e);
72 }
73 };
74
75 let text = Self::parse_lines(lines);
76
77 let binary = extract_binary_from_lines(lines);
78
79 let timestamp = if let Some(first_line) = lines.first() {
81 super::parse_timestamp(first_line)?
82 } else {
83 0
84 };
85
86 let trace = Trace {
87 timestamp,
88 layer: Layer::NAS,
89 additional_infos,
90 text: Some(text),
91 binary,
92 relation: TraceRelation::default(),
93 };
94 Ok(trace)
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn test_parse_nas_line() {
104 let line = "13:20:58.310 [NAS] UL 0048 5GMM: Service request";
105 let lines = vec![line.to_string()];
106
107 let result = NASParser::parse_additional_infos(&lines);
108 assert!(result.is_ok());
109
110 match result.unwrap() {
111 AdditionalInfos::NASInfos(infos) => {
112 assert_eq!(infos.direction, Direction::UL);
113 assert_eq!(infos.message_type, "Service request");
114 }
115 _ => panic!("Expected NASInfos"),
116 }
117 }
118
119 #[test]
120 fn test_parse_nas_dl() {
121 let line = "13:20:58.310 [NAS] DL 0048 5GMM: Registration accept";
122 let lines = vec![line.to_string()];
123
124 let result = NASParser::parse_additional_infos(&lines);
125 assert!(result.is_ok());
126
127 match result.unwrap() {
128 AdditionalInfos::NASInfos(infos) => {
129 assert_eq!(infos.direction, Direction::DL);
130 assert_eq!(infos.message_type, "Registration accept");
131 }
132 _ => panic!("Expected NASInfos"),
133 }
134 }
135
136 #[test]
137 fn test_parse_nas_invalid_direction() {
138 let line = "13:20:58.310 [NAS] INVALID 0048 5GMM: Service request";
139 let lines = vec![line.to_string()];
140
141 let result = NASParser::parse_additional_infos(&lines);
142 assert!(result.is_err());
143 }
144}