1 // Take a look at the license at the top of the repository in the LICENSE file. 2 3 use crate::prelude::*; 4 use crate::InetAddress; 5 use crate::SocketFamily; 6 use glib::object::IsA; 7 use glib::translate::*; 8 9 use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; 10 11 #[derive(Debug)] 12 pub enum InetAddressBytes<'a> { 13 V4(&'a [u8; 4]), 14 V6(&'a [u8; 16]), 15 } 16 17 impl<'a> InetAddressBytes<'a> { deref(&self) -> &[u8]18 fn deref(&self) -> &[u8] { 19 use self::InetAddressBytes::*; 20 21 match *self { 22 V4(bytes) => bytes, 23 V6(bytes) => bytes, 24 } 25 } 26 } 27 28 impl InetAddress { 29 #[doc(alias = "g_inet_address_new_from_bytes")] from_bytes(inet_address_bytes: InetAddressBytes) -> Self30 pub fn from_bytes(inet_address_bytes: InetAddressBytes) -> Self { 31 let bytes = inet_address_bytes.deref(); 32 33 let family = match inet_address_bytes { 34 InetAddressBytes::V4(_) => SocketFamily::Ipv4, 35 InetAddressBytes::V6(_) => SocketFamily::Ipv6, 36 }; 37 unsafe { 38 from_glib_full(ffi::g_inet_address_new_from_bytes( 39 bytes.to_glib_none().0, 40 family.into_glib(), 41 )) 42 } 43 } 44 } 45 46 pub trait InetAddressExtManual { 47 #[doc(alias = "g_inet_address_to_bytes")] to_bytes(&self) -> Option<InetAddressBytes<'_>>48 fn to_bytes(&self) -> Option<InetAddressBytes<'_>>; 49 } 50 51 impl<O: IsA<InetAddress>> InetAddressExtManual for O { 52 // rustdoc-stripper-ignore-next 53 /// Returns `None` in case the address has a native size different than 4 and 16. 54 #[doc(alias = "g_inet_address_to_bytes")] to_bytes(&self) -> Option<InetAddressBytes<'_>>55 fn to_bytes(&self) -> Option<InetAddressBytes<'_>> { 56 let size = self.native_size(); 57 unsafe { 58 let bytes = ffi::g_inet_address_to_bytes(self.as_ref().to_glib_none().0); 59 if size == 4 { 60 Some(InetAddressBytes::V4(&*(bytes as *const [u8; 4]))) 61 } else if size == 16 { 62 Some(InetAddressBytes::V6(&*(bytes as *const [u8; 16]))) 63 } else { 64 None 65 } 66 } 67 } 68 } 69 70 impl From<IpAddr> for InetAddress { from(addr: IpAddr) -> Self71 fn from(addr: IpAddr) -> Self { 72 match addr { 73 IpAddr::V4(v4) => Self::from_bytes(InetAddressBytes::V4(&v4.octets())), 74 IpAddr::V6(v6) => Self::from_bytes(InetAddressBytes::V6(&v6.octets())), 75 } 76 } 77 } 78 79 impl From<InetAddress> for IpAddr { from(addr: InetAddress) -> Self80 fn from(addr: InetAddress) -> Self { 81 let size = addr.native_size(); 82 unsafe { 83 let bytes = ffi::g_inet_address_to_bytes(addr.to_glib_none().0); 84 if size == 4 { 85 Self::V4(Ipv4Addr::from(*(bytes as *const [u8; 4]))) 86 } else if size == 16 { 87 Self::V6(Ipv6Addr::from(*(bytes as *const [u16; 8]))) 88 } else { 89 panic!("Unknown IP kind"); 90 } 91 } 92 } 93 } 94