cross_platform_tun 0.1.5

cross platform tun device implement
Documentation
use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4};

use crate::error::{Error, Result};

pub trait IntoIpv4Addr {
    fn into_ipv4(&self) -> Result<Ipv4Addr>;
}

impl IntoIpv4Addr for u32 {
    fn into_ipv4(&self) -> Result<Ipv4Addr> {
        Ok(Ipv4Addr::from(*self))
    }
}

impl IntoIpv4Addr for i32 {
    fn into_ipv4(&self) -> Result<Ipv4Addr> {
        Ok(Ipv4Addr::from(*self as u32))
    }
}

impl IntoIpv4Addr for (u8, u8, u8, u8) {
    fn into_ipv4(&self) -> Result<Ipv4Addr> {
        Ok(Ipv4Addr::new(self.0, self.1, self.2, self.3))
    }
}

impl IntoIpv4Addr for str {
    fn into_ipv4(&self) -> Result<Ipv4Addr> {
        self.parse().map_err(|_| Error::InvalidAddress)
    }
}

impl IntoIpv4Addr for &str {
    fn into_ipv4(&self) -> Result<Ipv4Addr> {
        (*self).into_ipv4()
    }
}

impl IntoIpv4Addr for String {
    fn into_ipv4(&self) -> Result<Ipv4Addr> {
        self.as_str().into_ipv4()
    }
}

impl IntoIpv4Addr for &String {
    fn into_ipv4(&self) -> Result<Ipv4Addr> {
        (**self).into_ipv4()
    }
}

impl IntoIpv4Addr for Ipv4Addr {
    fn into_ipv4(&self) -> Result<Ipv4Addr> {
        Ok(*self)
    }
}

impl IntoIpv4Addr for &Ipv4Addr {
    fn into_ipv4(&self) -> Result<Ipv4Addr> {
        Ok(**self)
    }
}

impl IntoIpv4Addr for IpAddr {
    fn into_ipv4(&self) -> Result<Ipv4Addr> {
        match self {
            IpAddr::V4(addr) => Ok(*addr),
            _ => Err(Error::InvalidAddress),
        }
    }
}

impl IntoIpv4Addr for &IpAddr {
    fn into_ipv4(&self) -> Result<Ipv4Addr> {
        (*self).into_ipv4()
    }
}

impl IntoIpv4Addr for SocketAddrV4 {
    fn into_ipv4(&self) -> Result<Ipv4Addr> {
        self.ip().into_ipv4()
    }
}

impl IntoIpv4Addr for &SocketAddrV4 {
    fn into_ipv4(&self) -> Result<Ipv4Addr> {
        (*self).into_ipv4()
    }
}

impl IntoIpv4Addr for SocketAddr {
    fn into_ipv4(&self) -> Result<Ipv4Addr> {
        match self {
            SocketAddr::V4(addr) => addr.into_ipv4(),
            _ => Err(Error::InvalidAddress),
        }
    }
}

pub trait Ipv4AddrExt {
    fn to_sockaddr(&self) -> libc::sockaddr;
    fn from_sockaddr(sock: libc::sockaddr) -> Self;
}

pub trait SockAddrExt<T> {
    fn into_ipv4addr(self) -> T;
}

impl<T> SockAddrExt<T> for libc::sockaddr
where
    T: Ipv4AddrExt,
{
    fn into_ipv4addr(self) -> T {
        T::from_sockaddr(self)
    }
}

impl Ipv4AddrExt for Ipv4Addr {
    fn to_sockaddr(&self) -> libc::sockaddr {
        let mut addr: libc::sockaddr_in = unsafe { std::mem::zeroed() };
        addr.sin_family = libc::AF_INET as _;
        // addr.sin_port = 0;
        addr.sin_addr = libc::in_addr {
            s_addr: u32::from_ne_bytes(self.octets()),
        };
        unsafe { std::mem::transmute(addr) }
    }

    fn from_sockaddr(addr: libc::sockaddr) -> Self {
        let addr: libc::sockaddr_in = unsafe { std::mem::transmute(addr) };
        // network byte order to host byte order
        addr.sin_addr.s_addr.to_ne_bytes().into()
    }
}