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
use regex::Regex;
use crate::tables::{EtcProtocols,EtcProtocolsIface};
use std::str::FromStr;
use std::borrow::Borrow;
cfg_if! {
if #[cfg(target_os = "linux")] {
use crate::linux::EtcProtocolsReader;
} else if #[cfg(target_os = "macos")] {
use crate::macos::EtcProtocolsReader;
} else if #[cfg(target_os = "windows")] {
use crate::windows::EtcProtocolsReader;
}
}
lazy_static! {
static ref PROTOCOLS_FILE_REGEX: Regex = Regex::new(r"(?m)^([^#]*)").unwrap();
static ref PROTOCOLS_FILE_REGEX_COMMENTS: Regex = Regex::new(r"#\s*(.*)").unwrap();
}
impl EtcProtocols {
pub fn new() -> EtcProtocols {
EtcProtocols {
name: String::new(),
number: 0,
alias: String::new(),
comment: String::new(),
}
}
pub fn get_specific_ex(reader: &dyn EtcProtocolsIface) -> Vec<EtcProtocols> {
let mut protocols: Vec<EtcProtocols> = Vec::new();
for line in reader
.get_protocols_file()
.unwrap_or_else(|| "".to_string())
.lines()
{
let mut etc_protocols = EtcProtocols::new();
let captures = PROTOCOLS_FILE_REGEX.captures(&line);
if let Some(cap) = captures {
if let Some(protocols_group) = cap.get(0) {
if protocols_group.as_str().is_empty() {
continue;
}
let v: Vec<_> = protocols_group.as_str().trim().split_whitespace().collect();
if v.len() <= 2 {
continue;
}
etc_protocols.name = v[0].to_string();
etc_protocols.number = u16::from_str(v[1]).unwrap_or(0);
if let Some(alias) = v.get(2) {
etc_protocols.alias = alias.to_string();
}
};
let comments = PROTOCOLS_FILE_REGEX_COMMENTS.captures(&line);
if let Some(cap) = comments {
if let Some(captured_comments) = cap.get(1) {
if !captured_comments.as_str().is_empty() {
etc_protocols.comment = captured_comments.as_str().to_owned();
}
};
}
};
protocols.push(etc_protocols);
}
protocols
}
pub fn get_specific() -> Vec<EtcProtocols> {
let reader: Box<dyn EtcProtocolsIface> = Box::new(EtcProtocolsReader{});
let out = EtcProtocols::get_specific_ex(reader.borrow());
out
}
}
#[cfg(test)]
mod tests {
use super::*;
pub struct EtcProtocolsTest {}
impl EtcProtocolsIface for EtcProtocolsTest {
fn get_protocols_file(&self) -> Option<String> {
Some(String::from(include_str!("../../test_data/protocols.txt")))
}
}
#[test]
fn test_etc_protocols () {
let reader: Box<dyn EtcProtocolsIface> = Box::new(EtcProtocolsTest {});
let etc_protocols = EtcProtocols::get_specific_ex(reader.borrow());
assert_eq!(etc_protocols.get(0).unwrap().name, "ip");
assert_eq!(etc_protocols.get(0).unwrap().number, 0);
assert_eq!(etc_protocols.get(0).unwrap().alias, "IP");
assert_eq!(etc_protocols.get(0).unwrap().comment, "internet protocol, pseudo protocol number");
assert_eq!(etc_protocols.get(1).unwrap().name, "icmp");
assert_eq!(etc_protocols.get(1).unwrap().number, 1);
assert_eq!(etc_protocols.get(1).unwrap().alias, "ICMP");
assert_eq!(etc_protocols.get(1).unwrap().comment, "internet control message protocol");
assert_eq!(etc_protocols.len(), 3);
}
}