ssip_client_async/
fifo.rs1use std::env;
11use std::io;
12use std::path::{Path, PathBuf};
13
14const SPEECHD_APPLICATION_NAME: &str = "speech-dispatcher";
15const SPEECHD_SOCKET_NAME: &str = "speechd.sock";
16
17struct FifoPath {
18 path: Option<PathBuf>,
19}
20
21impl FifoPath {
22 fn new() -> FifoPath {
23 FifoPath { path: None }
24 }
25
26 fn set<P>(&mut self, path: P)
27 where
28 P: AsRef<Path>,
29 {
30 self.path = Some(path.as_ref().to_path_buf());
31 }
32
33 fn default_path() -> io::Result<PathBuf> {
35 match env::var_os("XDG_RUNTIME_DIR") {
36 Some(runtime_dir) => Ok(PathBuf::from(runtime_dir)
37 .join(SPEECHD_APPLICATION_NAME)
38 .join(SPEECHD_SOCKET_NAME)),
39 None => Err(io::Error::new(
40 io::ErrorKind::NotFound,
41 "unix socket not found",
42 )),
43 }
44 }
45
46 fn get(&self) -> io::Result<PathBuf> {
47 match &self.path {
48 Some(path) => Ok(path.to_path_buf()),
49 _ => FifoPath::default_path(),
50 }
51 }
52}
53
54pub mod synchronous {
55 use std::io::{self, BufReader, BufWriter};
56 pub use std::os::unix::net::UnixStream;
57 use std::path::Path;
58 use std::process::Command;
59 use std::time::Duration;
60
61 use crate::client::Client;
62 use crate::net::StreamMode;
63
64 use super::FifoPath;
65
66 pub struct Builder {
67 path: FifoPath,
68 mode: StreamMode,
69 }
70 impl Default for Builder {
71 fn default() -> Self {
72 Self::new()
73 }
74 }
75
76 impl Builder {
77 pub fn new() -> Self {
78 Self {
79 path: FifoPath::new(),
80 mode: StreamMode::Blocking,
81 }
82 }
83
84 pub fn path<P>(&mut self, socket_path: P) -> &mut Self
85 where
86 P: AsRef<Path>,
87 {
88 self.path.set(socket_path);
89 self
90 }
91
92 pub fn timeout(&mut self, read_timeout: Duration) -> &mut Self {
93 self.mode = StreamMode::TimeOut(read_timeout);
94 self
95 }
96
97 pub fn nonblocking(&mut self) -> &mut Self {
98 self.mode = StreamMode::NonBlocking;
99 self
100 }
101
102 pub fn with_spawn(&self) -> io::Result<&Self> {
104 Command::new("speech-dispatcher")
105 .args(["--spawn"])
107 .output()?;
108 Ok(self)
109 }
110
111 pub fn build(&self) -> io::Result<Client<UnixStream>> {
112 let input = UnixStream::connect(self.path.get()?)?;
113 match self.mode {
114 StreamMode::Blocking => input.set_nonblocking(false)?,
115 StreamMode::NonBlocking => input.set_nonblocking(true)?,
116 StreamMode::TimeOut(timeout) => input.set_read_timeout(Some(timeout))?,
117 }
118
119 let output = input.try_clone()?;
120 Ok(Client::new(BufReader::new(input), BufWriter::new(output)))
121 }
122 }
123}
124
125#[cfg(feature = "async-io")]
126pub mod asynchronous_async_io {
127 use crate::async_io::AsyncClient;
128 use async_net::unix::UnixStream;
129 use futures_lite::io::{self, BufReader};
130 use std::path::Path;
131
132 use super::FifoPath;
133
134 pub struct Builder {
135 path: FifoPath,
136 }
137 impl Default for Builder {
138 fn default() -> Self {
139 Self {
140 path: FifoPath::new(),
141 }
142 }
143 }
144
145 impl Builder {
146 pub fn path<P>(&mut self, socket_path: P) -> &mut Self
147 where
148 P: AsRef<Path>,
149 {
150 self.path.set(socket_path);
151 self
152 }
153
154 pub async fn build(&self) -> io::Result<AsyncClient<BufReader<UnixStream>, UnixStream>> {
155 let stream = UnixStream::connect(self.path.get()?).await?;
156 let (unbuf_read_stream, write_stream) = (stream.clone(), stream);
157 let read_stream = BufReader::new(unbuf_read_stream);
158 Ok(AsyncClient::new(read_stream, write_stream))
159 }
160 }
161}
162
163#[cfg(feature = "async-mio")]
164pub mod asynchronous_mio {
165 pub use mio::net::UnixStream;
166 use std::io::{self, BufReader, BufWriter};
167 use std::os::unix::net::UnixStream as StdUnixStream;
168 use std::path::Path;
169
170 use crate::client::MioClient as Client;
171
172 use super::FifoPath;
173
174 pub struct Builder {
175 path: FifoPath,
176 }
177 impl Default for Builder {
178 fn default() -> Self {
179 Self::new()
180 }
181 }
182
183 impl Builder {
184 pub fn new() -> Self {
185 Self {
186 path: FifoPath::new(),
187 }
188 }
189
190 fn non_blocking(socket: StdUnixStream) -> io::Result<StdUnixStream> {
191 socket.set_nonblocking(true)?;
192 Ok(socket)
193 }
194
195 pub fn path<P>(&mut self, socket_path: P) -> &mut Self
196 where
197 P: AsRef<Path>,
198 {
199 self.path.set(socket_path);
200 self
201 }
202
203 pub fn build(&self) -> io::Result<Client<UnixStream>> {
204 let stream = StdUnixStream::connect(self.path.get()?)?;
205 Ok(Client::new(
206 BufReader::new(UnixStream::from_std(Self::non_blocking(
207 stream.try_clone()?,
208 )?)),
209 BufWriter::new(UnixStream::from_std(Self::non_blocking(stream)?)),
210 ))
211 }
212 }
213}
214
215#[cfg(feature = "tokio")]
216pub mod asynchronous_tokio {
217 use std::path::Path;
218 use tokio::io::{self, BufReader as AsyncBufReader, BufWriter as AsyncBufWriter};
219 pub use tokio::net::{unix::OwnedReadHalf, unix::OwnedWriteHalf, UnixStream};
220
221 use crate::tokio::AsyncClient;
222
223 use super::FifoPath;
224
225 pub struct Builder {
226 path: FifoPath,
227 }
228 impl Default for Builder {
229 fn default() -> Self {
230 Self {
231 path: FifoPath::new(),
232 }
233 }
234 }
235
236 impl Builder {
237 pub fn path<P>(&mut self, socket_path: P) -> &mut Self
238 where
239 P: AsRef<Path>,
240 {
241 self.path.set(socket_path);
242 self
243 }
244
245 pub async fn build(
246 &self,
247 ) -> io::Result<AsyncClient<AsyncBufReader<OwnedReadHalf>, AsyncBufWriter<OwnedWriteHalf>>>
248 {
249 let (read_stream, write_stream) =
250 UnixStream::connect(self.path.get()?).await?.into_split();
251 Ok(AsyncClient::new(
252 AsyncBufReader::new(read_stream),
253 AsyncBufWriter::new(write_stream),
254 ))
255 }
256 }
257}
258
259#[cfg(test)]
260mod tests {
261
262 #[test]
263 fn test_fifo_path() -> std::io::Result<()> {
264 if std::env::var("XDG_RUNTIME_DIR").is_ok() {
265 let socket_path = super::FifoPath::new();
266 assert!(socket_path
267 .get()?
268 .to_str()
269 .unwrap()
270 .ends_with("/speech-dispatcher/speechd.sock"));
271 }
272 Ok(())
273 }
274}