Skip to main content

uds_fork/
addr.rs

1
2#[cfg(windows)]
3use std::borrow::Cow;
4use std::
5{
6    ffi::{CStr, OsStr, c_char}, 
7    fmt::{self, Debug, Display}, 
8    hash::{Hash, Hasher}, 
9    io::{self, ErrorKind}, 
10    mem, 
11    path::Path, 
12    slice
13};
14
15#[cfg(unix)]
16use std::os::unix::{ffi::OsStrExt, net};
17
18#[cfg(unix)]
19use libc::{AF_UNIX, sa_family_t, sockaddr, sockaddr_storage, sockaddr_un, socklen_t};
20
21#[cfg(windows)]
22pub use windows_sys::Win32::Networking::WinSock::
23{
24    AF_UNIX, SOCKADDR_STORAGE as sockaddr_storage, socklen_t, SOCKADDR as sockaddr, 
25    SOCKADDR_UN as sockaddr_un, ADDRESS_FAMILY as sa_family_t
26};
27
28/// Offset of `.sun_path` in `sockaddr_un`.
29///
30/// This is not always identical to `mem::size_of::<sa_family_t>()`,
31/// as there can be other fields before or after `.sun_family`.
32fn path_offset() -> socklen_t 
33{
34    unsafe 
35    {
36        let total_size = mem::size_of::<sockaddr_un>();
37        let name_size = mem::size_of_val(&mem::zeroed::<sockaddr_un>().sun_path);
38
39        (total_size - name_size) as socklen_t
40    }
41}
42
43const 
44fn as_u8(slice: &[c_char]) -> &[u8] 
45{
46    unsafe { &*(slice as *const[c_char] as *const[u8]) }
47}
48
49const 
50fn as_char(slice: &[u8]) -> &[c_char] 
51{
52    unsafe { &*(slice as *const[u8] as *const[c_char]) }
53}
54
55const TOO_LONG_DESC: &str = "address is too long";
56
57
58/// A unix domain socket address.
59///
60/// # Differences from `std`'s `unix::net::SocketAddr`
61///
62/// This type fully supports Linux's abstract socket addresses,
63/// and can be created by user code instead of just returned by `accept()`
64/// and similar.
65///
66/// # Examples
67///
68/// Creating an abstract address (fails if the OS doesn't support them):
69///
70#[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
71#[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
72/// use uds_fork::UnixSocketAddr;
73///
74/// let addr = UnixSocketAddr::new("@abstract").unwrap();
75/// assert!(addr.is_abstract());
76/// assert_eq!(addr.to_string(), "@abstract");
77/// ```
78#[derive(Clone, Copy)]
79pub struct UnixSocketAddr 
80{
81    addr: sockaddr_un,
82
83    /// How many bytes of addr are in use.
84    ///
85    /// Must never be greater than `size_of::<sockaddr_un>()`.
86    ///
87    /// On BSDs and macOS, `sockaddr_un` has a (non-standard) `.sun_len` field
88    /// that *could* be used to store the length instead, but doing that is
89    /// not a very good idea:  
90    /// At least [NetBSD ignores it](http://mail-index.netbsd.org/tech-net/2006/10/11/0008.html)
91    /// so we would still need to pass a correctly set `socklen_t`,
92    /// in some cases by referece.
93    /// Because it's rarely used and some BSDs aren't afraid to break stuff,
94    /// it could even dissappear in the future.  
95    /// The size this extra field is also rather minor compared to the size of
96    /// `sockaddr_un`, so the possible benefit is tiny.
97    len: socklen_t,
98}
99
100
101
102/// An enum representation of an unix socket address.
103///
104/// Useful for pattern matching an [`UnixSocketAddr`](struct.UnixSocketAddr.html)
105/// via [`UnixSocketAddr.name()`](struct.UnixSocketAddr.html#method.name).
106///
107/// It cannot be used to bind or connect a socket directly as it
108/// doesn't contain a `sockaddr_un`, but a `UnixSocketAddr` can be created
109/// from it.
110///
111/// # Examples
112///
113/// Cleaning up pathname socket files after ourselves:
114///
115/// ```no_run
116/// # use uds_fork::{UnixSocketAddr, AddrName};
117/// let addr = UnixSocketAddr::from_path("/var/run/socket.sock").unwrap();
118/// if let AddrName::Path(path) = addr.name() {
119///     let _ = std::fs::remove_file(path);
120/// }
121/// ```
122#[derive(Clone,Copy, PartialEq,Eq,Hash, Debug)]
123pub enum AddrName<'a> 
124{
125    /// Unnamed / anonymous address.
126    Unnamed,
127    /// Regular file path based address.
128    ///
129    /// Can be both relative and absolute.
130    Path(&'a Path),
131    /// Address in the abstract namespace.
132    Abstract(&'a [u8]),
133}
134
135impl<'a> From<&'a UnixSocketAddr> for AddrName<'a> 
136{
137    fn from(addr: &'a UnixSocketAddr) -> AddrName<'a> 
138    {
139        let name_len = addr.len as isize - path_offset() as isize;
140
141        if addr.is_unnamed() == true
142        {
143            AddrName::Unnamed
144        } 
145        else if addr.is_abstract() == true
146        {
147            let slice = &addr.addr.sun_path[1..name_len as usize];
148            AddrName::Abstract(as_u8(slice))
149        } 
150        else 
151        {
152            let mut slice = &addr.addr.sun_path[..name_len as usize];
153
154            // remove trailing NUL if present (and multiple NULs on OpenBSD)
155            while let Some(&0) = slice.last() 
156            {
157                slice = &slice[..slice.len()-1];
158            }
159
160            #[cfg(unix)]
161            return 
162                AddrName::Path(Path::new(OsStr::from_bytes(as_u8(slice))));
163
164            // sun_path is UTF-8
165            #[cfg(windows)]
166            {
167                //let utf8_valid = str::from_utf8(as_u8(slice)).unwrap();
168
169                return 
170                    AddrName::Path(Path::new(unsafe{ OsStr::from_encoded_bytes_unchecked(as_u8(slice)) } ))
171            }
172        }
173    }
174}
175
176pub type UnixSocketAddrRef<'a> = AddrName<'a>;
177
178impl Debug for UnixSocketAddr 
179{
180    fn fmt(&self,  fmtr: &mut fmt::Formatter) -> fmt::Result 
181    {
182        #[derive(Debug)]
183        struct Unnamed;
184        #[derive(Debug)]
185        struct Path<'a>(&'a std::path::Path);
186        #[cfg(unix)]
187        #[derive(Debug)]
188        struct Abstract<'a>(&'a OsStr);
189
190        #[cfg(windows)]
191        #[derive(Debug)]
192        struct Abstract<'a>(Cow<'a, str>);
193
194        // doesn't live long enough if created inside match
195        let mut path_type = Path("".as_ref());
196        #[cfg(unix)]
197        let mut abstract_type = Abstract(OsStr::new(""));
198
199        #[cfg(windows)]
200        let mut abstract_type = Abstract(Cow::Borrowed(""));
201
202        let variant: &dyn Debug = 
203            match self.into() 
204            {
205                UnixSocketAddrRef::Unnamed => 
206                    &Unnamed,
207                UnixSocketAddrRef::Path(path) => 
208                {
209                    path_type.0 = path;
210                    &path_type
211                },
212                UnixSocketAddrRef::Abstract(name) => 
213                {
214                    #[cfg(unix)]
215                    {
216                        abstract_type.0 = OsStr::from_bytes(name);
217                    }
218
219                    #[cfg(windows)]
220                    {
221                        let utf8_valid = String::from_utf8_lossy(name);
222                        abstract_type.0 = utf8_valid;
223                    }
224                    
225                    &abstract_type
226                },
227            };
228        fmtr.debug_tuple("UnixSocketAddr").field(variant).finish()
229    }
230}
231
232impl Display for UnixSocketAddr 
233{
234    fn fmt(&self,  fmtr: &mut fmt::Formatter) -> fmt::Result 
235    {
236        match self.into() 
237        {
238            UnixSocketAddrRef::Unnamed => 
239                fmtr.write_str("unnamed"),
240            UnixSocketAddrRef::Path(path) => 
241                write!(fmtr, "{}", path.display()), // TODO check that display() doesn't print \n as-is
242            #[cfg(unix)]
243            UnixSocketAddrRef::Abstract(name) => 
244                {
245                    write!(fmtr, "@{}", OsStr::from_bytes(name).to_string_lossy()) // FIXME escape to sane characters
246                }
247            #[cfg(windows)]
248            UnixSocketAddrRef::Abstract(name) =>     
249                {
250                    let utf8_valid = String::from_utf8_lossy(name);
251
252                    write!(fmtr, "@{}", utf8_valid) // FIXME escape to sane characters
253                }
254        }
255    }
256}
257
258#[cfg(windows)]
259impl UnixSocketAddr
260{
261    /// Allows creating abstract, path or unspecified address based on an
262    /// user-supplied string.
263    ///
264    /// A leading `'@'` or `'\0'` signifies an abstract address,
265    /// an empty slice is taken as the unnamed address, and anything else is a
266    /// path address.  
267    /// If a relative path address starts with `@`, escape it by prepending
268    /// `"./"`.
269    /// To avoid surprises, abstract addresses will be detected regargsless of
270    /// wheither the OS supports them, and result in an error if it doesn't.
271    ///
272    /// # Errors
273    ///
274    /// * A path or abstract address is too long.
275    /// * A path address contains `'\0'`.
276    /// * An abstract name was supplied on an OS that doesn't support them.
277    ///
278    /// # Examples
279    ///
280    /// Abstract address:
281    ///
282    /// ```
283    /// # use uds_fork::UnixSocketAddr;
284    /// if UnixSocketAddr::has_abstract_addresses() {
285    ///     assert!(UnixSocketAddr::new("@abstract").unwrap().is_abstract());
286    ///     assert!(UnixSocketAddr::new("\0abstract").unwrap().is_abstract());
287    /// } else {
288    ///     assert!(UnixSocketAddr::new("@abstract").is_err());
289    ///     assert!(UnixSocketAddr::new("\0abstract").is_err());
290    /// }
291    /// ```
292    ///
293    /// Escaped path address:
294    ///
295    /// ```
296    /// # use uds_fork::UnixSocketAddr;
297    /// assert!(UnixSocketAddr::new("./@path").unwrap().is_relative_path());
298    /// ```
299    ///
300    /// Unnamed address:
301    ///
302    #[cfg_attr(not(target_family="windows"), doc="```")]
303    #[cfg_attr(target_family="windows", doc="```no_run")]
304    /// # use uds_fork::UnixSocketAddr;
305    /// assert!(UnixSocketAddr::new("").unwrap().is_unnamed());
306    /// ```
307    pub 
308    fn new<A: AsRef<[u8]>+?Sized>(addr: &A) -> Result<Self, io::Error> 
309    {
310        fn parse(addr: &[u8]) -> Result<UnixSocketAddr, io::Error> 
311        {
312            match addr.first() 
313            {
314                Some(&b'@') | Some(&b'\0') => 
315                    return 
316                        Err(
317                            io::Error::new(
318                                ErrorKind::AddrNotAvailable, 
319                                format!( "abstract unix domain socket addresses are not available on {}",
320                                    std::env::consts::OS)
321                            )
322                        ),
323                Some(_) => 
324                {
325                    let utf8_valid = 
326                        str::from_utf8(addr)
327                            .map_err(|e| io::Error::new(ErrorKind::InvalidInput, e)
328                        )?;
329
330                    UnixSocketAddr::from_path(Path::new(utf8_valid))
331                },
332                None => 
333                    return 
334                        Err(
335                            io::Error::new(
336                                ErrorKind::AddrNotAvailable, 
337                                format!( "unspecified unix domain socket addresses are not available on {}",
338                                    std::env::consts::OS)
339                            )
340                        ),
341            }
342        }
343
344        return parse(addr.as_ref());
345    }
346
347    /// Allows creating abstract, path or unspecified address based on an
348    /// user-supplied string for Windows UTF-16 path.
349    ///
350    /// A leading `'@'` or `'\0'` signifies an abstract address,
351    /// an empty slice is taken as the unnamed address, and anything else is a
352    /// path address. (Windows does not support abstract addresses)  
353    /// If a relative path address starts with `@`, escape it by prepending
354    /// `"./"`.
355    /// To avoid surprises, abstract addresses will be detected regargsless of
356    /// wheither the OS supports them, and result in an error if it doesn't.
357    ///
358    /// # Errors
359    ///
360    /// * A path or abstract address is too long.
361    /// * A path address contains `'\0'`.
362    /// * An abstract name was supplied on an OS that doesn't support them.
363    pub 
364    fn new_utf16<A: AsRef<[u16]>+?Sized>(addr_v: &A) -> Result<Self, io::Error> 
365    {
366        use std::{ffi::OsString, os::windows::ffi::OsStringExt};
367        let addr = addr_v.as_ref();
368       
369        let first = 
370            if addr.len() > 0
371            {
372                Some(OsString::from_wide(&addr[0..1]))
373            }
374            else
375            {
376                None
377            };
378
379        match first.as_ref().map(|v| v.as_encoded_bytes())
380        {
381            Some(b"@") | Some(b"\0") => 
382                return 
383                    Err(
384                        io::Error::new(
385                            ErrorKind::AddrNotAvailable, 
386                            format!( "abstract unix domain socket addresses are not available on {}",
387                                std::env::consts::OS)
388                        )
389                    ),
390            Some(_) => 
391            {
392                
393                let osstr = OsString::from_wide(addr);
394
395                return  UnixSocketAddr::from_path(Path::new( &osstr ));
396            },
397            None => 
398                return 
399                    Err(
400                        io::Error::new(
401                            ErrorKind::AddrNotAvailable, 
402                            format!( "unspecified unix domain socket addresses are not available on {}",
403                                std::env::consts::OS)
404                        )
405                    ),
406        }
407    }
408}
409
410#[cfg(unix)]
411impl UnixSocketAddr 
412{
413    /// Allows creating abstract, path or unspecified address based on an
414    /// user-supplied string.
415    ///
416    /// A leading `'@'` or `'\0'` signifies an abstract address,
417    /// an empty slice is taken as the unnamed address, and anything else is a
418    /// path address.  
419    /// If a relative path address starts with `@`, escape it by prepending
420    /// `"./"`.
421    /// To avoid surprises, abstract addresses will be detected regargsless of
422    /// wheither the OS supports them, and result in an error if it doesn't.
423    ///
424    /// # Errors
425    ///
426    /// * A path or abstract address is too long.
427    /// * A path address contains `'\0'`.
428    /// * An abstract name was supplied on an OS that doesn't support them.
429    ///
430    /// # Examples
431    ///
432    /// Abstract address:
433    ///
434    /// ```
435    /// # use uds_fork::UnixSocketAddr;
436    /// if UnixSocketAddr::has_abstract_addresses() {
437    ///     assert!(UnixSocketAddr::new("@abstract").unwrap().is_abstract());
438    ///     assert!(UnixSocketAddr::new("\0abstract").unwrap().is_abstract());
439    /// } else {
440    ///     assert!(UnixSocketAddr::new("@abstract").is_err());
441    ///     assert!(UnixSocketAddr::new("\0abstract").is_err());
442    /// }
443    /// ```
444    ///
445    /// Escaped path address:
446    ///
447    /// ```
448    /// # use uds_fork::UnixSocketAddr;
449    /// assert!(UnixSocketAddr::new("./@path").unwrap().is_relative_path());
450    /// ```
451    ///
452    /// Unnamed address:
453    ///
454    /// ```
455    /// # use uds_fork::UnixSocketAddr;
456    /// assert!(UnixSocketAddr::new("").unwrap().is_unnamed());
457    /// ```
458    pub 
459    fn new<A: AsRef<[u8]>+?Sized>(addr: &A) -> Result<Self, io::Error> 
460    {
461        fn parse(addr: &[u8]) -> Result<UnixSocketAddr, io::Error> 
462        {
463            match addr.first() 
464            {
465                Some(&b'@') | Some(&b'\0') => 
466                    UnixSocketAddr::from_abstract(&addr[1..]),
467                Some(_) => 
468                    UnixSocketAddr::from_path(Path::new(OsStr::from_bytes(addr))),
469                None => 
470                    Ok(UnixSocketAddr::new_unspecified()),
471            }
472        }
473
474        return parse(addr.as_ref());
475    }
476}
477
478impl UnixSocketAddr 
479{
480    /// Creates an unnamed address, which on Linux can be used for auto-bind.
481    ///
482    /// Binding a socket to the unnamed address is different from not binding
483    /// at all:
484    ///
485    /// On Linux doing so binds the socket to a random abstract address
486    /// determined by the OS.
487    ///
488    /// # Examples
489    ///
490    #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
491    #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```ignore")]
492    /// # use uds_fork::{UnixSocketAddr, UnixDatagramExt};
493    /// # use std::os::unix::net::UnixDatagram;
494    /// let addr = UnixSocketAddr::new_unspecified();
495    /// assert!(addr.is_unnamed());
496    /// let socket = UnixDatagram::unbound().unwrap();
497    /// socket.bind_to_unix_addr(&addr).unwrap();
498    /// assert!(socket.local_unix_addr().unwrap().is_abstract());
499    /// ```
500    pub 
501    fn new_unspecified() -> Self 
502    {
503        let mut addr: sockaddr_un = unsafe { mem::zeroed() };
504        addr.sun_family = AF_UNIX as sa_family_t;
505
506        return 
507            UnixSocketAddr 
508            {
509                len: path_offset(),
510                addr,
511            };
512    }
513
514    /// Returns the maximum size of pathname addresses supported by `UnixSocketAddr`.
515    ///
516    /// Is the size of the underlying `sun_path` field, minus 1 if the OS
517    /// is known to either require a trailing NUL (`'\0'`) byte,
518    /// or supports longer paths that go past the end of `sun_path`.
519    ///
520    /// These OSes are:
521    ///
522    /// * OpenBSD: Enforces that `sun_path`` is NUL-terminated.
523    /// * macOS / iOS / anything else Apple: I haven't found a manpage,
524    ///   but it supports longer paths.
525    /// * Illumos: [The manpage](https://illumos.org/man/3SOCKET/sockaddr_un)
526    ///   says it must be NUL-terminated (and that it cannot be longer),
527    ///   but when I tested on an older version, neither of these constraints seem to be the case.
528    /// * Solaris: Assumed to be identical to Illumos.
529    ///
530    /// OSes that have been tested that they allow using the full `sun_path`
531    /// without NUL and no longer paths, and whose manpages don't state the opposite:
532    ///
533    /// * [Linux](https://www.man7.org/linux/man-pages/man7/unix.7.html)
534    /// * [FreeBSD](https://man.freebsd.org/cgi/man.cgi?query=unix&sektion=4)
535    /// * [NetBSD](https://man.netbsd.org/unix.4)
536    /// * [Dragonfly BSD](https://man.dragonflybsd.org/?command=unix&section=4)
537    pub 
538    fn max_path_len() -> usize 
539    {
540        let always_nul_terminate = 
541            cfg!(any(
542                target_os="openbsd",
543                target_vendor="apple",
544                target_os="illumos",
545                target_os="solaris",
546            ));
547
548        return
549            if always_nul_terminate == true 
550            {
551                mem::size_of_val(&Self::new_unspecified().addr.sun_path) - 1
552            } 
553            else 
554            {
555                mem::size_of_val(&Self::new_unspecified().addr.sun_path)
556            };
557    }
558
559    /// Creates a pathname unix socket address.
560    ///
561    /// # Errors
562    ///
563    /// This function will return an error if the path is too long for the
564    /// underlying `sockaddr_un` type, or contains NUL (`'\0'`) bytes.
565    pub 
566    fn from_path<P: AsRef<Path>+?Sized>(path: &P) -> Result<Self, io::Error> 
567    {
568        fn from_path_inner(path: &[u8]) -> Result<UnixSocketAddr, io::Error> 
569        {
570            let mut addr = UnixSocketAddr::new_unspecified();
571            let capacity = UnixSocketAddr::max_path_len();
572
573            if path.is_empty() == true 
574            {
575                return Err(io::Error::new(ErrorKind::NotFound, "path is empty"));
576            } 
577            else if path.len() > capacity 
578            {
579                let message = "path is too long for an unix socket address";
580
581                return Err(io::Error::new(ErrorKind::InvalidInput, message));
582            } 
583            else if path.iter().any(|&b| b == b'\0' ) == true
584            {
585                return Err(io::Error::new(ErrorKind::InvalidInput, "path cannot contain nul bytes"));
586            } 
587            else 
588            {
589                addr.addr.sun_path[..path.len()].copy_from_slice(as_char(path));
590                addr.len = path_offset() + path.len() as socklen_t;
591                
592                if path.len() < capacity 
593                {
594                    addr.len += 1; // for increased portability
595                }
596                
597                return Ok(addr);
598            }
599        }
600
601        #[cfg(unix)]
602        return from_path_inner(path.as_ref().as_os_str().as_bytes());
603
604        #[cfg(windows)]
605        return from_path_inner(path.as_ref().as_os_str().as_encoded_bytes());
606    }
607
608    /// Returns maximum size of abstract addesses supported by `UnixSocketAddr`.
609    ///
610    /// Is the size of the underlying `sun_path` field minus 1 for the
611    /// leading `'\0'` byte.
612    ///
613    /// This value is also returned on operating systems that doesn't support
614    /// abstract addresses.
615    pub 
616    fn max_abstract_len() -> usize 
617    {
618        mem::size_of_val(&Self::new_unspecified().addr.sun_path) - 1
619    }
620
621    /// Returns whether the operating system is known to support
622    /// abstract unix domain socket addresses.
623    ///
624    /// Is `true` for Linux & Android, and `false` for all other OSes.
625    pub const 
626    fn has_abstract_addresses() -> bool 
627    {
628        cfg!(any(target_os="linux", target_os="android"))
629    }
630
631    /// Creates an abstract unix domain socket address.
632    ///
633    /// Abstract addresses use a namespace separate from the file system,
634    /// that doesn't have directories (ie. is flat) or permissions.
635    /// The advandage of it is that the address disappear when the socket bound
636    /// to it is closed, which frees one from dealing with removing it when
637    /// shutting down cleanly.
638    ///
639    /// They are a Linux-only feature though, and this function will fail
640    /// if abstract addresses are not supported.
641    ///
642    /// # Errors
643    ///
644    /// This function will return an error if the name is too long.
645    /// Call [`max_abstract_len()`](#method.max_abstract_len)
646    /// get the limit.
647    ///
648    /// It will also fail on operating systems that don't support abstract
649    /// addresses. (ie. anything other than Linux and Android)
650    pub 
651    fn from_abstract<N: AsRef<[u8]>+?Sized>(name: &N) -> Result<Self, io::Error> 
652    {
653        fn from_abstract_inner(name: &[u8]) -> Result<UnixSocketAddr, io::Error> 
654        {
655            let mut addr = UnixSocketAddr::new_unspecified();
656
657            if UnixSocketAddr::has_abstract_addresses() == false
658            {
659                return 
660                    Err(
661                        io::Error::new(
662                            ErrorKind::AddrNotAvailable, 
663                            format!( "abstract unix domain socket addresses are not available on {}",
664                                std::env::consts::OS)
665                        )
666                    );
667            } 
668            else if name.len() > UnixSocketAddr::max_abstract_len() 
669            {
670                return 
671                    Err(io::Error::new(ErrorKind::InvalidInput, "abstract name is too long"));
672            } 
673            else 
674            {
675                addr.addr.sun_path[1..1+name.len()].copy_from_slice(as_char(name));
676                addr.len = path_offset() + 1 + name.len() as socklen_t;
677                return Ok(addr);
678            }
679        }
680
681        return from_abstract_inner(name.as_ref());
682    }
683
684    /// Tries to convert a `std::os::unix::net::SocketAddr` into an `UnixSocketAddr`.
685    ///
686    /// This can fail (produce `None`) on Linux and Android
687    /// if the `std` `SocketAddr` represents an abstract address,
688    /// as it provides no method for viewing abstract addresses.
689    /// (other than parsing its `Debug` output, anyway.)
690    #[cfg(unix)]
691    pub 
692    fn from_std(addr: net::SocketAddr) -> Option<Self> 
693    {
694        return 
695            if let Some(path) = addr.as_pathname() 
696            {
697                Some(Self::from_path(path).expect("pathname addr cannot be converted"))
698            } 
699            else if addr.is_unnamed() 
700            {
701                Some(Self::new_unspecified())
702            } 
703            else 
704            {
705                None
706            };
707    }
708
709    /// Returns unnamed addres for empty strings, and path addresses otherwise.
710    ///
711    /// # Errors
712    ///
713    /// Returns ENAMETOOLONG if path (without the trailing `'\0'`) is too long
714    /// for `sockaddr_un.sun_path`.
715    pub 
716    fn from_c_str(path: &CStr) -> Result<Self, io::Error> 
717    {
718        let path = path.to_bytes();
719        let mut addr = Self::new_unspecified();
720
721        if path.is_empty() 
722        {
723            return Ok(addr);
724        } 
725        else if path.len() > mem::size_of_val(&addr.addr.sun_path) 
726        {
727            let message = "path is too long for unix socket address";
728
729            return Err(io::Error::new(ErrorKind::InvalidInput, message));
730        } 
731        else 
732        {
733            addr.addr.sun_path[..path.len()].copy_from_slice(as_char(path));
734            addr.len = path_offset() + path.len() as socklen_t;
735
736            if path.len() < mem::size_of_val(&addr.addr.sun_path) 
737            {
738                addr.len += 1;
739            }
740
741            return Ok(addr);
742        }
743    }
744
745    /// Checks whether the address is unnamed.
746    #[inline]
747    pub 
748    fn is_unnamed(&self) -> bool 
749    {
750        if Self::has_abstract_addresses() 
751        {
752            return self.len <= path_offset();
753        } 
754        else 
755        {
756            // MacOS can apparently return non-empty addresses but with
757            // all-zeroes path for unnamed addresses.
758            return self.len <= path_offset()  ||  self.addr.sun_path[0] as u8 == b'\0';
759        }
760    }
761
762    /// Checks whether the address is a name in the abstract namespace.
763    ///
764    /// Always returns `false` on operating systems that don't support abstract
765    /// addresses.
766    pub 
767    fn is_abstract(&self) -> bool 
768    {
769        if Self::has_abstract_addresses() == true
770        {
771            return self.len > path_offset()  &&  self.addr.sun_path[0] as u8 == b'\0';
772        } 
773        else 
774        {
775            return false;
776        }
777    }
778
779    /// Checks whether the address is a path that begins with '/'.
780    #[cfg(unix)]
781    #[inline]
782    pub 
783    fn is_absolute_path(&self) -> bool 
784    {
785        self.len > path_offset()  &&  self.addr.sun_path[0] as u8 == b'/'
786    }
787
788    /// Checks whether the address is a path that begins with '/' or "C:\".
789    #[cfg(windows)]
790    #[inline]
791    pub 
792    fn is_absolute_path(&self) -> bool 
793    {
794        self.len > path_offset()  &&  
795            (
796                self.addr.sun_path[0] as u8 == b'/' || 
797                (self.addr.sun_path[0] as u8 as char).is_ascii_alphabetic() == true
798            )
799    }
800
801    /// Checks whether the address is a path that doesn't begin with '/'.
802    #[inline]
803    pub 
804    fn is_relative_path(&self) -> bool 
805    {
806        self.len > path_offset()
807            &&  self.addr.sun_path[0] as u8 != b'\0'
808            &&  self.addr.sun_path[0] as u8 != b'/'
809    }
810    /// Checks whether the address is a path.
811    #[inline]
812    pub 
813    fn is_path(&self) -> bool 
814    {
815        self.len > path_offset()  &&  self.addr.sun_path[0] as u8 != b'\0'
816    }
817
818    /// Returns a view of the address that can be pattern matched
819    /// to the differnt types of addresses.
820    ///
821    /// # Examples
822    ///
823    /// ```
824    /// use uds_fork::{UnixSocketAddr, AddrName};
825    /// use std::path::Path;
826    ///
827    /// assert_eq!(
828    ///     UnixSocketAddr::new_unspecified().name(),
829    ///     AddrName::Unnamed
830    /// );
831    /// assert_eq!(
832    ///     UnixSocketAddr::from_path("/var/run/socket.sock").unwrap().name(),
833    ///     AddrName::Path(Path::new("/var/run/socket.sock"))
834    /// );
835    /// if UnixSocketAddr::has_abstract_addresses() {
836    ///     assert_eq!(
837    ///         UnixSocketAddr::from_abstract("tcartsba").unwrap().name(),
838    ///         AddrName::Abstract(b"tcartsba")
839    ///     );
840    /// }
841    /// ```
842    pub 
843    fn name(&self) -> AddrName<'_>
844    {
845        AddrName::from(self)
846    }
847
848    /// Returns the path of a path-based address.
849    pub 
850    fn as_pathname(&self) -> Option<&Path> 
851    {
852        let UnixSocketAddrRef::Path(path) = UnixSocketAddrRef::from(self)
853        else { return None };
854
855        return Some(path);
856    }
857
858    /// Returns the name of an address which is in the abstract namespace.
859    pub 
860    fn as_abstract(&self) -> Option<&[u8]> 
861    {
862        let UnixSocketAddrRef::Abstract(name) = UnixSocketAddrRef::from(self) 
863        else {return None};
864
865        return Some(name);
866    }
867
868    /// Returns a view that can be pattern matched to the differnt types of
869    /// addresses.
870    ///
871    /// # Examples
872    ///
873    #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
874    #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```ignore")]
875    /// use uds_fork::{UnixDatagramExt, UnixSocketAddr, UnixSocketAddrRef};
876    /// use std::os::unix::net::UnixDatagram;
877    /// use tempfile::TempDir;
878    /// use std::path::Path;
879    /// 
880    /// let dir = tempfile::tempdir().unwrap();
881    /// let path = dir.path().join("dgram.socket");
882    ///
883    /// let receiver = UnixDatagram::bind(&path).expect("create datagram socket");
884    /// assert_eq!(
885    ///     receiver.local_unix_addr().unwrap().as_ref(),
886    ///     UnixSocketAddrRef::Path(&path)
887    /// );
888    ///
889    /// let sender = UnixDatagram::unbound().expect("create unbound datagram socket");
890    /// sender.send_to(b"I can't hear you", &path).expect("send");
891    ///
892    /// let mut buf = [0; 100];
893    /// let (len, addr) = receiver.recv_from_unix_addr(&mut buf).unwrap();
894    /// assert_eq!(addr.as_ref(), UnixSocketAddrRef::Unnamed);
895    /// ```
896    pub 
897    fn as_ref(&self) -> UnixSocketAddrRef<'_>
898    {
899        UnixSocketAddrRef::from(self)
900    }
901
902    /// Creates an address from a slice of bytes to place in `sun_path`.
903    ///
904    /// This is a low-level but simple interface for creating addresses by
905    /// other unix socket wrappers without exposing any libc types.  
906    /// The meaning of a slice can vary between operating systems.
907    ///
908    /// `addr` should point to thes start of the "path" part of a socket
909    /// address, with length being the number of valid bytes of the path.
910    /// (Trailing NULs are not stripped by this function.)
911    ///
912    /// # Errors
913    ///
914    /// If the slice is longer than `sun_path`, an error of kind `Other` is
915    /// returned. No other validation of the bytes is performed.
916    ///
917    /// # Examples
918    ///
919    /// A normal path-based address
920    ///
921    /// ```
922    /// # use std::path::Path;
923    /// # use uds_fork::UnixSocketAddr;
924    /// let addr = UnixSocketAddr::from_raw_bytes(b"/tmp/a.sock\0").unwrap();
925    /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/a.sock")));
926    /// assert_eq!(addr.as_raw_bytes(), b"/tmp/a.sock\0");
927    /// ```
928    ///
929    /// On Linux:
930    ///
931    #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
932    #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
933    /// # use uds_fork::UnixSocketAddr;
934    /// let addr = UnixSocketAddr::from_raw_bytes(b"\0a").unwrap();
935    /// assert_eq!(addr.as_abstract(), Some(&b"a"[..]));
936    /// assert_eq!(addr.as_raw_bytes(), b"\0a");
937    /// ```
938    ///
939    /// Elsewhere:
940    ///
941    #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```")]
942    #[cfg_attr(any(target_os="linux", target_os="android"), doc="```no_run")]
943    /// # use uds_fork::UnixSocketAddr;
944    /// let addr = UnixSocketAddr::from_raw_bytes(b"\0a").unwrap();
945    /// assert!(addr.is_unnamed());
946    /// assert_eq!(addr.as_raw_bytes().len(), 2);
947    /// ```
948    ///
949    /// A portable unnamed address:
950    ///
951    /// ```
952    /// # use uds_fork::UnixSocketAddr;
953    /// let addr = UnixSocketAddr::from_raw_bytes(&[]).expect("not too long");
954    /// assert!(addr.is_unnamed());
955    /// assert!(addr.as_raw_bytes().is_empty());
956    /// ```
957    pub 
958    fn from_raw_bytes(addr: &[u8]) -> Result<Self, io::Error> 
959    {
960        if addr.len() <= Self::max_path_len() 
961        {
962            let name = addr;
963            let mut addr = Self::default();
964            addr.addr.sun_path[..name.len()].copy_from_slice(as_char(name));
965            addr.len = path_offset() + name.len() as socklen_t;
966            
967            return Ok(addr);
968        } 
969        else 
970        {
971            return Err(io::Error::new(ErrorKind::InvalidInput, TOO_LONG_DESC));
972        }
973    }
974    /// Returns a low-level view of the address without using any libc types.
975    ///
976    /// The returned slice points to the start of `sun_addr` of the contained
977    /// `sockaddr_un`, and the length is the number of bytes of `sun_addr`
978    /// that were filled out by the OS. Any trailing NUL(s) will be preserved.
979    ///
980    /// # Examples
981    ///
982    /// A normal path-based address:
983    ///
984    #[cfg_attr(any(target_vendor="apple", target_os="openbsd"), doc="```")]
985    #[cfg_attr(not(any(target_vendor="apple", target_os="openbsd")), doc="```ignore")]
986    /// # use std::path::Path;
987    /// # use std::os::unix::net::UnixDatagram;
988    /// # use uds_fork::{UnixSocketAddr, UnixDatagramExt};
989    /// let pathname = "/tmp/a_file";
990    /// let socket = UnixDatagram::bind(pathname).expect("create datagram socket");
991    /// # let _ = std::fs::remove_file(pathname);
992    /// let addr = socket.local_unix_addr().expect("get its address");
993    /// assert!(addr.as_raw_bytes().starts_with(pathname.as_bytes()));
994    /// assert!(addr.as_raw_bytes()[pathname.len()..].iter().all(|&b| b == b'\0' ));
995    /// assert_eq!(addr.as_pathname(), Some(Path::new(pathname)));
996    /// ```
997    ///
998    /// Abstract address:
999    ///
1000    #[cfg_attr(any(target_os="linux", target_os="android"), doc="```")]
1001    #[cfg_attr(not(any(target_os="linux", target_os="android")), doc="```no_run")]
1002    /// # use uds_fork::UnixSocketAddr;
1003    /// let addr = UnixSocketAddr::new("@someone@").unwrap();
1004    /// assert_eq!(addr.as_raw_bytes(), b"\0someone@");
1005    /// ```
1006    ///
1007    /// Unnamed address on macOS, OpenBSD and maybe others:
1008    ///
1009    #[cfg_attr(any(target_vendor="apple", target_os="openbsd"), doc="```")]
1010    #[cfg_attr(not(any(target_vendor="apple", target_os="openbsd")), doc="```ignore")]
1011    /// # use std::os::unix::net::UnixDatagram;
1012    /// # use uds_fork::{UnixSocketAddr, UnixDatagramExt};
1013    /// let socket = UnixDatagram::unbound().expect("create datagram socket");
1014    /// let addr = socket.local_unix_addr().expect("get its unbound address");
1015    /// let bytes = addr.as_raw_bytes();
1016    /// assert!(bytes.len() > 0);
1017    /// assert!(bytes.iter().all(|&b| b == b'\0' ));
1018    /// assert!(addr.is_unnamed());
1019    /// ```
1020    pub 
1021    fn as_raw_bytes(&self) -> &[u8] 
1022    {
1023        as_u8(&self.addr.sun_path[..(self.len-path_offset()) as usize])
1024    }
1025
1026    /// Prepares a `struct sockaddr*` and `socklen_t*` for passing to FFI
1027    /// (such as `getsockname()`, `getpeername()`, or `accept()`),
1028    /// and validate and normalize the produced address afterwards.
1029    ///
1030    /// Validation:
1031    ///
1032    /// * Check that the address family is `AF_UNIX`.
1033    /// * Check that the address wasn't truncated (the `socklen_t` is too big).
1034    ///
1035    /// Normalization:
1036    ///
1037    /// * Ensure path addresses have a trailing NUL byte if there is space.
1038    pub 
1039    fn new_from_ffi<R, F>(call: F) -> Result<(R, Self), io::Error>
1040    where 
1041        F: FnOnce(&mut sockaddr, &mut socklen_t) -> Result<R, io::Error> 
1042    {
1043        let mut addr = Self::new_unspecified();
1044        let capacity = mem::size_of_val(&addr.addr) as socklen_t;
1045        addr.len = capacity;
1046
1047        unsafe 
1048        {
1049            let (addr_ptr, addr_len_ptr) = addr.as_raw_mut_general();
1050            let ret = call(addr_ptr, addr_len_ptr)?;
1051
1052            if addr.addr.sun_family != AF_UNIX as sa_family_t 
1053            {
1054                return Err(
1055                    io::Error::new(
1056                        ErrorKind::InvalidData,
1057                        "file descriptor did not correspond to a Unix socket" // identical to std's
1058                    )
1059                );
1060            }
1061
1062            if addr.is_abstract() == true
1063            {
1064                if addr.len > capacity 
1065                {
1066                    return Err(
1067                        io::Error::new(ErrorKind::InvalidData, "abstract name was too long")
1068                    );
1069                }
1070            } 
1071            else if addr.is_path() == true 
1072            {
1073                if addr.len > capacity+1 
1074                {
1075                    return Err(io::Error::new(ErrorKind::InvalidData, "path was too long"));
1076                    // accept lengths one too big; assume the truncated byte was NUL
1077                } 
1078                else 
1079                {
1080                    // normalize addr.len to include terminating NUL byte if possible
1081                    // and not be greater than capacity
1082                    if addr.len >= capacity 
1083                    {
1084                        addr.len = capacity;
1085                    } 
1086                    else if addr.addr.sun_path[(addr.len-1-path_offset()) as usize] != 0 
1087                    {
1088                        addr.len += 1;
1089                        addr.addr.sun_path[(addr.len-1-path_offset()) as usize] = 0;
1090                    }
1091                }
1092            }
1093            
1094            return Ok((ret, addr));
1095        }
1096    }
1097
1098    pub unsafe 
1099    fn from_ref(addr: &sockaddr,  len: socklen_t) -> Result<Self, io::Error> 
1100    {
1101        let mut copy = Self::new_unspecified();
1102
1103        if len < path_offset() 
1104        {
1105            return Err(io::Error::new(ErrorKind::InvalidInput, "address length is too short"));
1106        } 
1107        else if len > mem::size_of::<sockaddr_un>() as socklen_t 
1108        {
1109            return Err(io::Error::new(ErrorKind::InvalidInput, TOO_LONG_DESC));
1110        } 
1111        else if addr.sa_family != AF_UNIX as sa_family_t 
1112        {
1113            return Err(io::Error::new(ErrorKind::InvalidData, "not an unix socket address"));
1114        } 
1115        else 
1116        {
1117            let addr = addr as *const sockaddr  as *const sockaddr_un;
1118            let sun_path_ptr = unsafe { (&*addr).sun_path.as_ptr() };
1119            let path_len = (len - path_offset()) as usize;
1120            let sun_path = unsafe { slice::from_raw_parts(sun_path_ptr, path_len) };
1121            
1122            copy.addr.sun_path[..path_len].copy_from_slice(sun_path);
1123            copy.len = len;
1124            
1125            return Ok(copy);
1126        }
1127    }
1128
1129    /// Creates an `UnixSocketAddr` from a pointer to a generic [libc::sockaddr_storage] and
1130    /// a length.
1131    /// 
1132    /// If len is  == 0 or < path_offset() an `unspecified` type is returned.
1133    ///
1134    /// # Safety
1135    ///
1136    /// * `len` must not be greater than the size of the memory `addr` points to.
1137    /// * `addr` must point to valid memory if `len` is greater than zero, or be NULL.
1138    pub unsafe 
1139    fn from_sockaddr_storage(addr: &sockaddr_storage,  len: socklen_t) -> Result<Self, io::Error> 
1140    {
1141        let mut copy = Self::new_unspecified();
1142
1143        if len < path_offset() 
1144        {
1145            return Ok(copy);
1146        } 
1147        else if len > mem::size_of::<sockaddr_un>() as socklen_t 
1148        {
1149            return Err(io::Error::new(ErrorKind::InvalidInput, TOO_LONG_DESC));
1150        } 
1151        else if addr.ss_family != AF_UNIX as sa_family_t 
1152        {
1153            return Err(io::Error::new(ErrorKind::InvalidData, "not an unix socket address"));
1154        } 
1155        else 
1156        {
1157            let addr = addr as *const sockaddr_storage as *const sockaddr_un;
1158            let sun_path_ptr = unsafe { (&*addr).sun_path.as_ptr() };
1159            let path_len = (len - path_offset()) as usize;
1160            let sun_path = unsafe { slice::from_raw_parts(sun_path_ptr, path_len) };
1161            
1162            copy.addr.sun_path[..path_len].copy_from_slice(sun_path);
1163            copy.len = len;
1164            
1165            return Ok(copy);
1166        }
1167    }
1168
1169    /// Creates an `UnixSocketAddr` from a pointer to a generic `sockaddr` and
1170    /// a length.
1171    ///
1172    /// # Safety
1173    ///
1174    /// * `len` must not be greater than the size of the memory `addr` points to.
1175    /// * `addr` must point to valid memory if `len` is greater than zero, or be NULL.
1176    pub unsafe 
1177    fn from_raw(addr: *const sockaddr,  len: socklen_t) -> Result<Self, io::Error> 
1178    {
1179        let mut copy = Self::new_unspecified();
1180
1181        if addr.is_null() == true && len == 0 
1182        {
1183            return Ok(Self::new_unspecified());
1184        } 
1185        else if addr.is_null() == true
1186        {
1187            return Err(io::Error::new(ErrorKind::InvalidInput, "addr is NULL"));
1188        } 
1189        else if len < path_offset() 
1190        {
1191            return Err(io::Error::new(ErrorKind::InvalidInput, "address length is too short"));
1192        } 
1193        else if len > mem::size_of::<sockaddr_un>() as socklen_t 
1194        {
1195            return Err(io::Error::new(ErrorKind::InvalidInput, TOO_LONG_DESC));
1196        } 
1197        else if unsafe { (&*addr).sa_family } != AF_UNIX as sa_family_t 
1198        {
1199            return Err(io::Error::new(ErrorKind::InvalidData, "not an unix socket address"));
1200        } 
1201        else 
1202        {
1203            let addr = addr as *const sockaddr_un;
1204            let sun_path_ptr = unsafe { (&*addr).sun_path.as_ptr() };
1205            let path_len = (len - path_offset()) as usize;
1206            let sun_path = unsafe { slice::from_raw_parts(sun_path_ptr, path_len) };
1207            
1208            copy.addr.sun_path[..path_len].copy_from_slice(sun_path);
1209            copy.len = len;
1210            
1211            return Ok(copy);
1212        }
1213    }
1214
1215    /// Creates an `UnixSocketAddr` without any validation.
1216    ///
1217    /// # Safety
1218    ///
1219    /// * `len` must be `<= size_of::<sockaddr_un>()`.
1220    /// * `addr.sun_family` should be `AF_UNIX` or strange things might happen.
1221    /// * `addr.sun_len`, if it exists, should be zero (but is probably ignored).
1222    pub unsafe 
1223    fn from_raw_unchecked(addr: sockaddr_un,  len: socklen_t) -> Self 
1224    {
1225        Self{addr, len}
1226    }
1227
1228    /// Splits the address into its inner, raw parts.
1229    pub 
1230    fn into_raw(self) -> (sockaddr_un, socklen_t) 
1231    {
1232        (self.addr, self.len)
1233    }
1234
1235    /// Returns a general `sockaddr` reference to the address and its length.
1236    ///
1237    /// Useful for passing to `bind()`, `connect()`, `sendto()` or other FFI.
1238    ///
1239    /// Pathname addresses are not guaranteed to be NUL-terminated on most OSes:
1240    /// Most paths will be NUL-terminated, but paths that just fit within `sockaddr_un.sun_len`
1241    /// (iow their length is equal to `addr.sun_len[..].len()`) will not have one.  
1242    /// Therefore do not call `SUN_LEN()` on unknown addresses.  
1243    /// See [`max_path_len()`](#tymethod.max_path_len) for which OSes this affects.
1244    pub 
1245    fn as_raw_general(&self) -> (&sockaddr, socklen_t) 
1246    {
1247        // SAFETY: sockaddr is a super-type of sockaddr_un.
1248        (unsafe { &*(&self.addr as *const sockaddr_un as *const sockaddr) }, self.len)
1249    }
1250
1251    /// Returns a reference to the inner `struct sockaddr_un`, and length.
1252    ///
1253    /// Pathname addresses are not guaranteed to be NUL-terminated on most OSes:
1254    /// Most paths will be NUL-terminated, but paths that just fit within `sockaddr_un.sun_len`
1255    /// (iow their length is equal to `addr.sun_len[..].len()`) will not have one.  
1256    /// Therefore do not call `SUN_LEN()` on unknown addresses.  
1257    /// See [`max_path_len()`](#tymethod.max_path_len) for which OSes this affects.
1258    pub 
1259    fn as_raw(&self) -> (&sockaddr_un, socklen_t) 
1260    {
1261        (&self.addr, self.len)
1262    }
1263
1264    /// Returns mutable references to a general `struct sockaddr` and `socklen_t`.
1265    ///
1266    /// If passing to `getpeername()`, `accept()` or similar, remember to set
1267    /// the length to the capacity,
1268    /// and consider using [`new_from_ffi()`](#method.new_from_ffi) instead.
1269    ///
1270    /// Pathname addresses are not guaranteed to be NUL-terminated on most OSes:
1271    /// Most paths will be NUL-terminated, but paths that just fit within `sockaddr_un.sun_len`
1272    /// (iow their length is equal to `addr.sun_len[..].len()`) will not have one.  
1273    /// Therefore do not call `SUN_LEN()` on unknown addresses.  
1274    /// See [`max_path_len()`](#tymethod.max_path_len) for which OSes this affects.
1275    ///
1276    /// # Safety
1277    ///
1278    /// Assigning a value > `sizeof(struct sockaddr_un)` to the `socklen_t`
1279    /// reference might lead to out-of-bounds reads later.
1280    pub unsafe 
1281    fn as_raw_mut_general(&mut self) -> (&mut sockaddr, &mut socklen_t) 
1282    {
1283        // SAFETY: sockaddr is a super-type of sockaddr_un.
1284        (unsafe { &mut*(&mut self.addr as *mut sockaddr_un as *mut sockaddr) }, &mut self.len)
1285    }
1286
1287    pub unsafe 
1288    fn as_raw_ptr_general(&self) -> (*const sockaddr, socklen_t) 
1289    {
1290        // SAFETY: sockaddr is a super-type of sockaddr_un.
1291        (&self.addr as *const sockaddr_un as *const sockaddr, self.len)
1292    }
1293
1294    /// Returns mutable references to the inner `struct sockaddr_un` and length.
1295    ///
1296    /// Pathname addresses are not guaranteed to be NUL-terminated on most OSes:
1297    /// Most paths will be NUL-terminated, but paths that just fit within `sockaddr_un.sun_len`
1298    /// (iow their length is equal to `addr.sun_len[..].len()`) will not have one.  
1299    /// Therefore do not call `SUN_LEN()` on unknown addresses.  
1300    /// See [`max_path_len()`](#tymethod.max_path_len) for which OSes this affects
1301    ///
1302    /// # Safety
1303    ///
1304    /// Assigning a value > `sizeof(struct sockaddr_un)` to the `socklen_t`
1305    /// reference might lead to out-of-bounds reads later.
1306    pub unsafe 
1307    fn as_raw_mut(&mut self) -> (&mut sockaddr_un, &mut socklen_t) 
1308    {
1309        (&mut self.addr, &mut self.len)
1310    }
1311}
1312
1313impl Default for UnixSocketAddr 
1314{
1315    fn default() -> Self 
1316    {
1317        Self::new_unspecified()
1318    }
1319}
1320
1321impl PartialEq for UnixSocketAddr 
1322{
1323    fn eq(&self, other: &Self) -> bool 
1324    {
1325        self.as_ref() == other.as_ref()
1326    }
1327}
1328
1329impl Eq for UnixSocketAddr {}
1330
1331impl Hash for UnixSocketAddr 
1332{
1333    fn hash<H: Hasher>(&self,  hasher: &mut H) 
1334    {
1335        self.as_ref().hash(hasher)
1336    }
1337}
1338
1339impl PartialEq<[u8]> for UnixSocketAddr 
1340{
1341    fn eq(&self,  unescaped: &[u8]) -> bool 
1342    {
1343        match (self.as_ref(), unescaped.first()) 
1344        {
1345            #[cfg(unix)]
1346            (UnixSocketAddrRef::Path(path), Some(_)) => 
1347                path.as_os_str().as_bytes() == unescaped,
1348            #[cfg(windows)]
1349            (UnixSocketAddrRef::Path(path), Some(_)) => 
1350                path.as_os_str().as_encoded_bytes() == unescaped,
1351            (UnixSocketAddrRef::Abstract(name), Some(b'\0')) => 
1352                name == &unescaped[1..],
1353            (UnixSocketAddrRef::Unnamed, None) => 
1354                true,
1355            (_, _) => 
1356                false,
1357        }
1358    }
1359}
1360impl PartialEq<UnixSocketAddr> for [u8]  
1361{
1362    fn eq(&self,  addr: &UnixSocketAddr) -> bool 
1363    {
1364        addr == self
1365    }
1366}
1367