use alloc::boxed::Box;
use anyhow::Result;
use core::{fmt, pin::Pin};
use futures::{AsyncRead, AsyncWrite};
pub trait Socket: AsyncRead + AsyncWrite + 'static {
fn connect(address: SocketAddr) -> Result<Pin<Box<dyn Socket + Send>>>
where
Self: Sized;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Ipv4Addr(pub [u16; 4]);
impl Ipv4Addr {
pub const fn new(a: u8, b: u8, c: u8, d: u8) -> Self {
Self([a as u16, b as u16, c as u16, d as u16])
}
pub const fn octets(&self) -> [u8; 4] {
[
self.0[0] as u8,
self.0[1] as u8,
self.0[2] as u8,
self.0[3] as u8,
]
}
pub fn from_bytes(bytes: [u8; 4]) -> Self {
Self([
bytes[0] as u16,
bytes[1] as u16,
bytes[2] as u16,
bytes[3] as u16,
])
}
}
impl fmt::Display for Ipv4Addr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let octets = self.octets();
write!(f, "{}.{}.{}.{}", octets[0], octets[1], octets[2], octets[3])
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Ipv6Addr(pub [u16; 8]);
impl Ipv6Addr {
pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Self {
Self([a, b, c, d, e, f, g, h])
}
pub const fn segments(&self) -> [u16; 8] {
self.0
}
pub fn octets(&self) -> [u8; 16] {
let mut octets = [0u8; 16];
for (i, &segment) in self.0.iter().enumerate() {
octets[i * 2] = (segment >> 8) as u8;
octets[i * 2 + 1] = (segment & 0xff) as u8;
}
octets
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum IpAddr {
V4(Ipv4Addr),
V6(Ipv6Addr),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SocketAddr {
ip: IpAddr,
port: u16,
}
impl SocketAddr {
pub const fn new(ip: IpAddr, port: u16) -> Self {
Self { ip, port }
}
pub const fn v4(ip: Ipv4Addr, port: u16) -> Self {
Self {
ip: IpAddr::V4(ip),
port,
}
}
pub const fn v6(ip: Ipv6Addr, port: u16) -> Self {
Self {
ip: IpAddr::V6(ip),
port,
}
}
pub const fn ip(&self) -> IpAddr {
self.ip
}
pub const fn port(&self) -> u16 {
self.port
}
}