use std::{ffi::CStr, fmt, str::FromStr};
use crate::{
bindings::{
ip4_header_t, ip6_address_t, ip6_header_t, vlib_helper_format_ip4_header,
vlib_helper_format_ip6_header, vlib_helper_format_vnet_sw_if_index_name,
vlib_helper_unformat_vnet_sw_interface, vnet_get_main,
},
vppinfra,
};
impl ip6_address_t {
pub const fn new() -> Self {
Self { as_u8: [0; 16] }
}
}
impl ip6_header_t {
pub const fn new() -> Self {
Self {
ip_version_traffic_class_and_flow_label: 0,
payload_length: 0,
protocol: 0,
hop_limit: 0,
src_address: ip6_address_t::new(),
dst_address: ip6_address_t::new(),
}
}
}
impl fmt::Debug for ip6_header_t {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<Self as fmt::Display>::fmt(self, f)
}
}
impl fmt::Display for ip6_header_t {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
unsafe {
let s = vppinfra::vec::Vec::from_raw(vlib_helper_format_ip6_header(
std::ptr::null_mut(),
self,
std::mem::size_of::<Self>(),
));
let cstr = CStr::from_bytes_with_nul_unchecked(&s);
write!(f, "{}", cstr.to_string_lossy())
}
}
}
impl Clone for ip6_header_t {
fn clone(&self) -> Self {
unsafe {
Self {
ip_version_traffic_class_and_flow_label: std::ptr::read_unaligned(
std::ptr::addr_of!(self.ip_version_traffic_class_and_flow_label),
),
payload_length: std::ptr::read_unaligned(std::ptr::addr_of!(self.payload_length)),
protocol: self.protocol,
hop_limit: self.hop_limit,
src_address: self.src_address,
dst_address: self.dst_address,
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SwIfIndex(u32);
impl SwIfIndex {
pub const LOCAL0: Self = SwIfIndex::new(0);
pub const fn new(sw_if_index: u32) -> Self {
Self(sw_if_index)
}
}
impl fmt::Display for SwIfIndex {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
unsafe {
let s = vppinfra::vec::Vec::from_raw(vlib_helper_format_vnet_sw_if_index_name(
std::ptr::null_mut(),
vnet_get_main(),
self.0,
));
let cstr = CStr::from_bytes_with_nul_unchecked(&s);
write!(f, "{}", cstr.to_string_lossy())
}
}
}
impl From<u32> for SwIfIndex {
fn from(value: u32) -> Self {
Self(value)
}
}
impl From<SwIfIndex> for u32 {
fn from(value: SwIfIndex) -> Self {
value.0
}
}
impl FromStr for SwIfIndex {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut i = vppinfra::unformat::UnformatInput::from(s);
let mut sw_if_index = 0;
let ret = unsafe {
vlib_helper_unformat_vnet_sw_interface(i.as_ptr(), vnet_get_main(), &mut sw_if_index)
};
if ret > 0 {
Ok(Self(sw_if_index))
} else {
Err(())
}
}
}
impl fmt::Debug for ip4_header_t {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<Self as fmt::Display>::fmt(self, f)
}
}
impl fmt::Display for ip4_header_t {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
unsafe {
let s = vppinfra::vec::Vec::from_raw(vlib_helper_format_ip4_header(
std::ptr::null_mut(),
self,
std::mem::size_of::<Self>(),
));
let cstr = CStr::from_bytes_with_nul_unchecked(&s);
write!(f, "{}", cstr.to_string_lossy())
}
}
}