use std::{
ffi::CString,
net::{Ipv4Addr, SocketAddrV4},
};
use enet_sys::ENetAddress;
use crate::Error;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Address {
addr: SocketAddrV4,
}
impl Address {
pub fn new(addr: Ipv4Addr, port: u16) -> Address {
Address {
addr: SocketAddrV4::new(addr, port),
}
}
pub fn from_hostname(hostname: &CString, port: u16) -> Result<Address, Error> {
use enet_sys::enet_address_set_host;
let mut addr = ENetAddress { host: 0, port };
let res =
unsafe { enet_address_set_host(&mut addr as *mut ENetAddress, hostname.as_ptr()) };
if res != 0 {
return Err(Error(res));
}
Ok(Self::from_enet_address(&addr))
}
pub fn ip(&self) -> &Ipv4Addr {
self.addr.ip()
}
pub fn port(&self) -> u16 {
self.addr.port()
}
pub(crate) fn to_enet_address(&self) -> ENetAddress {
ENetAddress {
host: u32::from_ne_bytes(self.ip().octets()),
port: self.port(),
}
}
pub(crate) fn from_enet_address(addr: &ENetAddress) -> Address {
Address::new(Ipv4Addr::from(addr.host.to_ne_bytes()), addr.port)
}
}
impl From<SocketAddrV4> for Address {
fn from(addr: SocketAddrV4) -> Address {
Address { addr }
}
}
#[cfg(test)]
mod tests {
use std::{ffi::CString, net::Ipv4Addr};
use super::Address;
#[test]
fn test_from_valid_hostname() {
let addr = Address::from_hostname(&CString::new("localhost").unwrap(), 0).unwrap();
assert_eq!(addr.addr.ip(), &Ipv4Addr::new(127, 0, 0, 1));
assert_eq!(addr.addr.port(), 0);
}
#[test]
fn test_from_invalid_hostname() {
assert!(Address::from_hostname(&CString::new("").unwrap(), 0).is_err());
}
}