pcap-async 0.1.2

Async/Stream Extensions for libpcap
Documentation
use crate::Error;

use byteorder::{ByteOrder, WriteBytesExt};
use futures::AsyncWriteExt;
use std::io::Cursor;

#[derive(Clone, Debug)]
pub struct Packet {
    timestamp: std::time::SystemTime,
    actual_length: u32,
    original_length: u32,
    data: Vec<u8>,
}

impl Packet {
    pub fn into_data(self) -> Vec<u8> {
        self.data
    }
    pub fn into_pcap_record<T: ByteOrder>(self) -> Result<Vec<u8>, Error> {
        let dur = self
            .timestamp
            .duration_since(std::time::UNIX_EPOCH)
            .map_err(Error::Time)?;
        let data = Vec::with_capacity(self.data.len() + 4 * std::mem::size_of::<u32>());
        let mut cursor = Cursor::new(data);
        cursor
            .write_u32::<T>(dur.as_secs() as _)
            .map_err(Error::Io)?;
        cursor
            .write_u32::<T>(dur.subsec_micros())
            .map_err(Error::Io)?;
        cursor
            .write_u32::<T>(self.actual_length)
            .map_err(Error::Io)?;
        cursor
            .write_u32::<T>(self.original_length)
            .map_err(Error::Io)?;
        let mut res = cursor.into_inner();
        res.extend(self.data);
        Ok(res)
    }
    pub fn timestamp(&self) -> &std::time::SystemTime {
        &self.timestamp
    }
    pub fn data(&self) -> &Vec<u8> {
        &self.data
    }
    pub fn actual_length(&self) -> u32 {
        self.actual_length
    }
    pub fn original_length(&self) -> u32 {
        self.original_length
    }

    pub fn new(
        timestamp: std::time::SystemTime,
        actual_length: u32,
        original_length: u32,
        data: Vec<u8>,
    ) -> Packet {
        Packet {
            timestamp: timestamp,
            actual_length: actual_length,
            original_length: original_length,
            data,
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use byteorder::ReadBytesExt;
    use std::io::Read;
    use std::time::SystemTime;

    #[test]
    fn converts_to_record() {
        let ts = SystemTime::now();
        let data = vec![0u8; 100];
        let packet = Packet {
            timestamp: ts,
            actual_length: 100,
            original_length: 200,
            data: data.clone(),
        };
        let bytes = packet
            .into_pcap_record::<byteorder::LittleEndian>()
            .expect("Failed to convert to record");

        let dur = ts
            .duration_since(std::time::UNIX_EPOCH)
            .expect("Could not convert to dur");

        let mut cursor = Cursor::new(bytes);
        assert_eq!(
            cursor
                .read_u32::<byteorder::LittleEndian>()
                .expect("Failed to read"),
            dur.as_secs() as u32
        );
        assert_eq!(
            cursor
                .read_u32::<byteorder::LittleEndian>()
                .expect("Failed to read"),
            dur.subsec_micros()
        );
        assert_eq!(
            cursor
                .read_u32::<byteorder::LittleEndian>()
                .expect("Failed to read"),
            100
        );
        assert_eq!(
            cursor
                .read_u32::<byteorder::LittleEndian>()
                .expect("Failed to read"),
            200
        );
        let mut read_data = vec![];
        assert_eq!(
            cursor.read_to_end(&mut read_data).expect("Failed to read"),
            100
        );
        assert_eq!(read_data, data);
    }
}