use std::io::Write;
use std::time::Duration;
use super::types::LinkType;
pub struct PcapNgWriter<W: Write> {
writer: W,
}
impl<W: Write> PcapNgWriter<W> {
pub fn new(mut writer: W, link_type: LinkType) -> Result<Self, std::io::Error> {
let shb_body = [0u8; 16]; let shb_len = 28u32; writer.write_all(&0x0A0D0D0Au32.to_be_bytes())?;
writer.write_all(&shb_len.to_be_bytes())?;
writer.write_all(&shb_body)?;
writer.write_all(&shb_len.to_be_bytes())?;
let lt: u16 = match link_type { LinkType::Ethernet => 1, LinkType::Raw => 101, LinkType::Unknown(v) => v as u16 };
let mut idb_body = vec![0u8; 16];
idb_body[8..10].copy_from_slice(<.to_le_bytes()); let idb_len = 32u32; writer.write_all(&1u32.to_be_bytes())?;
writer.write_all(&idb_len.to_be_bytes())?;
writer.write_all(&idb_body)?;
writer.write_all(&idb_len.to_be_bytes())?;
Ok(Self { writer })
}
pub fn write_epb(&mut self, ts: Duration, packet: &[u8]) -> Result<(), std::io::Error> {
let padded_len = (packet.len() + 3) & !3;
let epb_body_len = 20 + padded_len;
let epb_total_len = 12 + epb_body_len;
self.writer.write_all(&6u32.to_be_bytes())?;
self.writer.write_all(&(epb_total_len as u32).to_be_bytes())?;
self.writer.write_all(&0u32.to_be_bytes())?; self.writer.write_all(&(ts.as_secs() as u32).to_be_bytes())?; self.writer.write_all(&ts.subsec_nanos().to_be_bytes())?; self.writer.write_all(&(packet.len() as u32).to_be_bytes())?; self.writer.write_all(&(packet.len() as u32).to_be_bytes())?; self.writer.write_all(packet)?;
if padded_len > packet.len() {
self.writer.write_all(&vec![0u8; padded_len - packet.len()])?;
}
self.writer.write_all(&(epb_total_len as u32).to_be_bytes())?;
self.writer.flush()
}
}