gio/
unix_socket_address.rs1#[cfg(not(docsrs))]
4use std::ffi::OsStr;
5#[cfg(unix)]
6#[cfg(not(docsrs))]
7use std::os::unix::ffi::OsStrExt;
8use std::{path, ptr, slice};
9
10use glib::translate::*;
11
12use crate::{ffi, prelude::*, SocketAddress, UnixSocketAddress, UnixSocketAddressType};
13
14#[derive(Debug)]
15pub enum UnixSocketAddressPath<'a> {
16 Path(&'a path::Path),
17 Anonymous,
18 Abstract(&'a [u8]),
19 AbstractPadded(&'a [u8]),
20}
21
22impl UnixSocketAddressPath<'_> {
23 fn to_type(&self) -> UnixSocketAddressType {
24 use self::UnixSocketAddressPath::*;
25
26 match *self {
27 Path(_) => UnixSocketAddressType::Path,
28 Anonymous => UnixSocketAddressType::Anonymous,
29 Abstract(_) => UnixSocketAddressType::Abstract,
30 AbstractPadded(_) => UnixSocketAddressType::AbstractPadded,
31 }
32 }
33}
34
35impl UnixSocketAddress {
36 #[doc(alias = "g_unix_socket_address_new")]
37 pub fn new(path: &path::Path) -> UnixSocketAddress {
38 unsafe {
39 SocketAddress::from_glib_full(ffi::g_unix_socket_address_new(path.to_glib_none().0))
40 .unsafe_cast()
41 }
42 }
43
44 #[doc(alias = "g_unix_socket_address_new_with_type")]
45 pub fn with_type(address_type: UnixSocketAddressPath) -> Self {
46 use self::UnixSocketAddressPath::*;
47
48 let type_ = address_type.to_type();
49 let new = |ptr, len| unsafe {
50 SocketAddress::from_glib_full(ffi::g_unix_socket_address_new_with_type(
51 ptr,
52 len,
53 type_.into_glib(),
54 ))
55 .unsafe_cast()
56 };
57 match address_type {
58 Path(path) => new(path.to_glib_none().0, -1),
59 Abstract(path) | AbstractPadded(path) => new(
60 path.to_glib_none().0 as *mut libc::c_char,
61 path.len() as i32,
62 ),
63 Anonymous => new(ptr::null_mut(), 0),
64 }
65 }
66}
67
68mod sealed {
69 pub trait Sealed {}
70 impl<T: super::IsA<super::UnixSocketAddress>> Sealed for T {}
71}
72
73pub trait UnixSocketAddressExtManual: sealed::Sealed + IsA<UnixSocketAddress> + 'static {
74 #[doc(alias = "g_unix_socket_address_get_path")]
75 #[doc(alias = "get_path")]
76 fn path(&self) -> Option<UnixSocketAddressPath> {
77 use self::UnixSocketAddressPath::*;
78
79 let path = unsafe {
80 let path = ffi::g_unix_socket_address_get_path(self.as_ref().to_glib_none().0);
81 if path.is_null() || self.path_len() == 0 {
82 &[]
83 } else {
84 slice::from_raw_parts(path as *const u8, self.path_len())
85 }
86 };
87 match self.address_type() {
88 UnixSocketAddressType::Anonymous => Some(Anonymous),
89 #[cfg(not(docsrs))]
90 UnixSocketAddressType::Path => Some(Path(path::Path::new(OsStr::from_bytes(path)))),
91 #[cfg(docsrs)]
92 UnixSocketAddressType::Path => unreachable!(),
93 UnixSocketAddressType::Abstract => Some(Abstract(path)),
94 UnixSocketAddressType::AbstractPadded => Some(AbstractPadded(path)),
95 UnixSocketAddressType::Invalid | UnixSocketAddressType::__Unknown(_) => None,
96 }
97 }
98}
99
100impl<O: IsA<UnixSocketAddress>> UnixSocketAddressExtManual for O {}
101
102#[cfg(test)]
103mod test {
104 use super::*;
105
106 #[test]
108 fn check_path() {
109 let mut os_string = std::ffi::OsString::with_capacity(100);
110 os_string.push("/tmp/foo");
111 let path = os_string.as_ref();
112
113 let addr = UnixSocketAddress::new(path);
114 assert_eq!(addr.path_len(), 8);
115 assert_eq!(addr.path_as_array().unwrap().as_ref(), b"/tmp/foo");
116
117 let addr = UnixSocketAddress::with_type(UnixSocketAddressPath::Path(path));
118 assert_eq!(addr.path_len(), 8);
119 assert_eq!(addr.path_as_array().unwrap().as_ref(), b"/tmp/foo");
120 }
121}