fcnetd_client/
socket.rs

1use std::{future::Future, path::Path};
2
3#[cfg(feature = "smol-socket")]
4use futures_lite::{AsyncBufReadExt as SmolAsyncBufReadExt, AsyncWriteExt as SmolAsyncWriteExt, StreamExt};
5#[cfg(feature = "tokio-socket")]
6use tokio::io::{AsyncBufReadExt as TokioAsyncBufReadExt, AsyncWriteExt as TokioAsyncWriteExt};
7
8/// The [Socket] trait is a basic abstraction over an underlying asynchronous Unix socket connection used
9/// by this crate to connect to fcnetd. This allows for different async I/O implementations to be used
10/// interchangeably by implementing this trait.
11pub trait Socket: Send + Sync + Sized + Unpin {
12    fn connect(socket_path: &Path) -> impl Future<Output = Result<Self, std::io::Error>> + Send;
13
14    fn write_line(&mut self, line: String) -> impl Future<Output = Result<(), std::io::Error>> + Send;
15
16    fn read_line(&mut self) -> impl Future<Output = Result<Option<String>, std::io::Error>> + Send;
17}
18
19/// A [Socket] that uses a [UnixStream](tokio::net::UnixStream) from the [tokio] crate internally.
20#[cfg(feature = "tokio-socket")]
21#[cfg_attr(docsrs, doc(cfg(feature = "tokio-socket")))]
22pub struct TokioSocket(tokio::net::UnixStream);
23
24#[cfg(feature = "tokio-socket")]
25#[cfg_attr(docsrs, doc(cfg(feature = "tokio-socket")))]
26impl Socket for TokioSocket {
27    async fn connect(socket_path: &Path) -> Result<Self, std::io::Error> {
28        tokio::net::UnixStream::connect(socket_path).await.map(Self)
29    }
30
31    async fn write_line(&mut self, line: String) -> Result<(), std::io::Error> {
32        self.0.write_all(format!("{line}\n").as_bytes()).await
33    }
34
35    async fn read_line(&mut self) -> Result<Option<String>, std::io::Error> {
36        let mut lines = tokio::io::BufReader::new(&mut self.0).lines();
37        lines.next_line().await
38    }
39}
40
41/// A [Socket] that uses a [UnixStream](async_net::unix::UnixStream) from the [async_net] crate internally.
42#[cfg(feature = "smol-socket")]
43#[cfg_attr(docsrs, doc(cfg(feature = "smol-socket")))]
44pub struct SmolSocket(async_net::unix::UnixStream);
45
46#[cfg(feature = "smol-socket")]
47#[cfg_attr(docsrs, doc(cfg(feature = "smol-socket")))]
48impl Socket for SmolSocket {
49    async fn connect(socket_path: &Path) -> Result<Self, std::io::Error> {
50        async_net::unix::UnixStream::connect(socket_path).await.map(Self)
51    }
52
53    async fn write_line(&mut self, line: String) -> Result<(), std::io::Error> {
54        self.0.write_all(format!("{line}\n").as_bytes()).await
55    }
56
57    async fn read_line(&mut self) -> Result<Option<String>, std::io::Error> {
58        let mut lines = futures_lite::io::BufReader::new(&mut self.0).lines();
59        lines.next().await.transpose()
60    }
61}