use std::convert::TryFrom;
use super::{OptionCode, PcapNGOption};
pub fn build_ts_resolution(ts_resol: u8) -> Option<u64> {
let ts_mode = ts_resol & 0x80;
let unit = if ts_mode == 0 {
if ts_resol > 19 {
return None;
}
10u64.pow(ts_resol as u32)
} else {
if ts_resol > 63 {
return None;
}
1 << ((ts_resol & 0x7f) as u64)
};
Some(unit)
}
pub fn build_ts(ts_high: u32, ts_low: u32, ts_offset: u64, resolution: u64) -> (u32, u32) {
let if_tsoffset = ts_offset;
let ts: u64 = ((ts_high as u64) << 32) | (ts_low as u64);
let ts_sec = (if_tsoffset + (ts / resolution)) as u32;
let ts_fractional = (ts % resolution) as u32;
(ts_sec, ts_fractional)
}
pub fn build_ts_f64(ts_high: u32, ts_low: u32, ts_offset: u64, resolution: u64) -> f64 {
let ts: u64 = ((ts_high as u64) << 32) | (ts_low as u64);
let ts_sec = (ts_offset + (ts / resolution)) as u32;
let ts_fractional = (ts % resolution) as u32;
ts_sec as f64 + ((ts_fractional as f64) / (resolution as f64))
}
pub(crate) fn if_extract_tsoffset_and_tsresol(options: &[PcapNGOption]) -> (u8, i64) {
let mut if_tsresol: u8 = 6;
let mut if_tsoffset: i64 = 0;
for opt in options {
match opt.code {
OptionCode::IfTsresol => {
if !opt.value.is_empty() {
if_tsresol = opt.value[0];
}
}
OptionCode::IfTsoffset => {
if opt.value.len() >= 8 {
let int_bytes =
<[u8; 8]>::try_from(&opt.value[..8]).expect("Convert bytes to i64");
if_tsoffset = i64::from_le_bytes(int_bytes);
}
}
_ => (),
}
}
(if_tsresol, if_tsoffset)
}
#[cfg(test)]
mod tests {
use hex_literal::hex;
use super::*;
#[test]
fn decode_ts() {
const INPUT_HIGH: [u8; 4] = hex!("97 c3 04 00");
const INPUT_LOW: [u8; 4] = hex!("aa 47 ca 64");
let ts_high = u32::from_le_bytes(INPUT_HIGH);
let ts_low = u32::from_le_bytes(INPUT_LOW);
let ts_offset = 0;
let resolution = build_ts_resolution(6).unwrap();
let (ts_sec, ts_usec) = build_ts(ts_high, ts_low, ts_offset, resolution);
eprintln!("{ts_sec}:{ts_usec}");
const EXPECTED_TS_SEC: u32 = 1340954905;
const EXPECTED_TS_USEC: u32 = 298858;
assert_eq!(ts_sec, EXPECTED_TS_SEC);
assert_eq!(ts_usec, EXPECTED_TS_USEC);
}
}