diff --git a/src/caa.rs b/src/caa.rs index 88aa05627..ec6162102 100644 --- a/src/caa.rs +++ b/src/caa.rs @@ -1,4 +1,3 @@ -use std::ffi::CStr; use std::marker::PhantomData; use std::os::raw::{c_int, c_uchar, c_void}; use std::{fmt, ptr, slice, str}; @@ -7,6 +6,7 @@ use itertools::Itertools; use crate::error::{Error, Result}; use crate::panic; +use crate::utils::c_string_as_str_checked; /// The result of a successful CAA lookup. #[derive(Debug)] @@ -104,8 +104,7 @@ impl<'a> CAAResult<'a> { /// The property represented by this `CAAResult`. pub fn property(self) -> &'a str { - let c_str = unsafe { CStr::from_ptr(self.caa_reply.property.cast()) }; - c_str.to_str().unwrap() + unsafe { c_string_as_str_checked(self.caa_reply.property.cast()) } } /// The value represented by this `CAAResult`. diff --git a/src/channel.rs b/src/channel.rs index fefe62d08..aa2eacb3f 100644 --- a/src/channel.rs +++ b/src/channel.rs @@ -1,5 +1,4 @@ -#[allow(unused_imports)] -use std::ffi::{CStr, CString}; +use std::ffi::CString; use std::marker::PhantomData; use std::mem; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; @@ -30,8 +29,10 @@ use crate::string::AresString; use crate::txt::{query_txt_callback, TXTResults}; use crate::types::{AddressFamily, DnsClass, QueryType, Socket}; use crate::uri::{query_uri_callback, URIResults}; +#[allow(unused_imports)] use crate::utils::{ - ipv4_as_in_addr, ipv6_as_in6_addr, socket_addrv4_as_sockaddr_in, socket_addrv6_as_sockaddr_in6, + c_string_as_str_unchecked, ipv4_as_in_addr, ipv6_as_in6_addr, socket_addrv4_as_sockaddr_in, + socket_addrv6_as_sockaddr_in6, }; use crate::Flags; #[cfg(cares1_29)] @@ -1160,8 +1161,7 @@ unsafe extern "C" fn server_state_callback( F: FnMut(&str, bool, ServerStateFlags) + Send + 'static, { let handler = data.cast::(); - let c_str = CStr::from_ptr(server_string); - let server = c_str.to_str().unwrap(); + let server = c_string_as_str_unchecked(server_string); panic::catch(|| { (*handler)( server, diff --git a/src/error.rs b/src/error.rs index 0af2c8a39..eb2fb164e 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,9 +1,9 @@ use std::error; -use std::ffi::CStr; use std::fmt; use std::os::raw::c_int; use std::result; -use std::str; + +use crate::utils::c_string_as_str_unchecked; /// Error codes that the library might return. #[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)] @@ -96,8 +96,7 @@ impl fmt::Display for Error { fn fmt(&self, fmt: &mut fmt::Formatter) -> result::Result<(), fmt::Error> { let text = unsafe { let ptr = c_ares_sys::ares_strerror(*self as c_int); - let buf = CStr::from_ptr(ptr).to_bytes(); - str::from_utf8_unchecked(buf) + c_string_as_str_unchecked(ptr) }; fmt.write_str(text) } diff --git a/src/hostent.rs b/src/hostent.rs index b7c6f27e7..420117463 100644 --- a/src/hostent.rs +++ b/src/hostent.rs @@ -1,4 +1,3 @@ -use std::ffi::CStr; use std::marker::PhantomData; use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::os::raw::c_char; @@ -7,11 +6,10 @@ use std::{fmt, ptr, slice}; use itertools::Itertools; use crate::types::AddressFamily; -use crate::utils::address_family; +use crate::utils::{address_family, hostname_as_str}; fn hostname(hostent: &c_types::hostent) -> &str { - let c_str = unsafe { CStr::from_ptr(hostent.h_name.cast()) }; - c_str.to_str().unwrap() + unsafe { hostname_as_str(hostent.h_name.cast()) } } fn addresses(hostent: &c_types::hostent) -> HostAddressResultsIter { @@ -180,8 +178,7 @@ impl<'a> Iterator for HostAliasResultsIter<'a> { None } else { self.next = unsafe { &*ptr::from_ref(self.next).offset(1) }; - let c_str = unsafe { CStr::from_ptr(h_alias) }; - let string = c_str.to_str().unwrap(); + let string = unsafe { hostname_as_str(h_alias) }; Some(string) } } diff --git a/src/mx.rs b/src/mx.rs index 743e4072a..42c1d4453 100644 --- a/src/mx.rs +++ b/src/mx.rs @@ -1,4 +1,3 @@ -use std::ffi::CStr; use std::fmt; use std::marker::PhantomData; use std::os::raw::{c_int, c_uchar, c_void}; @@ -9,6 +8,7 @@ use itertools::Itertools; use crate::error::{Error, Result}; use crate::panic; +use crate::utils::hostname_as_str; /// The result of a successful MX lookup. #[derive(Debug)] @@ -100,8 +100,7 @@ unsafe impl<'a> Sync for MXResultsIter<'a> {} impl<'a> MXResult<'a> { /// Returns the hostname in this `MXResult`. pub fn host(self) -> &'a str { - let c_str = unsafe { CStr::from_ptr(self.mx_reply.host) }; - c_str.to_str().unwrap() + unsafe { hostname_as_str(self.mx_reply.host) } } /// Returns the priority from this `MXResult`. diff --git a/src/nameinfo.rs b/src/nameinfo.rs index ec34da027..6db96b8e3 100644 --- a/src/nameinfo.rs +++ b/src/nameinfo.rs @@ -1,9 +1,9 @@ -use std::ffi::CStr; -use std::fmt; use std::os::raw::{c_char, c_int, c_void}; +use std::{fmt, str}; use crate::error::{Error, Result}; use crate::panic; +use crate::utils::{c_string_as_str_unchecked, hostname_as_str}; /// The result of a successful name-info lookup. #[derive(Clone, Copy, Debug)] @@ -19,18 +19,13 @@ impl<'a> NameInfoResult<'a> { /// Returns the node from this `NameInfoResult`. pub fn node(&self) -> Option<&str> { - self.node.map(|string| { - let c_str = unsafe { CStr::from_ptr(string) }; - c_str.to_str().unwrap() - }) + self.node.map(|string| unsafe { hostname_as_str(string) }) } /// Returns the service from this `NameInfoResult`. pub fn service(&self) -> Option<&str> { - self.service.map(|string| { - let c_str = unsafe { CStr::from_ptr(string) }; - c_str.to_str().unwrap() - }) + self.service + .map(|string| unsafe { c_string_as_str_unchecked(string) }) } } diff --git a/src/naptr.rs b/src/naptr.rs index 42c12294d..b8591fb86 100644 --- a/src/naptr.rs +++ b/src/naptr.rs @@ -1,4 +1,3 @@ -use std::ffi::CStr; use std::fmt; use std::marker::PhantomData; use std::os::raw::{c_int, c_uchar, c_void}; @@ -9,6 +8,7 @@ use itertools::Itertools; use crate::error::{Error, Result}; use crate::panic; +use crate::utils::{c_string_as_str_checked, hostname_as_str}; /// The result of a successful NAPTR lookup. #[derive(Debug)] @@ -100,26 +100,22 @@ unsafe impl<'a> Sync for NAPTRResultsIter<'a> {} impl<'a> NAPTRResult<'a> { /// Returns the flags in this `NAPTRResult`. pub fn flags(self) -> &'a str { - let c_str = unsafe { CStr::from_ptr(self.naptr_reply.flags.cast()) }; - c_str.to_str().unwrap() + unsafe { c_string_as_str_checked(self.naptr_reply.flags.cast()) } } /// Returns the service name in this `NAPTRResult`. pub fn service_name(self) -> &'a str { - let c_str = unsafe { CStr::from_ptr(self.naptr_reply.service.cast()) }; - c_str.to_str().unwrap() + unsafe { c_string_as_str_checked(self.naptr_reply.service.cast()) } } /// Returns the regular expression in this `NAPTRResult`. pub fn reg_exp(self) -> &'a str { - let c_str = unsafe { CStr::from_ptr(self.naptr_reply.regexp.cast()) }; - c_str.to_str().unwrap() + unsafe { c_string_as_str_checked(self.naptr_reply.regexp.cast()) } } /// Returns the replacement pattern in this `NAPTRResult`. pub fn replacement_pattern(self) -> &'a str { - let c_str = unsafe { CStr::from_ptr(self.naptr_reply.replacement) }; - c_str.to_str().unwrap() + unsafe { hostname_as_str(self.naptr_reply.replacement) } } /// Returns the order value in this `NAPTRResult`. diff --git a/src/soa.rs b/src/soa.rs index 6abb7df02..8e321ec51 100644 --- a/src/soa.rs +++ b/src/soa.rs @@ -1,4 +1,3 @@ -use std::ffi::CStr; use std::fmt; use std::marker::PhantomData; use std::os::raw::{c_int, c_uchar, c_void}; @@ -7,6 +6,7 @@ use std::slice; use crate::error::{Error, Result}; use crate::panic; +use crate::utils::hostname_as_str; /// The result of a successful SOA lookup. #[derive(Debug)] @@ -39,14 +39,12 @@ impl SOAResult { /// Returns the name server from this `SOAResult`. pub fn name_server(&self) -> &str { - let c_str = unsafe { CStr::from_ptr((*self.soa_reply).nsname) }; - c_str.to_str().unwrap() + unsafe { hostname_as_str((*self.soa_reply).nsname) } } /// Returns the hostmaster from this `SOAResult`. pub fn hostmaster(&self) -> &str { - let c_str = unsafe { CStr::from_ptr((*self.soa_reply).hostmaster) }; - c_str.to_str().unwrap() + unsafe { hostname_as_str((*self.soa_reply).hostmaster) } } /// Returns the serial number from this `SOAResult`. diff --git a/src/srv.rs b/src/srv.rs index 155cf006a..3e4b60581 100644 --- a/src/srv.rs +++ b/src/srv.rs @@ -1,4 +1,3 @@ -use std::ffi::CStr; use std::fmt; use std::marker::PhantomData; use std::os::raw::{c_int, c_uchar, c_void}; @@ -9,6 +8,7 @@ use itertools::Itertools; use crate::error::{Error, Result}; use crate::panic; +use crate::utils::hostname_as_str; /// The result of a successful SRV lookup. #[derive(Debug)] @@ -101,8 +101,7 @@ unsafe impl<'a> Sync for SRVResultsIter<'a> {} impl<'a> SRVResult<'a> { /// Returns the hostname in this `SRVResult`. pub fn host(self) -> &'a str { - let c_str = unsafe { CStr::from_ptr(self.srv_reply.host) }; - c_str.to_str().unwrap() + unsafe { hostname_as_str(self.srv_reply.host) } } /// Returns the weight in this `SRVResult`. diff --git a/src/string.rs b/src/string.rs index 14de76230..7471d3e2b 100644 --- a/src/string.rs +++ b/src/string.rs @@ -1,6 +1,8 @@ -use std::ffi::CStr; use std::ops::Deref; use std::os::raw::c_char; +use std::str; + +use crate::utils::c_string_as_str_unchecked; /// A smart pointer wrapping a string as allocated by c-ares. pub struct AresString { @@ -11,8 +13,7 @@ pub struct AresString { impl AresString { #[allow(dead_code)] pub(crate) fn new(ares_string: *mut c_char) -> Self { - let c_str = unsafe { CStr::from_ptr(ares_string) }; - let rust_str = c_str.to_str().unwrap(); + let rust_str = unsafe { c_string_as_str_unchecked(ares_string) }; AresString { ares_string, rust_str, diff --git a/src/uri.rs b/src/uri.rs index d1a52ca74..96521408d 100644 --- a/src/uri.rs +++ b/src/uri.rs @@ -1,4 +1,3 @@ -use std::ffi::CStr; use std::fmt; use std::marker::PhantomData; use std::os::raw::{c_int, c_uchar, c_void}; @@ -9,6 +8,7 @@ use itertools::Itertools; use crate::error::{Error, Result}; use crate::panic; +use crate::utils::c_string_as_str_checked; /// The result of a successful URI lookup. #[derive(Debug)] @@ -111,8 +111,7 @@ impl<'a> URIResult<'a> { /// Returns the uri in this `URIResult`. pub fn uri(self) -> &'a str { - let c_str = unsafe { CStr::from_ptr(self.uri_reply.uri) }; - c_str.to_str().unwrap() + unsafe { c_string_as_str_checked(self.uri_reply.uri) } } /// Returns the time-to-live in this `URIResult`. diff --git a/src/utils.rs b/src/utils.rs index 494ffa5c1..0a77c1781 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,5 +1,5 @@ use crate::types::AddressFamily; -use std::ffi::CStr; +use std::ffi::{c_char, CStr}; use std::mem; use std::net::{Ipv4Addr, Ipv6Addr, SocketAddrV4, SocketAddrV6}; use std::os::raw::c_int; @@ -155,6 +155,26 @@ pub fn socket_addrv6_as_sockaddr_in6(sock_v6: &SocketAddrV6) -> c_types::sockadd sockaddr_in6 } +pub unsafe fn c_string_as_str_unchecked<'a>(c_str: *const c_char) -> &'a str { + let bytes = CStr::from_ptr(c_str).to_bytes(); + str::from_utf8_unchecked(bytes) +} + +pub unsafe fn c_string_as_str_checked<'a>(c_str: *const c_char) -> &'a str { + let c_str = CStr::from_ptr(c_str); + c_str.to_str().unwrap() +} + +#[cfg(not(cares1_17_2))] +pub unsafe fn hostname_as_str<'a>(hostname: *const c_char) -> &'a str { + c_string_as_str_checked(hostname) +} + +#[cfg(cares1_17_2)] +pub unsafe fn hostname_as_str<'a>(hostname: *const c_char) -> &'a str { + c_string_as_str_unchecked(hostname) +} + /// Get the version number of the underlying `c-ares` library. /// /// The version is returned as both a string and an integer. The integer is built up as 24bit @@ -164,8 +184,7 @@ pub fn version() -> (&'static str, u32) { let mut int_version: c_int = 0; let str_version = unsafe { let ptr = c_ares_sys::ares_version(&mut int_version); - let buf = CStr::from_ptr(ptr).to_bytes(); - str::from_utf8_unchecked(buf) + c_string_as_str_unchecked(ptr) }; (str_version, int_version as u32) }