use std::cell::RefCell;
use std::fmt;
use std::ops::{Deref, DerefMut};
use bytemuck::Pod;
pub struct RefMut<'a, T> {
buf: std::cell::RefMut<'a, Vec<u8>>,
off: usize,
phantom: std::marker::PhantomData<T>,
}
impl<T> RefMut<'_, T> {
pub fn size_of() -> usize {
std::mem::size_of::<T>()
}
pub fn len(&self) -> usize {
Self::size_of()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<T> DerefMut for RefMut<'_, T> {
#[inline]
fn deref_mut(&mut self) -> &mut T {
let off = self.off;
let bytes = &self.buf[off..off + Self::size_of()];
unsafe { &mut *(bytes.as_ptr() as *mut T) }
}
}
impl<T> Deref for RefMut<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
let off = self.off;
let bytes = &self.buf[off..off + Self::size_of()];
unsafe { &*(bytes.as_ptr() as *const T) }
}
}
pub struct Ref<'a, T> {
buf: std::cell::Ref<'a, Vec<u8>>,
off: usize,
phantom: std::marker::PhantomData<T>,
}
impl<T> Ref<'_, T> {
pub fn size_of() -> usize {
std::mem::size_of::<T>()
}
pub fn len(&self) -> usize {
Self::size_of()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<T> Deref for Ref<'_, T> {
type Target = T;
#[inline]
fn deref(&self) -> &T {
let off = self.off;
let len = Self::size_of();
let bytes = &self.buf[off..off + len];
unsafe { &*(bytes.as_ptr() as *const T) }
}
}
pub struct SliceRefMut<'a> {
buf: std::cell::RefMut<'a, Vec<u8>>,
off: usize,
len: usize,
}
impl DerefMut for SliceRefMut<'_> {
#[inline]
fn deref_mut(&mut self) -> &mut [u8] {
&mut self.buf[self.off..self.off + self.len]
}
}
impl Deref for SliceRefMut<'_> {
type Target = [u8];
#[inline]
fn deref(&self) -> &[u8] {
&self.buf[self.off..self.off + self.len]
}
}
pub struct SliceRef<'a> {
buf: std::cell::Ref<'a, Vec<u8>>,
off: usize,
len: usize,
}
impl AsRef<[u8]> for SliceRef<'_> {
#[inline]
fn as_ref(&self) -> &[u8] {
self.deref()
}
}
impl Deref for SliceRef<'_> {
type Target = [u8];
#[inline]
fn deref(&self) -> &[u8] {
&self.buf[self.off..self.off + self.len]
}
}
#[derive(Debug, Copy, Clone)]
pub struct Hdr<T> {
off: usize,
phantom: std::marker::PhantomData<T>,
}
impl<T: Pod> Hdr<T> {
fn new(off: usize) -> Self {
Self {
off,
phantom: std::marker::PhantomData,
}
}
pub fn off(&self) -> usize {
self.off
}
pub fn size_of() -> usize {
std::mem::size_of::<T>()
}
pub fn len(&self) -> usize {
Self::size_of()
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn get<'a>(&self, pkt: &'a Packet) -> Ref<'a, T> {
Ref {
buf: pkt.buf.borrow(),
off: self.off,
phantom: self.phantom,
}
}
pub fn get_mut<'a>(&self, pkt: &'a Packet) -> RefMut<'a, T> {
RefMut {
buf: pkt.buf.borrow_mut(),
off: self.off,
phantom: self.phantom,
}
}
pub fn mutate<F>(&self, pkt: &Packet, f: F)
where
F: FnOnce(&mut T),
{
let mut buf = pkt.buf.borrow_mut();
let off = self.off;
let bytes = &mut buf[off..off + Self::size_of()];
f(unsafe { &mut *(bytes.as_ptr() as *mut T) });
}
pub fn mutate_as_bytes<F>(&self, pkt: &Packet, f: F)
where
F: FnOnce(&mut [u8]),
{
let mut buf = pkt.buf.borrow_mut();
let off = self.off;
let bytes = &mut buf[off..off + Self::size_of()];
f(bytes);
}
pub fn as_slice(&self) -> PktSlice {
PktSlice {
off: self.off(),
len: Self::size_of(),
}
}
pub fn payload(&self, n: usize) -> PktSlice {
let begin = self.off() + Self::size_of();
PktSlice { off: begin, len: n }
}
pub fn packet(&self, n: usize) -> PktSlice {
let begin = self.off();
PktSlice { off: begin, len: n }
}
pub fn as_bytes<'a>(&self, pkt: &'a Packet) -> SliceRef<'a> {
self.as_slice().get(pkt)
}
pub fn as_bytes_mut<'a>(&self, pkt: &'a Packet) -> SliceRefMut<'a> {
self.as_slice().get_mut(pkt)
}
pub fn bytes_after<'a>(&self, pkt: &'a Packet, n: usize) -> SliceRef<'a> {
self.payload(n).get(pkt)
}
pub fn bytes_after_mut<'a>(&self, pkt: &'a Packet, n: usize) -> SliceRefMut<'a> {
self.payload(n).get_mut(pkt)
}
pub fn packet_bytes<'a>(&self, pkt: &'a Packet, n: usize) -> SliceRef<'a> {
self.packet(n).get(pkt)
}
pub fn packet_bytes_mut<'a>(&self, pkt: &'a Packet, n: usize) -> SliceRefMut<'a> {
self.packet(n).get_mut(pkt)
}
pub fn len_from(&self, pkt: &Packet) -> usize {
pkt.len_from(self.off)
}
pub fn len_after(&self, pkt: &Packet) -> usize {
pkt.len_from(self.off + Self::size_of())
}
}
#[derive(Debug, Copy, Clone)]
pub struct PktSlice {
off: usize,
len: usize,
}
impl PktSlice {
fn new(off: usize, len: usize) -> Self {
Self { off, len }
}
pub fn off(&self) -> usize {
self.off
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn get<'a>(&self, pkt: &'a Packet) -> SliceRef<'a> {
SliceRef {
buf: pkt.buf.borrow(),
off: self.off,
len: self.len,
}
}
pub fn get_mut<'a>(&self, pkt: &'a Packet) -> SliceRefMut<'a> {
SliceRefMut {
buf: pkt.buf.borrow_mut(),
off: self.off,
len: self.len,
}
}
pub fn mutate<F>(&self, pkt: &Packet, f: F)
where
F: FnOnce(&mut [u8]),
{
let mut buf = pkt.buf.borrow_mut();
let off = self.off;
let bytes = &mut buf[off..off + self.len()];
f(bytes);
}
}
#[derive(Clone, Eq, PartialEq)]
pub struct Packet {
buf: RefCell<Vec<u8>>,
headroom: usize,
}
impl fmt::Debug for Packet {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if f.alternate() {
self.alt_fmt(f, 16)
} else {
f.write_fmt(format_args!("Packet<{} bytes>", self.len()))?;
Ok(())
}
}
}
impl Default for Packet {
fn default() -> Self {
Packet::new(Self::DEFAULT_HEADROOM, Self::DEFAULT_CAPACITY)
}
}
impl Packet {
const DEFAULT_HEADROOM: usize = 16;
const DEFAULT_CAPACITY: usize = 64;
pub fn new(headroom: usize, capacity: usize) -> Self {
let new: Self = Self {
buf: RefCell::new(Vec::with_capacity(headroom + capacity)),
headroom,
};
new.expand(headroom);
new
}
pub fn with_headroom(headroom: usize) -> Self {
Packet::new(headroom, Self::DEFAULT_CAPACITY)
}
pub fn with_capacity(capacity: usize) -> Self {
Packet::new(Self::DEFAULT_HEADROOM, capacity)
}
pub fn headroom(&self) -> usize {
self.headroom
}
pub fn len(&self) -> usize {
let buf = self.buf.borrow();
assert!(buf.len() >= self.headroom);
buf.len() - self.headroom
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
fn len_from(&self, off: usize) -> usize {
let buf = self.buf.borrow();
let end = buf.len();
assert!(end >= off);
end - off
}
fn expand(&self, len: usize) -> usize {
let mut buf = self.buf.borrow_mut();
let prev_len = buf.len();
let new_len = prev_len + len;
buf.resize(new_len, 0);
prev_len
}
pub fn push_hdr<T: Pod>(&self) -> Hdr<T> {
let off = self.expand(std::mem::size_of::<T>());
Hdr::new(off)
}
pub fn push<T: Pod>(&self, item: T) -> Hdr<T> {
let hdr: Hdr<T> = self.push_hdr();
let mut buf = hdr.get_mut(self);
*buf = item;
hdr
}
pub fn push_bytes<T: AsRef<[u8]>>(&self, bytes: T) -> PktSlice {
let mut buf = self.buf.borrow_mut();
let off = buf.len();
let s = bytes.as_ref();
buf.extend_from_slice(s);
PktSlice::new(off, s.len())
}
pub fn push_slice(&self, len: usize) -> PktSlice {
PktSlice::new(self.expand(len), len)
}
pub fn as_slice(&self) -> PktSlice {
assert!(self.len() >= self.headroom);
PktSlice::new(self.headroom, self.len())
}
pub fn lower_headroom<T: Pod>(&mut self) -> Hdr<T> {
let sz = std::mem::size_of::<T>();
assert!(sz <= self.headroom);
self.headroom -= sz;
Hdr::new(self.headroom)
}
pub fn lower_headroom_for<T: Pod>(&mut self, item: T) -> Hdr<T> {
let hdr: Hdr<T> = self.lower_headroom();
let mut buf = hdr.get_mut(self);
*buf = item;
hdr
}
pub fn return_headroom<T: Pod>(&mut self, hdr: Hdr<T>) {
assert!(hdr.off() == self.headroom);
assert!(Hdr::<T>::size_of() <= self.len());
self.headroom += Hdr::<T>::size_of();
}
pub fn to_vec(&self) -> Vec<u8> {
let buf = self.buf.borrow();
if self.headroom == 0 {
buf.clone()
} else {
let s = &buf[self.headroom..self.headroom + self.len()];
s.to_owned()
}
}
pub fn to_vec_from(&self, ps: PktSlice) -> Vec<u8> {
let buf = self.buf.borrow();
assert!(ps.off >= self.headroom);
if ps.off == self.headroom && ps.len == self.len() {
buf.clone()
} else {
let s = &buf[ps.off..ps.off + ps.len];
s.to_owned()
}
}
pub fn into_vec_from(self, ps: PktSlice) -> Vec<u8> {
assert!(ps.off >= self.headroom);
if ps.off == self.headroom && ps.len == self.len() {
self.buf.into_inner()
} else {
let buf = self.buf.borrow();
let s = &buf[ps.off..ps.off + ps.len];
s.to_owned()
}
}
fn fmt_hex_dump(&self, f: &mut fmt::Formatter<'_>, width: usize) -> fmt::Result {
let mut pos = self.headroom;
let buf = self.buf.borrow();
let len = buf.len();
while pos < len {
let valid = if pos + width < buf.len() {
width
} else {
buf.len() - pos
};
let bytes = &buf[pos..pos + valid];
f.write_fmt(format_args!("{:05x} |", pos))?;
for b in bytes[0..valid].iter() {
f.write_fmt(format_args!(" {:02x}", b))?;
}
for _ in valid..width {
f.write_str(" ")?;
}
f.write_str(" ")?;
for b in bytes[0..valid].iter() {
let chr = *b as char;
if chr.is_ascii_graphic() {
f.write_fmt(format_args!("{}", chr))?;
} else {
f.write_str(".")?
}
}
f.write_str("\n")?;
pos += width;
}
Ok(())
}
fn alt_fmt(&self, f: &mut fmt::Formatter<'_>, width: usize) -> fmt::Result {
f.write_fmt(format_args!("{} byte packet:\n", self.len()))?;
self.fmt_hex_dump(f, width)
}
#[inline(always)]
fn ethernet_overhead(&self) -> u64 {
24
}
#[inline(always)]
fn timing_overhead(&self) -> u64 {
self.ethernet_overhead()
}
#[inline(always)]
pub fn bit_time(&self) -> u64 {
let len: u64 = self.len() as u64;
let bytes = len + self.timing_overhead();
bytes * 8
}
}
impl From<Packet> for Vec<u8> {
fn from(p: Packet) -> Self {
p.to_vec()
}
}