etherip-xdp 0.3.1

EtherIP implementation using XDP for Linux, in Rust.
Documentation
use std::fmt::Debug;

#[allow(dead_code)]
pub fn index_to_name(index: InterfaceId) -> Result<String, std::io::Error> {
    let index = if let Some(index) = index.inner() {
        index
    } else {
        return Err(std::io::Error::new(
            std::io::ErrorKind::InvalidInput,
            "interface index is unspecified",
        ));
    };
    let ifname_buf = [0u8; libc::IFNAMSIZ];
    let ret = unsafe { libc::if_indextoname(index, ifname_buf.as_ptr() as *mut libc::c_char) };
    if ret.is_null() {
        return Err(std::io::Error::last_os_error());
    }

    let name = unsafe { std::ffi::CStr::from_ptr(ret) }
        .to_str()
        .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?
        .to_owned();
    Ok(name)
}

pub fn name_to_index(name: &str) -> Result<InterfaceId, std::io::Error> {
    let name = std::ffi::CString::new(name)
        .map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e))?;
    let index = unsafe { libc::if_nametoindex(name.as_ptr() as *const libc::c_char) };
    if index == 0 {
        return Err(std::io::Error::last_os_error());
    }
    Ok(InterfaceId::new(index))
}

#[derive(Debug, Clone, Copy, PartialEq, Hash, Eq)]
pub struct InterfaceId {
    if_index: libc::c_uint,
}

#[allow(dead_code)]
impl InterfaceId {
    pub const UNSPECIFIED: Self = Self { if_index: 0 };

    pub(crate) fn new(if_index: libc::c_uint) -> Self {
        Self { if_index }
    }

    pub(crate) fn inner_unchecked(&self) -> libc::c_uint {
        self.if_index
    }

    pub(crate) fn inner(&self) -> Option<libc::c_uint> {
        if self.if_index == 0 {
            None
        } else {
            Some(self.if_index)
        }
    }

    pub fn is_unspecified(&self) -> bool {
        self.if_index == 0
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct Interface {
    pub if_id: InterfaceId,
    pub if_name: String,
}