use core::ops::Range;
use crate::error::{LengthExceedsAvailableSpaceError, NotEnoughHeadroomError};
use crate::ipv6_extensions::{Ipv6ExtMetaData, Ipv6ExtMetaDataMut};
pub trait BufferIntoInner<B>
where
B: AsRef<[u8]>,
{
fn data_length(&self) -> usize;
fn headroom(&self) -> usize;
fn buffer_into_inner(self) -> B;
fn buffer_get_ref(&self) -> &[u8];
}
pub trait Payload {
fn payload(&self) -> &[u8];
fn payload_length(&self) -> usize;
}
pub trait PayloadMut {
fn payload_mut(&mut self) -> &mut [u8];
}
pub(crate) trait HeaderMetadataExtraction<HM>
where
HM: HeaderMetadata + HeaderMetadataMut + Copy,
{
fn extract_header_metadata(&self) -> &HM;
}
pub(crate) trait EthernetMarker: HeaderMetadata + HeaderMetadataMut {}
pub(crate) trait Ieee802_1QVlanMarker: HeaderMetadata + HeaderMetadataMut {}
pub(crate) trait ArpMarker: HeaderMetadata + HeaderMetadataMut {}
pub(crate) trait Ipv4Marker: HeaderMetadata + HeaderMetadataMut {}
pub(crate) trait Ipv6Marker: HeaderMetadata + HeaderMetadataMut {}
pub(crate) trait Ipv6ExtMarker<const MAX_EXTENSIONS: usize>:
HeaderMetadata
+ HeaderMetadataMut
+ Ipv6ExtMetaData<MAX_EXTENSIONS>
+ Ipv6ExtMetaDataMut<MAX_EXTENSIONS>
{
}
pub(crate) trait TcpMarker: HeaderMetadata + HeaderMetadataMut {}
pub(crate) trait UdpMarker: HeaderMetadata + HeaderMetadataMut {}
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub(crate) enum Layer {
NoPreviousHeader,
EthernetII,
Ieee802_1QVlan,
Arp,
Ipv4,
Ipv6,
Ipv6Ext,
Tcp,
Udp,
}
pub(crate) trait BufferAccess {
fn buffer_length(&self) -> usize;
fn data_buffer_starting_at_header(&self, layer: Layer) -> &[u8];
fn read_slice(&self, layer: Layer, range: Range<usize>) -> &[u8];
fn read_value(&self, layer: Layer, idx: usize) -> u8;
fn read_array<const N: usize>(&self, layer: Layer, range: Range<usize>) -> [u8; N];
}
pub(crate) trait BufferAccessMut {
fn data_buffer_starting_at_header_mut(&mut self, layer: Layer) -> &mut [u8];
fn buffer_mut(&mut self) -> &mut [u8];
fn get_slice_mut(&mut self, layer: Layer, range: Range<usize>) -> &mut [u8];
fn write_value(&mut self, layer: Layer, idx: usize, value: u8);
fn write_slice(&mut self, layer: Layer, range: Range<usize>, slice: &[u8]);
}
pub(crate) trait HeaderMetadata {
fn headroom_internal(&self) -> usize;
fn header_start_offset(&self, layer: Layer) -> usize;
fn header_length(&self, layer: Layer) -> usize;
fn layer(&self) -> Layer;
fn data_length_internal(&self) -> usize;
}
pub(crate) trait HeaderManipulation:
BufferAccess + BufferAccessMut + HeaderMetadata + HeaderMetadataMut
{
#[inline]
fn grow_header(
&mut self,
current_header_bytes_to_move: usize,
grow_by: usize,
layer: Layer,
) -> Result<(), NotEnoughHeadroomError> {
if self.headroom_internal() >= grow_by {
assert!(current_header_bytes_to_move <= self.header_length(layer));
let start = self.headroom_internal();
let end = self.headroom_internal()
+ self.header_start_offset(layer)
+ current_header_bytes_to_move;
let destination = self.headroom_internal() - grow_by;
*self.header_length_mut(layer) += grow_by;
self.increase_header_start_offset(grow_by, layer);
*self.headroom_internal_mut() -= grow_by;
let data_length = self.data_length_internal() + grow_by;
self.set_data_length(data_length, self.buffer_length())
.expect("grow_by cannot set the data end higher than the buffer length");
self.buffer_mut().copy_within(start..end, destination);
Ok(())
} else {
Err(NotEnoughHeadroomError {
required: grow_by,
available: self.headroom_internal(),
})
}
}
#[inline]
fn shrink_header(
&mut self,
current_header_bytes_to_move: usize,
shrink_by: usize,
layer: Layer,
) {
assert!(self.header_length(layer) > shrink_by);
assert!(current_header_bytes_to_move <= self.header_length(layer) - shrink_by);
let start = self.headroom_internal();
let end = self.headroom_internal()
+ self.header_start_offset(layer)
+ current_header_bytes_to_move;
let destination = self.headroom_internal() + shrink_by;
*self.header_length_mut(layer) -= shrink_by;
self.decrease_header_start_offset(shrink_by, layer);
*self.headroom_internal_mut() += shrink_by;
let data_length = self.data_length_internal() - shrink_by;
self.set_data_length(data_length, self.buffer_length())
.expect("shrink_header cannot set the data end higher than the buffer length");
self.buffer_mut().copy_within(start..end, destination);
}
}
pub(crate) trait HeaderMetadataMut {
fn headroom_internal_mut(&mut self) -> &mut usize;
fn increase_header_start_offset(&mut self, increase_by: usize, layer: Layer);
fn decrease_header_start_offset(&mut self, decrease_by: usize, layer: Layer);
fn header_length_mut(&mut self, layer: Layer) -> &mut usize;
fn set_data_length(
&mut self,
data_length: usize,
buffer_length: usize,
) -> Result<(), LengthExceedsAvailableSpaceError>;
}