std/os/windows/net/
addr.rs1#![unstable(feature = "windows_unix_domain_sockets", issue = "150487")]
2use crate::bstr::ByteStr;
3use crate::ffi::OsStr;
4use crate::path::Path;
5#[cfg(not(doc))]
6use crate::sys::c::{AF_UNIX, SOCKADDR, SOCKADDR_UN};
7use crate::sys::cvt_nz;
8use crate::{fmt, io, mem, ptr};
9
10#[cfg(not(doc))]
11pub fn sockaddr_un(path: &Path) -> io::Result<(SOCKADDR_UN, usize)> {
12 let mut addr: SOCKADDR_UN = unsafe { mem::zeroed() };
14 addr.sun_family = AF_UNIX;
15
16 let bytes = path
18 .to_str()
19 .ok_or(io::const_error!(io::ErrorKind::InvalidInput, "path must be valid UTF-8"))?
20 .as_bytes();
21 if bytes.len() >= addr.sun_path.len() {
22 return Err(io::const_error!(io::ErrorKind::InvalidInput, "path too long"));
23 }
24 unsafe {
29 ptr::copy_nonoverlapping(bytes.as_ptr(), addr.sun_path.as_mut_ptr().cast(), bytes.len())
30 };
31
32 let len = SUN_PATH_OFFSET + bytes.len() + 1;
33 Ok((addr, len))
34}
35#[cfg(not(doc))]
36const SUN_PATH_OFFSET: usize = mem::offset_of!(SOCKADDR_UN, sun_path);
37pub struct SocketAddr {
38 #[cfg(not(doc))]
39 pub(super) addr: SOCKADDR_UN,
40 pub(super) len: u32, }
42impl fmt::Debug for SocketAddr {
43 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
44 match self.address() {
45 AddressKind::Unnamed => write!(fmt, "(unnamed)"),
46 AddressKind::Abstract(name) => write!(fmt, "{name:?} (abstract)"),
47 AddressKind::Pathname(path) => write!(fmt, "{path:?} (pathname)"),
48 }
49 }
50}
51
52impl SocketAddr {
53 #[cfg(not(doc))]
54 pub(super) fn new<F>(f: F) -> io::Result<SocketAddr>
55 where
56 F: FnOnce(*mut SOCKADDR, *mut i32) -> i32,
57 {
58 unsafe {
59 let mut addr: SOCKADDR_UN = mem::zeroed();
60 let mut len = mem::size_of::<SOCKADDR_UN>() as i32;
61 cvt_nz(f(&raw mut addr as *mut _, &mut len))?;
62 SocketAddr::from_parts(addr, len)
63 }
64 }
65 #[cfg(not(doc))]
66 pub(super) fn from_parts(addr: SOCKADDR_UN, len: i32) -> io::Result<SocketAddr> {
67 if addr.sun_family != AF_UNIX {
68 Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid address family"))
69 } else if len < SUN_PATH_OFFSET as _ || len > mem::size_of::<SOCKADDR_UN>() as _ {
70 Err(io::const_error!(io::ErrorKind::InvalidInput, "invalid address length"))
71 } else {
72 Ok(SocketAddr { addr, len: len as _ })
73 }
74 }
75
76 pub fn as_pathname(&self) -> Option<&Path> {
95 if let AddressKind::Pathname(path) = self.address() { Some(path) } else { None }
96 }
97
98 pub fn from_pathname<P>(path: P) -> io::Result<SocketAddr>
128 where
129 P: AsRef<Path>,
130 {
131 sockaddr_un(path.as_ref()).map(|(addr, len)| SocketAddr { addr, len: len as _ })
132 }
133 fn address(&self) -> AddressKind<'_> {
134 let len = self.len as usize - SUN_PATH_OFFSET;
135 let path = unsafe { mem::transmute::<&[i8], &[u8]>(&self.addr.sun_path) };
136
137 if len == 0 {
138 AddressKind::Unnamed
139 } else if self.addr.sun_path[0] == 0 {
140 AddressKind::Abstract(ByteStr::from_bytes(&path[1..len]))
141 } else {
142 AddressKind::Pathname(unsafe {
143 OsStr::from_encoded_bytes_unchecked(&path[..len - 1]).as_ref()
144 })
145 }
146 }
147
148 pub fn is_unnamed(&self) -> bool {
166 matches!(self.address(), AddressKind::Unnamed)
167 }
168}
169enum AddressKind<'a> {
170 Unnamed,
171 Pathname(&'a Path),
172 Abstract(&'a ByteStr),
173}