Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SockAddr::set_length #428

Merged
merged 3 commits into from
Apr 11, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 30 additions & 23 deletions src/sockaddr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,6 @@ pub struct SockAddr {

#[allow(clippy::len_without_is_empty)]
impl SockAddr {
/// Constructs a `SockAddr` with the family `AF_UNIX` and the provided path.
///
/// Returns an error if the path is longer than `SUN_LEN`.
pub fn unix<P>(path: P) -> io::Result<SockAddr>
where
P: AsRef<Path>,
{
crate::sys::unix_sockaddr(path.as_ref())
}

/// Create a `SockAddr` from the underlying storage and its length.
///
/// # Safety
Expand Down Expand Up @@ -153,6 +143,26 @@ impl SockAddr {
})
}

/// Constructs a `SockAddr` with the family `AF_UNIX` and the provided path.
///
/// Returns an error if the path is longer than `SUN_LEN`.
pub fn unix<P>(path: P) -> io::Result<SockAddr>
where
P: AsRef<Path>,
{
crate::sys::unix_sockaddr(path.as_ref())
}

/// Set the length of the address.
///
/// # Safety
///
/// Caller must ensure that the address up to `length` bytes are properly
/// initialised.
pub unsafe fn set_length(&mut self, length: socklen_t) {
self.len = length;
}
Comment on lines +162 to +164
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This puts a libc type in your public API. Did you intend to do that?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have that in various other places, e.g. the len function also returns socklen_t. So, it's not ideal and I'm aware of the complexities that then come with updating libc and windows-sys, but they're type definitions (not e.g. structs) should they should remain compatible between dependency updates.


/// Returns this address's family.
pub const fn family(&self) -> sa_family_t {
self.storage.ss_family
Expand Down Expand Up @@ -250,6 +260,14 @@ impl SockAddr {
_ => None,
}
}

/// Returns the initialised storage bytes.
fn as_bytes(&self) -> &[u8] {
// SAFETY: `self.storage` is a C struct which can always be treated a
// slice of bytes. Futhermore we ensure we don't read any unitialised
// bytes by using `self.len`.
unsafe { std::slice::from_raw_parts(self.as_ptr().cast(), self.len as usize) }
}
}

impl From<SocketAddr> for SockAddr {
Expand Down Expand Up @@ -329,29 +347,18 @@ impl fmt::Debug for SockAddr {

impl PartialEq for SockAddr {
fn eq(&self, other: &Self) -> bool {
unsafe {
let these_bytes: &[u8] = any_as_u8_slice(&self.storage, self.len as usize);
let those_bytes: &[u8] = any_as_u8_slice(&other.storage, other.len as usize);
these_bytes == those_bytes
}
self.as_bytes() == other.as_bytes()
}
}

impl Eq for SockAddr {}

impl Hash for SockAddr {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
unsafe {
let these_bytes: &[u8] = any_as_u8_slice(&self.storage, self.len as usize);
these_bytes.hash(state);
}
self.as_bytes().hash(state);
}
}

unsafe fn any_as_u8_slice<T: Sized>(p: &T, size: usize) -> &[u8] {
::std::slice::from_raw_parts((p as *const T) as *const u8, size)
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down