1use std::{fs::DirBuilder, path::PathBuf};
2
3use anyhow::Result;
4use tokio::{
5 net::UnixListener,
6 sync::mpsc::{UnboundedReceiver, UnboundedSender},
7};
8use tokio_stream::wrappers::UnixListenerStream;
9
10use crate::IpcStream;
11
12pub const IPC_DIR: &str = "/tmp/lazybar-ipc/";
14
15pub fn init(enabled: bool, bar_name: &str) -> (Result<IpcStream>, String) {
17 let mut final_name = bar_name.to_string();
18 (
19 if enabled && DirBuilder::new().recursive(true).create(IPC_DIR).is_ok()
20 {
21 let (path, idx) = find_path(bar_name);
22
23 if idx > 0 {
24 final_name = format!("{bar_name}({idx})");
25 }
26
27 #[allow(clippy::option_if_let_else)]
29 if let Ok(listener) = UnixListener::bind(path) {
30 let stream = UnixListenerStream::new(listener);
31
32 Ok(Box::pin(stream))
33 } else {
34 Ok(Box::pin(tokio_stream::pending()))
35 }
36 } else {
37 Ok(Box::pin(tokio_stream::pending()))
38 },
39 final_name,
40 )
41}
42
43fn find_path(bar_name: &str) -> (PathBuf, i32) {
44 let mut fmt = format!("{IPC_DIR}{bar_name}");
45 let mut path = PathBuf::from(fmt);
46 let mut idx = 0;
47 while path.exists() {
48 idx += 1;
49 fmt = format!("{IPC_DIR}{bar_name}({idx})");
50 path = PathBuf::from(fmt.as_str());
51 }
52
53 (path, idx)
54}
55
56#[derive(Debug)]
58pub struct ChannelEndpoint<T, U> {
59 pub send: UnboundedSender<T>,
61 pub recv: UnboundedReceiver<U>,
63}
64
65impl<T, U> ChannelEndpoint<T, U> {
66 #[must_use]
68 pub const fn new(
69 send: UnboundedSender<T>,
70 recv: UnboundedReceiver<U>,
71 ) -> Self {
72 Self { send, recv }
73 }
74}
75
76impl<T, U> AsRef<UnboundedSender<T>> for ChannelEndpoint<T, U> {
77 fn as_ref(&self) -> &UnboundedSender<T> {
78 &self.send
79 }
80}
81
82impl<T, U> AsMut<UnboundedSender<T>> for ChannelEndpoint<T, U> {
83 fn as_mut(&mut self) -> &mut UnboundedSender<T> {
84 &mut self.send
85 }
86}
87
88impl<T, U> AsRef<UnboundedReceiver<U>> for ChannelEndpoint<T, U> {
89 fn as_ref(&self) -> &UnboundedReceiver<U> {
90 &self.recv
91 }
92}
93
94impl<T, U> AsMut<UnboundedReceiver<U>> for ChannelEndpoint<T, U> {
95 fn as_mut(&mut self) -> &mut UnboundedReceiver<U> {
96 &mut self.recv
97 }
98}