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
68pub trait UnixSocketAddressExtManual: IsA<UnixSocketAddress> + 'static {
69 #[doc(alias = "g_unix_socket_address_get_path")]
70 #[doc(alias = "get_path")]
71 fn path(&self) -> Option<UnixSocketAddressPath<'_>> {
72 use self::UnixSocketAddressPath::*;
73
74 let path = unsafe {
75 let path = ffi::g_unix_socket_address_get_path(self.as_ref().to_glib_none().0);
76 if path.is_null() || self.path_len() == 0 {
77 &[]
78 } else {
79 slice::from_raw_parts(path as *const u8, self.path_len())
80 }
81 };
82 match self.address_type() {
83 UnixSocketAddressType::Anonymous => Some(Anonymous),
84 #[cfg(not(docsrs))]
85 UnixSocketAddressType::Path => Some(Path(path::Path::new(OsStr::from_bytes(path)))),
86 #[cfg(docsrs)]
87 UnixSocketAddressType::Path => unreachable!(),
88 UnixSocketAddressType::Abstract => Some(Abstract(path)),
89 UnixSocketAddressType::AbstractPadded => Some(AbstractPadded(path)),
90 UnixSocketAddressType::Invalid | UnixSocketAddressType::__Unknown(_) => None,
91 }
92 }
93}
94
95impl<O: IsA<UnixSocketAddress>> UnixSocketAddressExtManual for O {}
96
97#[cfg(test)]
98mod test {
99 use super::*;
100
101 #[test]
103 fn check_path() {
104 let mut os_string = std::ffi::OsString::with_capacity(100);
105 os_string.push("/tmp/foo");
106 let path = os_string.as_ref();
107
108 let addr = UnixSocketAddress::new(path);
109 assert_eq!(addr.path_len(), 8);
110 assert_eq!(addr.path_as_array().unwrap().as_ref(), b"/tmp/foo");
111
112 let addr = UnixSocketAddress::with_type(UnixSocketAddressPath::Path(path));
113 assert_eq!(addr.path_len(), 8);
114 assert_eq!(addr.path_as_array().unwrap().as_ref(), b"/tmp/foo");
115 }
116}