1#![forbid(unsafe_code)]
2use std::{cmp, fmt::Display, io::Write};
6
7use crate::{
8 byte_order::{ByteOrder, WriteExt},
9 pcap::file_header::MagicNumberAndEndianness,
10 pcap_ng::PCAP_NG_MAGIC,
11};
12pub mod any_reader;
13pub mod byte_order;
14pub mod link_type;
15pub mod pcap;
16pub mod pcap_ng;
17pub(crate) mod utils;
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum PcapFileType {
21 Pcap,
25 PcapNg,
27}
28impl Display for PcapFileType {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 match self {
31 PcapFileType::Pcap => write!(f, "PCAP"),
32 PcapFileType::PcapNg => write!(f, "PCAP-NG"),
33 }
34 }
35}
36impl PcapFileType {
37 pub fn from_magic(magic: [u8; 4]) -> Option<Self> {
39 if MagicNumberAndEndianness::try_from(magic).is_ok() {
40 Some(PcapFileType::Pcap)
41 } else if magic == PCAP_NG_MAGIC {
42 Some(PcapFileType::PcapNg)
43 } else {
44 None
45 }
46 }
47}
48
49#[derive(Debug, Clone, Copy, PartialEq, Eq)]
53pub struct Version {
54 pub major: u16,
56 pub minor: u16,
58}
59impl PartialOrd for Version {
60 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
61 Some(self.cmp(other))
62 }
63}
64impl Ord for Version {
65 fn cmp(&self, other: &Self) -> cmp::Ordering {
66 self.major
67 .cmp(&other.major)
68 .then_with(|| self.minor.cmp(&other.minor))
69 }
70}
71impl Version {
72 pub const PCAP_VERSION_2_4: Version = Version { major: 2, minor: 4 };
74 pub const PCAP_VERSION_2_3: Version = Version { major: 2, minor: 3 };
76 #[inline(always)]
78 pub(crate) fn parse(bytes: &[u8], byte_order: impl ByteOrder) -> Self {
79 let major = byte_order.u16_from_bytes([bytes[0], bytes[1]]);
80 let minor = byte_order.u16_from_bytes([bytes[2], bytes[3]]);
81 Self { major, minor }
82 }
83 pub(crate) fn write<W: Write>(
84 &self,
85 target: &mut W,
86 byte_order: impl ByteOrder,
87 ) -> Result<(), std::io::Error> {
88 target.write_u16(self.major, byte_order)?;
89 target.write_u16(self.minor, byte_order)?;
90 Ok(())
91 }
92}
93
94#[cfg(test)]
95pub(crate) mod test_helpers {
96 use std::{
97 fs::{File, create_dir_all},
98 io::Read,
99 path::{Path, PathBuf},
100 };
101
102 use anyhow::{Result, anyhow};
103
104 use crate::Version;
105
106 pub fn test_target_dir() -> Result<PathBuf> {
107 let base_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
108
109 let target_dir = base_dir.join("test_data/actual");
110
111 if !target_dir.exists() {
112 create_dir_all(&target_dir)?;
113 }
114 Ok(target_dir)
115 }
116 pub fn test_expected_dir() -> Result<PathBuf> {
117 let base_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
118
119 let target_dir = base_dir.join("test_data/expected");
120
121 if !target_dir.exists() {
122 create_dir_all(&target_dir)?;
123 }
124 Ok(target_dir)
125 }
126
127 pub fn test_files(test_file_name: &str) -> Result<(PathBuf, PathBuf)> {
128 let test_actual = test_target_dir()?.join(test_file_name);
129 let test_expected = test_expected_dir()?.join(test_file_name);
130 Ok((test_actual, test_expected))
131 }
132 #[track_caller]
133 pub fn do_files_match(actual: impl AsRef<Path>, expected: impl AsRef<Path>) -> Result<()> {
134 if !expected.as_ref().exists() {
135 println!("Expected Does not exist coppying actual over");
136 std::fs::copy(actual, expected)?;
137 return Err(anyhow!(
138 "No Expected File existed. But this is just to signal that you a new file was generated"
139 ));
140 }
141 let mut actual_file = File::open(actual)?;
142 let mut expected_file = File::open(expected)?;
143 let mut actual_bytes = Vec::with_capacity(actual_file.metadata()?.len() as usize);
144 let mut expected_bytes = Vec::with_capacity(actual_file.metadata()?.len() as usize);
145
146 actual_file.read_to_end(&mut actual_bytes)?;
147 expected_file.read_to_end(&mut expected_bytes)?;
148
149 assert_eq!(actual_bytes, expected_bytes);
150
151 Ok(())
152 }
153
154 #[test]
155 fn test_version_cmp() {
156 let v2_4 = Version { major: 2, minor: 4 };
157 let v2_3 = Version { major: 2, minor: 3 };
158 let v2_1 = Version { major: 1, minor: 1 };
159
160 assert!(v2_4 > v2_3);
161 assert!(v2_3 > v2_1);
162 assert!(v2_4 > v2_1);
163 }
164}