hyper_unix_socket/
client.rs

1use std::fmt;
2use std::future::Future;
3use std::marker::PhantomData;
4use std::path::Path;
5use std::pin::Pin;
6use std::task::{self, Context, Poll};
7
8use hyper::Uri;
9use hyper_util::rt::TokioIo;
10use pin_project_lite::pin_project;
11use tokio::net::UnixStream;
12use tower_service::Service;
13
14use super::UnixSocketConnection;
15
16type BoxError = Box<dyn std::error::Error + Send + Sync>;
17
18/// A Connector for a Socket.
19#[derive(Clone)]
20pub struct UnixSocketConnector<P> {
21    socket_path: P,
22}
23
24impl<P: AsRef<Path>> UnixSocketConnector<P> {
25    /// Construct a new `UnixStreamConnector`.
26    #[must_use]
27    pub fn new(socket_path: P) -> Self {
28        Self { socket_path }
29    }
30}
31
32impl<T: AsRef<Path>> From<T> for UnixSocketConnector<T> {
33    fn from(args: T) -> UnixSocketConnector<T> {
34        UnixSocketConnector { socket_path: args }
35    }
36}
37
38impl<T> fmt::Debug for UnixSocketConnector<T> {
39    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40        f.debug_struct("HttpsConnector").finish_non_exhaustive()
41    }
42}
43
44impl<T> Service<Uri> for UnixSocketConnector<T>
45where
46    T: AsRef<Path> + Clone + Send,
47{
48    type Response = UnixSocketConnection;
49    type Error = BoxError;
50    type Future = UnixStreamConnecting;
51
52    fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
53        Poll::Ready(Ok(()))
54    }
55
56    fn call(&mut self, _: Uri) -> Self::Future {
57        let socket_path = self.socket_path.as_ref().to_owned();
58
59        let fut = async move {
60            UnixStream::connect(socket_path)
61                .await
62                .map(TokioIo::new)
63                .map(Into::into)
64                .map_err(Into::into)
65        };
66
67        UnixStreamConnecting {
68            fut: Box::pin(fut),
69            _marker: PhantomData,
70        }
71    }
72}
73
74type ConnectResult = Result<UnixSocketConnection, BoxError>;
75type BoxConnecting = Pin<Box<dyn Future<Output = ConnectResult> + Send>>;
76
77pin_project! {
78    #[must_use = "futures do nothing unless polled"]
79    #[allow(missing_debug_implementations)]
80    pub struct UnixStreamConnecting<R = ()> {
81        #[pin]
82        fut: BoxConnecting,
83        _marker: PhantomData<R>,
84    }
85}
86
87impl<R> Future for UnixStreamConnecting<R> {
88    type Output = ConnectResult;
89
90    fn poll(self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
91        self.project().fut.poll(cx)
92    }
93}
94
95impl<R> fmt::Debug for UnixStreamConnecting<R> {
96    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
97        f.pad("UnixStreamConnecting")
98    }
99}