1#![warn(missing_docs, missing_debug_implementations)]
5#![forbid(clippy::unwrap_used)]
6#![cfg_attr(docsrs, feature(doc_cfg))]
7#![doc = include_str!("../README.md")]
8
9#[cfg(not(windows))]
10mod unix;
11#[cfg(windows)]
12mod win;
13
14use std::io;
15use std::path::{Path, PathBuf};
16use std::pin::Pin;
17use std::task::{Context, Poll};
18
19use futures_util::Stream;
20use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
21
22mod platform {
23 #[cfg(unix)]
24 pub(crate) use crate::unix::{
25 Connection, Endpoint, IpcStream, SecurityAttributes, from_std_stream,
26 };
27 #[cfg(windows)]
28 pub(crate) use crate::win::{Connection, Endpoint, IpcStream, SecurityAttributes};
29}
30
31pub trait IntoIpcPath: Send {
33 fn into_ipc_path(self) -> io::Result<PathBuf>;
35}
36
37impl IntoIpcPath for PathBuf {
38 fn into_ipc_path(self) -> io::Result<PathBuf> {
39 Ok(self)
40 }
41}
42
43#[derive(Debug, PartialEq, Eq, Clone, Copy)]
45pub enum OnConflict {
46 Ignore,
48 Error,
50 Overwrite,
52}
53
54#[derive(Clone, Debug, PartialEq, Eq)]
93pub struct ServerId<T>
94where
95 T: Into<String> + Send,
96{
97 id: T,
98 parent_folder: Option<PathBuf>,
99}
100
101impl<T> ServerId<T>
102where
103 T: Into<String> + Send,
104{
105 pub fn new(id: T) -> Self {
107 Self {
108 id,
109 parent_folder: None,
110 }
111 }
112
113 pub fn parent_folder<P>(mut self, folder: P) -> Self
132 where
133 P: Into<PathBuf>,
134 {
135 self.parent_folder = Some(folder.into());
136 self
137 }
138}
139
140impl<T> IntoIpcPath for ServerId<T>
141where
142 T: Into<String> + Send,
143{
144 fn into_ipc_path(self) -> io::Result<PathBuf> {
145 self.into_ipc_path()
146 }
147}
148
149#[derive(Debug, Clone)]
151pub struct SecurityAttributes(platform::SecurityAttributes);
152
153impl SecurityAttributes {
154 pub fn empty() -> Self {
156 Self(platform::SecurityAttributes::empty())
157 }
158
159 pub fn allow_everyone_connect() -> io::Result<Self> {
163 Ok(Self(platform::SecurityAttributes::allow_everyone_connect()?))
164 }
165
166 pub fn mode(self, mode: u16) -> io::Result<Self> {
170 Ok(Self(self.0.mode(mode)?))
171 }
172
173 pub fn allow_everyone_create() -> io::Result<Self> {
177 Ok(Self(platform::SecurityAttributes::allow_everyone_create()?))
178 }
179}
180
181#[derive(Debug, Clone)]
183pub struct Endpoint(platform::Endpoint);
184
185impl Endpoint {
186 pub fn incoming(self) -> io::Result<IpcStream> {
188 Ok(IpcStream(self.0.incoming()?))
189 }
190 pub fn security_attributes(mut self, security_attributes: SecurityAttributes) -> Self {
192 self.0 = self.0.security_attributes(security_attributes.0);
193 self
194 }
195 pub fn path(&self) -> &Path {
197 self.0.path()
198 }
199 pub async fn connect<P>(path: P) -> io::Result<Connection>
201 where
202 P: IntoIpcPath,
203 {
204 Ok(Connection(platform::Endpoint::connect(path).await?))
205 }
206
207 pub fn new<P>(path: P, on_conflict: OnConflict) -> io::Result<Self>
209 where
210 P: IntoIpcPath,
211 {
212 Ok(Self(platform::Endpoint::new(path, on_conflict)?))
213 }
214}
215
216#[derive(Debug)]
218pub struct Connection(platform::Connection);
219
220impl Connection {
221 #[cfg(unix)]
223 pub async fn from_std_stream(stream: std::os::unix::net::UnixStream) -> io::Result<Self> {
224 Ok(Self(platform::from_std_stream(stream).await?))
225 }
226}
227
228impl AsyncRead for Connection {
229 fn poll_read(
230 self: Pin<&mut Self>,
231 ctx: &mut Context<'_>,
232 buf: &mut ReadBuf<'_>,
233 ) -> Poll<io::Result<()>> {
234 let this = Pin::into_inner(self);
235 Pin::new(&mut this.0).poll_read(ctx, buf)
236 }
237}
238
239impl AsyncWrite for Connection {
240 fn poll_write(
241 self: Pin<&mut Self>,
242 ctx: &mut Context<'_>,
243 buf: &[u8],
244 ) -> Poll<Result<usize, io::Error>> {
245 let this = Pin::into_inner(self);
246 Pin::new(&mut this.0).poll_write(ctx, buf)
247 }
248
249 fn poll_flush(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
250 let this = Pin::into_inner(self);
251 Pin::new(&mut this.0).poll_flush(ctx)
252 }
253
254 fn poll_shutdown(self: Pin<&mut Self>, ctx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
255 let this = Pin::into_inner(self);
256 Pin::new(&mut this.0).poll_shutdown(ctx)
257 }
258}
259
260#[derive(Debug)]
262pub struct IpcStream(platform::IpcStream);
263
264impl IpcStream {
265 #[cfg(unix)]
267 pub fn from_std_listener(listener: std::os::unix::net::UnixListener) -> io::Result<Self> {
268 Ok(Self(platform::IpcStream::from_std_listener(listener)?))
269 }
270}
271
272impl Stream for IpcStream {
273 type Item = io::Result<Connection>;
274
275 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
276 let this = Pin::into_inner(self);
277 Pin::new(&mut this.0).poll_next(cx).map_ok(Connection)
278 }
279}