#![no_std]
#![deny(missing_docs)]
use alloc::vec;
#[cfg(feature = "alloc")]
pub use alloc::vec::Vec;
use core::{
marker::PhantomData,
mem::MaybeUninit,
ops::{Deref, DerefMut},
};
use zerocopy::{
FromBytes, Immutable, IntoByteSliceMut, IntoBytes, KnownLayout, Ref,
};
pub use zerocopy::{
ByteSlice, ByteSliceMut, IntoByteSlice, SplitByteSlice, SplitByteSliceMut,
};
#[cfg(feature = "alloc")]
extern crate alloc;
mod accessor;
mod emit;
mod error;
pub mod field;
pub mod header;
pub mod ip;
pub mod primitives;
pub mod util;
ingot_macros::define_tuple_trait_impls!();
pub use accessor::Accessor;
pub use emit::*;
pub use error::*;
pub use field::*;
pub use header::*;
pub use ip::*;
pub trait ToOwnedPacket: NextLayer {
type Target;
fn to_owned(&self, hint: Option<Self::Hint>) -> ParseResult<Self::Target>;
}
pub trait HeaderLen {
const MINIMUM_LENGTH: usize;
fn packet_length(&self) -> usize;
}
impl<H: HeaderLen> HeaderLen for &H {
const MINIMUM_LENGTH: usize = H::MINIMUM_LENGTH;
#[inline]
fn packet_length(&self) -> usize {
H::packet_length(self)
}
}
impl<T: HeaderLen> HeaderLen for Vec<T> {
const MINIMUM_LENGTH: usize = 0;
#[inline]
fn packet_length(&self) -> usize {
self.iter().map(|v| v.packet_length()).sum()
}
}
impl<T: HeaderLen> HeaderLen for Option<T> {
const MINIMUM_LENGTH: usize = 0;
#[inline]
fn packet_length(&self) -> usize {
self.as_ref().map(|v| v.packet_length()).unwrap_or_default()
}
}
impl HeaderLen for Vec<u8> {
const MINIMUM_LENGTH: usize = 0;
#[inline]
fn packet_length(&self) -> usize {
self.len()
}
}
pub trait HasView<B> {
type ViewType;
}
pub trait HasRepr {
type ReprType;
}
impl<T: HasView<B>, B> HasView<B> for Option<T> {
type ViewType = T;
}
impl<T: HasRepr> HasRepr for Option<T> {
type ReprType = T;
}
pub trait HeaderParse<B: SplitByteSlice>: NextLayer + Sized {
fn parse(from: B) -> ParseResult<Success<Self, B>> {
Self::parse_choice(from, None)
}
fn parse_choice(
data: B,
hint: Option<Self::Hint>,
) -> ParseResult<Success<Self, B>>;
}
pub trait Read {
type Chunk: SplitByteSlice;
fn next_chunk(&mut self) -> ParseResult<Self::Chunk>;
fn chunks_len(&self) -> usize;
fn is_empty(&self) -> bool {
self.chunks_len() == 0
}
}
#[cfg(feature = "alloc")]
impl<'a> Read for alloc::collections::linked_list::Iter<'a, Vec<u8>> {
type Chunk = &'a [u8];
#[inline]
fn next_chunk(&mut self) -> ParseResult<Self::Chunk> {
self.next().ok_or(ParseError::TooSmall).map(|v| v.as_ref())
}
#[inline]
fn chunks_len(&self) -> usize {
ExactSizeIterator::len(self)
}
}
#[cfg(feature = "alloc")]
impl<'a> Read for alloc::collections::linked_list::IterMut<'a, Vec<u8>> {
type Chunk = &'a mut [u8];
#[inline]
fn next_chunk(&mut self) -> ParseResult<Self::Chunk> {
self.next().ok_or(ParseError::TooSmall).map(|v| v.as_mut())
}
#[inline]
fn chunks_len(&self) -> usize {
ExactSizeIterator::len(self)
}
}
impl HeaderLen for &[u8] {
const MINIMUM_LENGTH: usize = 0;
#[inline]
fn packet_length(&self) -> usize {
self.len()
}
}
pub type Success<T, B> = (T, Option<<T as NextLayer>::Denom>, B);
pub trait NextLayer {
type Denom: Copy + Eq;
type Hint: Copy + Eq;
#[inline]
fn next_layer(&self) -> Option<Self::Denom> {
self.next_layer_choice(None)
}
#[inline]
fn next_layer_choice(
&self,
_hint: Option<Self::Hint>,
) -> Option<Self::Denom> {
None
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
pub enum ParseControl {
Continue,
Accept,
Reject,
}
pub trait NetworkRepr<U: Copy> {
fn to_network(self) -> U;
fn from_network(val: U) -> Self;
}
impl NetworkRepr<[u8; 6]> for macaddr::MacAddr6 {
#[inline]
fn to_network(self) -> [u8; 6] {
self.into_array()
}
#[inline]
fn from_network(val: [u8; 6]) -> Self {
macaddr::MacAddr6::from(val)
}
}
pub struct Parsed<Stack, RawPkt: Read> {
pub headers: Stack,
pub last_chunk: Option<RawPkt::Chunk>,
pub data: RawPkt,
}
pub unsafe trait IntoBufPointer<'a>: IntoByteSlice<'a> {
unsafe fn into_buf_ptr(self) -> *mut u8;
}
unsafe impl<'a> IntoBufPointer<'a> for &'a [u8] {
#[inline(always)]
unsafe fn into_buf_ptr(self) -> *mut u8 {
self.into_byte_slice().as_ptr() as *mut _
}
}
unsafe impl<'a> IntoBufPointer<'a> for &'a mut [u8] {
#[inline(always)]
unsafe fn into_buf_ptr(self) -> *mut u8 {
self.into_byte_slice_mut().as_mut_ptr()
}
}
#[cfg(feature = "alloc")]
#[doc(hidden)]
#[macro_export]
macro_rules! __cfg_alloc {
( $( $tok:tt )* ) => { $( $tok )* }
}
#[cfg(not(feature = "alloc"))]
#[doc(hidden)]
#[macro_export]
macro_rules! __cfg_alloc {
( $( $tok:tt )* ) => {};
}
#[doc(hidden)]
pub const fn min(a: usize, b: usize) -> usize {
if a < b {
a
} else {
b
}
}