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