use std::borrow::Cow;
use std::io::Read;
use byteorder::*;
use errors::*;
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
pub struct PacketHeader {
pub ts_sec: u32,
pub ts_usec: u32,
pub incl_len: u32,
pub orig_len: u32
}
impl PacketHeader {
pub fn new(ts_sec: u32, ts_usec: u32, len:u32) -> PacketHeader {
PacketHeader {
ts_sec: ts_sec,
ts_usec: ts_usec,
incl_len: len,
orig_len: len,
}
}
pub fn from_reader<R: Read, B: ByteOrder>(reader: &mut R) -> ResultChain<PacketHeader> {
let ts_sec = reader.read_u32::<B>()?;
let ts_usec = reader.read_u32::<B>()?;
let incl_len = reader.read_u32::<B>()?;
let orig_len = reader.read_u32::<B>()?;
if incl_len > 0xFFFF {
bail!(ErrorKind::WrongField(format!("PacketHeader.incl_len = {} > 0xFFFF", incl_len)));
}
if orig_len > 0xFFFF {
bail!(ErrorKind::WrongField(format!("PacketHeader.orig_len = {} > 0xFFFF", orig_len)));
}
if incl_len > orig_len {
bail!(ErrorKind::WrongField(format!("PacketHeader.incl_len ({}) > PacketHeader.orig_len ({})", incl_len, orig_len)));
}
Ok(
PacketHeader {
ts_sec,
ts_usec,
incl_len,
orig_len
}
)
}
pub fn to_array<B: ByteOrder>(&self) -> ResultChain<Vec<u8>> {
let mut out = Vec::with_capacity(16);
out.write_u32::<B>(self.ts_sec)?;
out.write_u32::<B>(self.ts_usec)?;
out.write_u32::<B>(self.incl_len)?;
out.write_u32::<B>(self.orig_len)?;
Ok(out)
}
}
#[derive(Clone, Debug)]
pub struct Packet<'a> {
pub header: PacketHeader,
pub data: Cow<'a, [u8]>
}
impl<'a> Packet<'a> {
pub fn new(ts_sec: u32, ts_usec: u32, len:u32, data: &'a [u8]) -> Packet<'a> {
let header = PacketHeader::new(ts_sec, ts_usec, len);
Packet {
header: header,
data: Cow::Borrowed(data)
}
}
pub fn new_owned(ts_sec: u32, ts_usec: u32, len:u32, data: Vec<u8>) -> Packet<'static> {
let header = PacketHeader::new(ts_sec, ts_usec, len);
Packet {
header: header,
data: Cow::Owned(data)
}
}
pub fn from_reader<R: Read, B: ByteOrder>(reader: &mut R) -> ResultChain<Packet<'static>> {
let header = PacketHeader::from_reader::<R, B>(reader)?;
let mut bytes = vec![0u8; header.incl_len as usize];
reader.read_exact(&mut bytes)?;
Ok(
Packet {
header,
data : Cow::Owned(bytes)
}
)
}
pub fn from_slice<B: ByteOrder>(slice: &[u8]) -> ResultChain<Packet> {
let mut slice = &slice[..];
let header = PacketHeader::from_reader::<_, B>(&mut slice)?;
if header.incl_len > slice.len() as u32 {
bail!(ErrorKind::BufferUnderflow(header.incl_len as u64, slice.len() as u64))
}
let len = header.incl_len as usize;
Ok(
Packet {
header : header,
data : Cow::Borrowed(&slice[0..len])
}
)
}
pub fn into_owned(self) -> Packet<'static> {
Packet {
header: self.header,
data: Cow::Owned(self.data.into_owned())
}
}
}