diff --git a/.clippy.toml b/.clippy.toml index 80771c5..ef963dd 100644 --- a/.clippy.toml +++ b/.clippy.toml @@ -1 +1,3 @@ +allow-mixed-uninlined-format-args = false +allow-unwrap-in-tests = true doc-valid-idents = ["NetBSD", "OpenBSD", ".."] diff --git a/Cargo.toml b/Cargo.toml index 7b73217..3af5adc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,42 @@ windows-bindgen = { version = "0.58", default-features = false, features = ["met [features] gecko = ["dep:mozbuild"] +[lints.rust] +absolute_paths_not_starting_with_crate = "warn" +ambiguous_negative_literals = "warn" +closure_returning_async_block = "warn" +explicit_outlives_requirements = "warn" +macro_use_extern_crate = "warn" +missing_abi = "warn" +non_ascii_idents = "warn" +redundant_imports = "warn" +redundant_lifetimes = "warn" +trivial_numeric_casts = "warn" +unit_bindings = "warn" +unused_import_braces = "warn" +unused_lifetimes = "warn" +unused_macro_rules = "warn" +# unused_qualifications = "warn" # Try to re-enable when MSRV is > 1.76 + [lints.clippy] cargo = { level = "warn", priority = -1 } nursery = { level = "warn", priority = -1 } pedantic = { level = "warn", priority = -1 } +multiple_crate_versions = "allow" +cfg_not_test = "warn" +clone_on_ref_ptr = "warn" +create_dir = "warn" +if_then_some_else_none = "warn" +get_unwrap = "warn" +multiple_inherent_impl = "warn" +pathbuf_init_then_push = "warn" +redundant_type_annotations = "warn" +ref_patterns = "warn" +renamed_function_params = "warn" +semicolon_inside_block = "warn" +try_err = "warn" +unneeded_field_pattern = "warn" +unused_result_ok = "warn" +unused_trait_names = "warn" +unwrap_used = "warn" +unwrap_in_result = "warn" diff --git a/build.rs b/build.rs index 5a14cfd..de9d7c7 100644 --- a/build.rs +++ b/build.rs @@ -4,6 +4,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#![allow(clippy::unwrap_used)] // OK in build scripts. + const BINDINGS: &str = "bindings.rs"; #[cfg(feature = "gecko")] diff --git a/src/bsd.rs b/src/bsd.rs index 42445e8..43c9d1b 100644 --- a/src/bsd.rs +++ b/src/bsd.rs @@ -6,9 +6,8 @@ use std::{ ffi::CStr, - io::{Error, ErrorKind, Read, Result, Write}, + io::{Error, ErrorKind, Read as _, Result, Write as _}, marker::PhantomData, - mem::size_of, net::IpAddr, num::TryFromIntError, ops::Deref, @@ -43,13 +42,13 @@ use crate::{ }; #[cfg(apple)] -const ALIGN: usize = size_of::(); +const ALIGN: usize = std::mem::size_of::(); #[cfg(bsd)] // See https://github.com/freebsd/freebsd-src/blob/524a425d30fce3d5e47614db796046830b1f6a83/sys/net/route.h#L362-L371 // See https://github.com/NetBSD/src/blob/4b50954e98313db58d189dd87b4541929efccb09/sys/net/route.h#L329-L331 // See https://github.com/Arquivotheca/Solaris-8/blob/2ad1d32f9eeed787c5adb07eb32544276e2e2444/osnet_volume/usr/src/cmd/cmd-inet/usr.sbin/route.c#L238-L239 -const ALIGN: usize = size_of::(); +const ALIGN: usize = std::mem::size_of::(); #[cfg(any(apple, target_os = "freebsd", target_os = "openbsd"))] asserted_const_with_type!(RTM_ADDRS, i32, RTA_DST, u32); @@ -66,12 +65,12 @@ type AddressFamily = u16; asserted_const_with_type!(AF_INET, AddressFamily, libc::AF_INET, i32); asserted_const_with_type!(AF_INET6, AddressFamily, libc::AF_INET6, i32); asserted_const_with_type!(AF_LINK, AddressFamily, libc::AF_LINK, i32); -asserted_const_with_type!(RTM_VERSION, u8, crate::bsd::bindings::RTM_VERSION, u32); -asserted_const_with_type!(RTM_GET, u8, crate::bsd::bindings::RTM_GET, u32); +asserted_const_with_type!(RTM_VERSION, u8, bindings::RTM_VERSION, u32); +asserted_const_with_type!(RTM_GET, u8, bindings::RTM_GET, u32); -const_assert!(size_of::() + ALIGN <= u8::MAX as usize); -const_assert!(size_of::() + ALIGN <= u8::MAX as usize); -const_assert!(size_of::() <= u8::MAX as usize); +const_assert!(std::mem::size_of::() + ALIGN <= u8::MAX as usize); +const_assert!(std::mem::size_of::() + ALIGN <= u8::MAX as usize); +const_assert!(std::mem::size_of::() <= u8::MAX as usize); struct IfAddrs(*mut ifaddrs); @@ -104,7 +103,9 @@ impl Drop for IfAddrs { fn drop(&mut self) { if !self.0.is_null() { // Free the memory allocated by `getifaddrs`. - unsafe { freeifaddrs(self.0) }; + unsafe { + freeifaddrs(self.0); + } } } } @@ -115,7 +116,7 @@ struct IfAddrPtr<'a> { } impl IfAddrPtr<'_> { - fn addr(&self) -> libc::sockaddr { + fn addr(&self) -> sockaddr { unsafe { *self.ifa_addr } } @@ -136,7 +137,7 @@ impl Deref for IfAddrPtr<'_> { type Target = ifaddrs; fn deref(&self) -> &Self::Target { - unsafe { self.ptr.as_ref().unwrap() } + unsafe { self.ptr.as_ref().expect("can deref") } } } @@ -182,8 +183,8 @@ union SockaddrStorage { fn sockaddr_len(af: AddressFamily) -> Result { let sa_len = match af { - AF_INET => size_of::(), - AF_INET6 => size_of::(), + AF_INET => std::mem::size_of::(), + AF_INET6 => std::mem::size_of::(), _ => { return Err(Error::new( ErrorKind::InvalidInput, @@ -202,7 +203,7 @@ impl From for SockaddrStorage { #[cfg(not(target_os = "solaris"))] #[allow(clippy::cast_possible_truncation)] // `sockaddr_in` len is <= u8::MAX per `const_assert!` above. - sin_len: size_of::() as u8, + sin_len: std::mem::size_of::() as u8, sin_family: AF_INET, sin_addr: in_addr { s_addr: u32::from_ne_bytes(ip.octets()), @@ -216,7 +217,7 @@ impl From for SockaddrStorage { #[cfg(not(target_os = "solaris"))] #[allow(clippy::cast_possible_truncation)] // `sockaddr_in6` len is <= u8::MAX per `const_assert!` above. - sin6_len: size_of::() as u8, + sin6_len: std::mem::size_of::() as u8, sin6_family: AF_INET6, sin6_addr: in6_addr { s6_addr: ip.octets(), @@ -249,7 +250,7 @@ impl RouteMessage { rtm: rt_msghdr { #[allow(clippy::cast_possible_truncation)] // `rt_msghdr` len + `ALIGN` is <= u8::MAX per `const_assert!` above. - rtm_msglen: (size_of::() + sa_len) as u16, + rtm_msglen: (std::mem::size_of::() + sa_len) as u16, rtm_version: RTM_VERSION, rtm_type: RTM_GET, rtm_seq: seq, @@ -275,14 +276,14 @@ impl RouteMessage { impl From<&RouteMessage> for &[u8] { fn from(value: &RouteMessage) -> Self { - debug_assert!(value.len() >= size_of::()); + debug_assert!(value.len() >= std::mem::size_of::()); unsafe { slice::from_raw_parts(ptr::from_ref(value).cast(), value.len()) } } } impl From<&[u8]> for rt_msghdr { fn from(value: &[u8]) -> Self { - debug_assert!(value.len() >= size_of::()); + debug_assert!(value.len() >= std::mem::size_of::()); unsafe { ptr::read_unaligned(value.as_ptr().cast()) } } } @@ -303,15 +304,15 @@ fn if_index_mtu(remote: IpAddr) -> Result<(u16, Option)> { loop { let mut buf = vec![ 0u8; - size_of::() + + std::mem::size_of::() + // There will never be `RTAX_MAX` sockaddrs attached, but it's a safe upper bound. - (RTAX_MAX as usize * size_of::()) + (RTAX_MAX as usize * std::mem::size_of::()) ]; let len = fd.read(&mut buf[..])?; - if len < size_of::() { + if len < std::mem::size_of::() { return Err(default_err()); } - let (reply, mut sa) = buf.split_at(size_of::()); + let (reply, mut sa) = buf.split_at(std::mem::size_of::()); let reply: rt_msghdr = reply.into(); if !(reply.rtm_version == query_version && reply.rtm_pid == pid @@ -326,17 +327,10 @@ fn if_index_mtu(remote: IpAddr) -> Result<(u16, Option)> { // This is a reply to our query. // This is the reply we are looking for. // Some BSDs let us get the interface index and MTU directly from the reply. - let mtu: Option = if reply.rtm_rmx.rmx_mtu != 0 { - Some( - reply - .rtm_rmx - .rmx_mtu - .try_into() - .map_err(|e: TryFromIntError| unlikely_err(e.to_string()))?, - ) - } else { - None - }; + let mtu = (reply.rtm_rmx.rmx_mtu != 0) + .then(|| usize::try_from(reply.rtm_rmx.rmx_mtu)) + .transpose() + .map_err(|e: TryFromIntError| unlikely_err(e.to_string()))?; if reply.rtm_index != 0 { // Some BSDs return the interface index directly. return Ok((reply.rtm_index, mtu)); diff --git a/src/linux.rs b/src/linux.rs index bb5e4b0..1a33df8 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -6,8 +6,7 @@ use std::{ ffi::CStr, - io::{Error, ErrorKind, Read, Result, Write}, - mem::size_of, + io::{Error, ErrorKind, Read as _, Result, Write as _}, net::IpAddr, num::TryFromIntError, ptr, slice, @@ -40,10 +39,10 @@ asserted_const_with_type!(NLM_F_REQUEST, u16, libc::NLM_F_REQUEST, c_int); asserted_const_with_type!(NLM_F_ACK, u16, libc::NLM_F_ACK, c_int); asserted_const_with_type!(NLMSG_ERROR, u16, libc::NLMSG_ERROR, c_int); -const_assert!(size_of::() <= u8::MAX as usize); -const_assert!(size_of::() <= u8::MAX as usize); -const_assert!(size_of::() <= u8::MAX as usize); -const_assert!(size_of::() <= u8::MAX as usize); +const_assert!(std::mem::size_of::() <= u8::MAX as usize); +const_assert!(std::mem::size_of::() <= u8::MAX as usize); +const_assert!(std::mem::size_of::() <= u8::MAX as usize); +const_assert!(std::mem::size_of::() <= u8::MAX as usize); const NETLINK_BUFFER_SIZE: usize = 8192; // See netlink(7) man page. @@ -96,8 +95,10 @@ impl IfIndexMsg { let addr = AddrBytes::new(remote); #[allow(clippy::cast_possible_truncation)] // Structs lens are <= u8::MAX per `const_assert!`s above; `addr_bytes` is max. 16 for IPv6. - let nlmsg_len = - (size_of::() + size_of::() + size_of::() + addr.len()) as u32; + let nlmsg_len = (std::mem::size_of::() + + std::mem::size_of::() + + std::mem::size_of::() + + addr.len()) as u32; Self { nlmsg: nlmsghdr { nlmsg_len, @@ -123,7 +124,7 @@ impl IfIndexMsg { rt: rtattr { #[allow(clippy::cast_possible_truncation)] // Structs len is <= u8::MAX per `const_assert!` above; `addr_bytes` is max. 16 for IPv6. - rta_len: (size_of::() + addr.len()) as u16, + rta_len: (std::mem::size_of::() + addr.len()) as u16, rta_type: RTA_DST, }, addr: addr.into(), @@ -132,7 +133,7 @@ impl IfIndexMsg { const fn len(&self) -> usize { let len = self.nlmsg.nlmsg_len as usize; - debug_assert!(len <= size_of::()); + debug_assert!(len <= std::mem::size_of::()); len } } @@ -147,7 +148,7 @@ impl TryFrom<&[u8]> for nlmsghdr { type Error = Error; fn try_from(value: &[u8]) -> Result { - if value.len() < size_of::() { + if value.len() < std::mem::size_of::() { return Err(default_err()); } Ok(unsafe { ptr::read_unaligned(value.as_ptr().cast()) }) @@ -155,8 +156,10 @@ impl TryFrom<&[u8]> for nlmsghdr { } fn parse_c_int(buf: &[u8]) -> Result { - let bytes = <&[u8] as TryInto<[u8; size_of::()]>>::try_into(&buf[..size_of::()]) - .map_err(|_| default_err())?; + let bytes = <&[u8] as TryInto<[u8; std::mem::size_of::()]>>::try_into( + &buf[..std::mem::size_of::()], + ) + .map_err(|_| default_err())?; Ok(c_int::from_ne_bytes(bytes)) } @@ -165,13 +168,13 @@ fn read_msg_with_seq(fd: &mut RouteSocket, seq: u32, kind: u16) -> Result<(nlmsg let buf = &mut [0u8; NETLINK_BUFFER_SIZE]; let len = fd.read(buf.as_mut_slice())?; let mut next = &buf[..len]; - while size_of::() <= next.len() { - let (hdr, mut msg) = next.split_at(size_of::()); + while std::mem::size_of::() <= next.len() { + let (hdr, mut msg) = next.split_at(std::mem::size_of::()); let hdr: nlmsghdr = hdr.try_into()?; // `msg` has the remainder of this message plus any following messages. // Strip those it off and assign them to `next`. - debug_assert!(size_of::() <= hdr.nlmsg_len as usize); - (msg, next) = msg.split_at(hdr.nlmsg_len as usize - size_of::()); + debug_assert!(std::mem::size_of::() <= hdr.nlmsg_len as usize); + (msg, next) = msg.split_at(hdr.nlmsg_len as usize - std::mem::size_of::()); if hdr.nlmsg_seq != seq { continue; @@ -195,7 +198,7 @@ impl TryFrom<&[u8]> for rtattr { type Error = Error; fn try_from(value: &[u8]) -> Result { - if value.len() < size_of::() { + if value.len() < std::mem::size_of::() { return Err(default_err()); } Ok(unsafe { ptr::read_unaligned(value.as_ptr().cast()) }) @@ -209,12 +212,12 @@ struct RtAttr<'a> { impl<'a> RtAttr<'a> { fn new(bytes: &'a [u8]) -> Result { - debug_assert!(bytes.len() >= size_of::()); - let (hdr, mut msg) = bytes.split_at(size_of::()); + debug_assert!(bytes.len() >= std::mem::size_of::()); + let (hdr, mut msg) = bytes.split_at(std::mem::size_of::()); let hdr: rtattr = hdr.try_into()?; let aligned_len = aligned_by(hdr.rta_len.into(), 4); - debug_assert!(size_of::() <= aligned_len); - (msg, _) = msg.split_at(aligned_len - size_of::()); + debug_assert!(std::mem::size_of::() <= aligned_len); + (msg, _) = msg.split_at(aligned_len - std::mem::size_of::()); Ok(Self { hdr, msg }) } } @@ -225,7 +228,7 @@ impl<'a> Iterator for RtAttrs<'a> { type Item = RtAttr<'a>; fn next(&mut self) -> Option { - if size_of::() <= self.0.len() { + if std::mem::size_of::() <= self.0.len() { let attr = RtAttr::new(self.0).ok()?; let aligned_len = aligned_by(attr.hdr.rta_len.into(), 4); debug_assert!(self.0.len() >= aligned_len); @@ -245,8 +248,8 @@ fn if_index(remote: IpAddr, fd: &mut RouteSocket) -> Result { // Receive RTM_GETROUTE response. let (_hdr, mut buf) = read_msg_with_seq(fd, msg_seq, RTM_NEWROUTE)?; - debug_assert!(size_of::() <= buf.len()); - let buf = buf.split_off(size_of::()); + debug_assert!(std::mem::size_of::() <= buf.len()); + let buf = buf.split_off(std::mem::size_of::()); // Parse through the attributes to find the interface index. for attr in RtAttrs(buf.as_slice()).by_ref() { @@ -268,7 +271,7 @@ impl IfInfoMsg { fn new(if_index: i32, nlmsg_seq: u32) -> Self { #[allow(clippy::cast_possible_truncation)] // Structs lens are <= u8::MAX per `const_assert!`s above. - let nlmsg_len = (size_of::() + size_of::()) as u32; + let nlmsg_len = (std::mem::size_of::() + std::mem::size_of::()) as u32; Self { nlmsg: nlmsghdr { nlmsg_len, @@ -293,7 +296,7 @@ impl IfInfoMsg { impl From<&IfInfoMsg> for &[u8] { fn from(value: &IfInfoMsg) -> Self { - debug_assert!(value.len() >= size_of::()); + debug_assert!(value.len() >= std::mem::size_of::()); unsafe { slice::from_raw_parts(ptr::from_ref(value).cast(), value.len()) } } } @@ -306,8 +309,8 @@ fn if_name_mtu(if_index: i32, fd: &mut RouteSocket) -> Result<(String, usize)> { // Receive RTM_GETLINK response. let (_hdr, mut buf) = read_msg_with_seq(fd, msg_seq, RTM_NEWLINK)?; - debug_assert!(size_of::() <= buf.len()); - let buf = buf.split_off(size_of::()); + debug_assert!(std::mem::size_of::() <= buf.len()); + let buf = buf.split_off(std::mem::size_of::()); // Parse through the attributes to find the interface name and MTU. let mut ifname = None; diff --git a/src/routesocket.rs b/src/routesocket.rs index ab99241..6416c55 100644 --- a/src/routesocket.rs +++ b/src/routesocket.rs @@ -7,7 +7,7 @@ use std::{ io::{Error, Read, Result, Write}, num::TryFromIntError, - os::fd::{AsRawFd, FromRawFd, OwnedFd}, + os::fd::{AsRawFd, FromRawFd as _, OwnedFd}, sync::atomic::Ordering, }; @@ -60,19 +60,19 @@ fn check_result(res: isize) -> Result { } impl Write for RouteSocket { - fn write(&mut self, buf: &[u8]) -> std::io::Result { + fn write(&mut self, buf: &[u8]) -> Result { let res = unsafe { write(self.as_raw_fd(), buf.as_ptr().cast(), buf.len()) }; check_result(res) } - fn flush(&mut self) -> std::io::Result<()> { + fn flush(&mut self) -> Result<()> { let res = unsafe { fsync(self.as_raw_fd()) }; check_result(res as isize).and(Ok(())) } } impl Read for RouteSocket { - fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + fn read(&mut self, buf: &mut [u8]) -> Result { // If we've written a well-formed message into the kernel via `write`, we should be able to // read a well-formed message back out, and not block. let res = unsafe { read(self.as_raw_fd(), buf.as_mut_ptr().cast(), buf.len()) }; diff --git a/src/windows.rs b/src/windows.rs index 1c76f26..247d28e 100644 --- a/src/windows.rs +++ b/src/windows.rs @@ -49,7 +49,9 @@ impl Drop for MibTablePtr { fn drop(&mut self) { if !self.0.is_null() { // Free the memory allocated by GetIpInterfaceTable. - unsafe { FreeMibTable(self.0.cast()) }; + unsafe { + FreeMibTable(self.0.cast()); + } } } }