vt-muxer 0.1.0

Mux one TCP stream into many
Documentation
use std::fmt::{Debug, Display, Formatter};
use std::hash::{Hash, Hasher};
use std::net::Ipv6Addr;
use std::str::FromStr;
use bytemuck::{Pod, Zeroable};
use crate::integers::NetworkOrderU16;

#[derive(Copy, Clone, Pod, Zeroable, Ord, PartialOrd, Eq, PartialEq)]
#[repr(C, packed)]
pub struct IpAddr {
    octets: [u8; 16]
}

impl IpAddr {
    pub const fn to_std(self) -> std::net::IpAddr {
        Ipv6Addr::from_bits(u128::from_be_bytes(self.octets)).to_canonical()
    }

    pub const fn from_std(ip: std::net::IpAddr) -> Self {
        let v6 = match ip {
            std::net::IpAddr::V4(v4) => v4.to_ipv6_mapped(),
            std::net::IpAddr::V6(v6) => v6,
        };

        Self { octets: v6.octets() }
    }
}


#[derive(Copy, Clone, Pod, Zeroable, Ord, PartialOrd, Eq, PartialEq)]
#[repr(C, packed)]
pub struct SocketAddr {
    ip: IpAddr,
    port: NetworkOrderU16
}

impl SocketAddr {
    pub const fn to_std(self) -> std::net::SocketAddr {
        std::net::SocketAddr::new(
            self.ip.to_std(),
            self.port.get()
        )
    }

    pub const fn from_std(sock: std::net::SocketAddr) -> Self {
        Self {
            ip: IpAddr::from_std(sock.ip()),
            port: NetworkOrderU16::new(sock.port())
        }
    }

    pub const fn ip(&self) -> IpAddr {
        self.ip
    }

    pub const fn port(&self) -> u16 {
        self.port.get()
    }
}

macro_rules! impl_display_debug {
    ($($type:ty),+) => {$(
        impl Display for $type {
            fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
                Display::fmt(&self.to_std(), f)
            }
        }
        
        impl Debug for $type {
            fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
                Debug::fmt(&self.to_std(), f)
            }
        }
    )+};
}

impl_display_debug!(IpAddr, SocketAddr);

macro_rules! impl_byte_hash {
    ($($type:ty),+) => {$(
        impl Hash for $type {
            fn hash<H: Hasher>(&self, state: &mut H) {
                state.write(bytemuck::bytes_of(self))
            }
        
            fn hash_slice<H: Hasher>(data: &[Self], state: &mut H)
            where
                Self: Sized,
            {
                state.write(bytemuck::cast_slice(data))
            }
        }
    )+};
}

impl_byte_hash!(IpAddr, SocketAddr);

macro_rules! impl_from_str {
    ($($ty:ident),+) => {$(
        impl FromStr for $ty {
            type Err = <std::net::$ty as FromStr>::Err;
            
            fn from_str(s: &str) -> Result<Self, Self::Err> {
                s.parse().map(Self::from_std)
            }
        }
    )*};
}

impl_from_str!(IpAddr, SocketAddr);