alloy_transport_ipc/connect.rs
1use interprocess::local_socket as ls;
2use std::io;
3
4pub(crate) fn to_name(path: &std::ffi::OsStr) -> io::Result<ls::Name<'_>> {
5 if cfg!(windows) && !path.as_encoded_bytes().starts_with(br"\\.\pipe\") {
6 ls::ToNsName::to_ns_name::<ls::GenericNamespaced>(path)
7 } else {
8 ls::ToFsName::to_fs_name::<ls::GenericFilePath>(path)
9 }
10}
11
12/// An IPC Connection object.
13#[derive(Clone, Debug)]
14pub struct IpcConnect<T> {
15 inner: T,
16}
17
18impl<T> IpcConnect<T> {
19 /// Create a new IPC connection object for any type T that can be converted into
20 /// `IpcConnect<T>`.
21 pub const fn new(inner: T) -> Self
22 where
23 Self: alloy_pubsub::PubSubConnect,
24 {
25 Self { inner }
26 }
27}
28
29macro_rules! impl_connect {
30 ($target:ty => | $inner:ident | $map:expr) => {
31 impl From<$target> for IpcConnect<$target> {
32 fn from(inner: $target) -> Self {
33 Self { inner }
34 }
35 }
36
37 impl From<IpcConnect<$target>> for $target {
38 fn from(this: IpcConnect<$target>) -> $target {
39 this.inner
40 }
41 }
42
43 impl alloy_pubsub::PubSubConnect for IpcConnect<$target> {
44 fn is_local(&self) -> bool {
45 true
46 }
47
48 async fn connect(
49 &self,
50 ) -> Result<alloy_pubsub::ConnectionHandle, alloy_transport::TransportError> {
51 let $inner = &self.inner;
52 let inner = $map;
53 let name = to_name(inner).map_err(alloy_transport::TransportErrorKind::custom)?;
54 crate::IpcBackend::connect(name)
55 .await
56 .map_err(alloy_transport::TransportErrorKind::custom)
57 }
58 }
59 };
60}
61
62impl_connect!(std::ffi::OsString => |s| s.as_os_str());
63impl_connect!(std::path::PathBuf => |s| s.as_os_str());
64impl_connect!(String => |s| s.as_ref());
65
66#[cfg(unix)]
67impl_connect!(std::ffi::CString => |s| {
68 use std::os::unix::ffi::OsStrExt;
69 std::ffi::OsStr::from_bytes(s.to_bytes())
70});