cassandra_cpp/cassandra/
inet.rs1use crate::cassandra::error::*;
2use crate::cassandra::util::{Protected, ProtectedInner};
3use crate::cassandra_sys::cass_inet_from_string_n;
4use crate::cassandra_sys::cass_inet_init_v4;
5use crate::cassandra_sys::cass_inet_init_v6;
6use crate::cassandra_sys::cass_inet_string;
7use crate::cassandra_sys::CassInet as _Inet;
8use std::default::Default;
9use std::ffi::CStr;
10use std::fmt;
11use std::fmt::{Debug, Formatter};
12
13use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
14use std::os::raw::c_char;
15use std::str::FromStr;
16use std::string::ToString;
17
18#[repr(C)]
19#[derive(Copy, Clone)]
21pub struct Inet(_Inet);
22
23impl Debug for Inet {
24 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
25 write!(f, "{}", self.to_string())
26 }
27}
28
29impl PartialEq for Inet {
30 fn eq(&self, other: &Inet) -> bool {
31 if self.0.address_length != other.0.address_length {
32 return false;
33 }
34 let length = self.0.address_length as usize;
35 self.0.address[0..length] == other.0.address[0..length]
36 }
37}
38
39impl ProtectedInner<_Inet> for Inet {
40 fn inner(&self) -> _Inet {
41 self.0
42 }
43}
44
45impl Protected<_Inet> for Inet {
46 fn build(inner: _Inet) -> Self {
47 Inet(inner)
48 }
49}
50
51impl Default for Inet {
52 fn default() -> Inet {
53 Inet(_Inet {
54 address: [0; 16],
55 address_length: 4,
56 })
57 }
58}
59
60impl Inet {
61 pub fn cass_inet_init_v4(address: &Ipv4Addr) -> Inet {
63 unsafe { Inet(cass_inet_init_v4(address.octets().as_ptr())) }
64 }
65
66 pub fn cass_inet_init_v6(address: &Ipv6Addr) -> Inet {
68 unsafe { Inet(cass_inet_init_v6(address.octets().as_ptr())) }
69 }
70}
71
72impl<'a> From<&'a IpAddr> for Inet {
73 fn from(ip_addr: &IpAddr) -> Inet {
74 match *ip_addr {
75 IpAddr::V4(ref ipv4_addr) => Inet::cass_inet_init_v4(ipv4_addr),
76 IpAddr::V6(ref ipv6_addr) => Inet::cass_inet_init_v6(ipv6_addr),
77 }
78 }
79}
80
81impl FromStr for Inet {
90 type Err = Error;
91
92 fn from_str(s: &str) -> Result<Self> {
93 let s_ptr = s.as_ptr() as *const c_char;
94 let mut inet = _Inet {
95 address: [0; 16],
96 address_length: 0,
97 };
98 unsafe {
99 cass_inet_from_string_n(s_ptr, s.len(), &mut inet)
100 .to_result(())
101 .map(|_| Inet(inet))
102 }
103 }
104}
105
106impl ToString for Inet {
107 fn to_string(&self) -> String {
108 unsafe {
109 let mut inet_str = [0i8; cassandra_cpp_sys::CASS_INET_STRING_LENGTH as usize];
110 cass_inet_string(self.0, inet_str.as_mut_ptr() as *mut libc::c_char);
111 CStr::from_ptr(inet_str.as_ptr() as *const libc::c_char)
112 .to_string_lossy()
113 .into_owned()
114 }
115 }
116}
117
118impl<'a> From<&'a Inet> for IpAddr {
119 fn from(inet: &Inet) -> Self {
120 match inet.0.address_length {
121 4 => {
122 let mut octets = [0u8; 4];
123 octets.copy_from_slice(&inet.0.address[0..4]);
124 IpAddr::from(octets)
125 }
126 16 => IpAddr::from(inet.0.address),
127 unsupported => panic!("impossible inet type: {}", unsupported),
128 }
129 }
130}
131
132#[test]
133fn ipv4_conversion() {
134 let ipv4_in = Ipv4Addr::new(127, 0, 0, 1);
135 let inet = Inet::cass_inet_init_v4(&ipv4_in);
136 let ip_out = IpAddr::from(&inet);
137 assert_eq!(IpAddr::V4(ipv4_in), ip_out);
138}
139
140#[test]
141fn ipv6_conversion() {
142 let ipv6_in = Ipv6Addr::new(0x2001, 0x0db8, 0, 0, 0, 0, 0, 1);
143 let inet = Inet::cass_inet_init_v6(&ipv6_in);
144 let ip_out = IpAddr::from(&inet);
145 assert_eq!(IpAddr::V6(ipv6_in), ip_out);
146}
147
148#[test]
149fn ipv4_to_string() {
150 let ipv4_in = Ipv4Addr::new(127, 0, 0, 1);
151 let inet = Inet::cass_inet_init_v4(&ipv4_in);
152 assert_eq!("127.0.0.1", inet.to_string());
153}