use byteorder::{ByteOrder, BigEndian, LittleEndian, NativeEndian};
use crate::{
Endianness,
errors::*,
pcap::PcapHeader,
pcap::{Packet, PacketHeader}
};
use std::{
borrow::Cow,
io::Write
};
#[derive(Debug)]
pub struct PcapWriter<W: Write> {
pub header: PcapHeader,
writer: W
}
impl<W: Write> PcapWriter<W> {
pub fn new(writer: W) -> ResultParsing<PcapWriter<W>> {
let tmp = NativeEndian::read_u16(&[0x42, 0x00]);
let endianness = match tmp {
0x4200 => Endianness::Big,
0x0042 => Endianness::Little,
_ => unreachable!()
};
let mut header = PcapHeader::default();
header.set_endianness(endianness);
PcapWriter::with_header(header, writer)
}
pub fn with_header(header: PcapHeader, mut writer: W) -> ResultParsing<PcapWriter<W>> {
match header.endianness() {
Endianness::Big => header.write_to::<_, BigEndian>(&mut writer)?,
Endianness::Little => header.write_to::<_, LittleEndian>(&mut writer)?,
}
Ok(
PcapWriter {
header,
writer
}
)
}
pub fn into_writer(self) -> W {
self.writer
}
pub fn get_ref(&self) -> &W {
&self.writer
}
pub fn get_mut(&mut self) -> &mut W {
&mut self.writer
}
pub fn write(&mut self, ts_sec: u32, ts_nsec: u32, data: &[u8], orig_len: u32) -> ResultParsing<()> {
let packet = Packet {
header: PacketHeader::new(ts_sec, ts_nsec, data.len() as u32, orig_len),
data: Cow::Borrowed(data)
};
self.write_packet(&packet)
}
pub fn write_packet(&mut self, packet: &Packet) -> ResultParsing<()> {
let ts_resolution = self.header.ts_resolution();
match self.header.endianness() {
Endianness::Big => packet.header.write_to::<_, BigEndian>(&mut self.writer, ts_resolution)?,
Endianness::Little => packet.header.write_to::<_, LittleEndian>(&mut self.writer, ts_resolution)?,
}
self.writer.write_all(&packet.data)?;
Ok(())
}
}