1 //! Socket address utilities.
5 //! This file uses `CStr::from_bytes_with_nul_unchecked` on a string it knows
6 //! to be NUL-terminated.
11 use crate::{io, path}
;
12 use core
::cmp
::Ordering
;
13 use core
::convert
::TryInto
;
15 use core
::hash
::{Hash, Hasher}
;
17 /// `struct sockaddr_un`
19 #[doc(alias = "sockaddr_un")]
20 pub struct SocketAddrUnix
{
21 pub(crate) unix
: c
::sockaddr_un
,
26 /// Construct a new Unix-domain address from a filesystem path.
28 pub fn new
<P
: path
::Arg
>(path
: P
) -> io
::Result
<Self> {
29 path
.into_with_c_str(Self::_new
)
33 fn _new(path
: &CStr
) -> io
::Result
<Self> {
34 let mut unix
= Self::init();
35 let bytes
= path
.to_bytes_with_nul();
36 if bytes
.len() > unix
.sun_path
.len() {
37 return Err(io
::Errno
::NAMETOOLONG
);
39 for (i
, b
) in bytes
.iter().enumerate() {
40 unix
.sun_path
[i
] = *b
;
42 let len
= offsetof_sun_path() + bytes
.len();
43 let len
= len
.try_into().unwrap();
44 Ok(Self { unix, len }
)
47 /// Construct a new abstract Unix-domain address from a byte slice.
49 pub fn new_abstract_name(name
: &[u8]) -> io
::Result
<Self> {
50 let mut unix
= Self::init();
51 let id
= &mut unix
.sun_path
[1..];
52 if let Some(id
) = id
.get_mut(..name
.len()) {
53 id
.copy_from_slice(name
);
54 let len
= offsetof_sun_path() + 1 + name
.len();
55 let len
= len
.try_into().unwrap();
56 Ok(Self { unix, len }
)
58 Err(io
::Errno
::NAMETOOLONG
)
62 const fn init() -> c
::sockaddr_un
{
64 sun_family
: c
::AF_UNIX
as _
,
69 /// For a filesystem path address, return the path.
71 pub fn path(&self) -> Option
<&CStr
> {
73 if len
!= 0 && self.unix
.sun_path
[0] != b'
\0'
{
74 let end
= len
as usize - offsetof_sun_path();
75 let bytes
= &self.unix
.sun_path
[..end
];
76 // SAFETY: `from_bytes_with_nul_unchecked` since the string is
78 unsafe { Some(CStr::from_bytes_with_nul_unchecked(bytes)) }
84 /// For an abstract address, return the identifier.
86 pub fn abstract_name(&self) -> Option
<&[u8]> {
88 if len
!= 0 && self.unix
.sun_path
[0] == b'
\0'
{
89 let end
= len
as usize - offsetof_sun_path();
90 Some(&self.unix
.sun_path
[1..end
])
97 pub(crate) fn addr_len(&self) -> c
::socklen_t
{
102 pub(crate) fn len(&self) -> usize {
103 self.addr_len() as usize
107 impl PartialEq
for SocketAddrUnix
{
109 fn eq(&self, other
: &Self) -> bool
{
110 let self_len
= self.len() - offsetof_sun_path();
111 let other_len
= other
.len() - offsetof_sun_path();
112 self.unix
.sun_path
[..self_len
].eq(&other
.unix
.sun_path
[..other_len
])
116 impl Eq
for SocketAddrUnix {}
118 impl PartialOrd
for SocketAddrUnix
{
120 fn partial_cmp(&self, other
: &Self) -> Option
<Ordering
> {
121 let self_len
= self.len() - offsetof_sun_path();
122 let other_len
= other
.len() - offsetof_sun_path();
123 self.unix
.sun_path
[..self_len
].partial_cmp(&other
.unix
.sun_path
[..other_len
])
127 impl Ord
for SocketAddrUnix
{
129 fn cmp(&self, other
: &Self) -> Ordering
{
130 let self_len
= self.len() - offsetof_sun_path();
131 let other_len
= other
.len() - offsetof_sun_path();
132 self.unix
.sun_path
[..self_len
].cmp(&other
.unix
.sun_path
[..other_len
])
136 impl Hash
for SocketAddrUnix
{
138 fn hash
<H
: Hasher
>(&self, state
: &mut H
) {
139 let self_len
= self.len() - offsetof_sun_path();
140 self.unix
.sun_path
[..self_len
].hash(state
)
144 impl fmt
::Debug
for SocketAddrUnix
{
145 fn fmt(&self, fmt
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
146 if let Some(path
) = self.path() {
148 } else if let Some(name
) = self.abstract_name() {
156 /// `struct sockaddr_storage` as a raw struct.
157 pub type SocketAddrStorage
= c
::sockaddr
;
159 /// Return the offset of the `sun_path` field of `sockaddr_un`.
161 pub(crate) fn offsetof_sun_path() -> usize {
162 let z
= c
::sockaddr_un
{
166 (crate::utils
::as_ptr(&z
.sun_path
) as usize) - (crate::utils
::as_ptr(&z
) as usize)